dynamicweb/static/cms/js/modules/cms.toolbar.js
rscnt bb68c32ba5 new static files.
Signed-off-by: rscnt <rascnt@gmail.com>
2015-06-08 23:26:27 -06:00

512 lines
14 KiB
JavaScript

/*##################################################|*/
/* #CMS# */
(function($) {
// CMS.$ will be passed for $
$(document).ready(function () {
/*!
* Toolbar
* Handles all features related to the toolbar
*/
CMS.Toolbar = new CMS.Class({
implement: [CMS.API.Helpers],
options: {
'preventSwitch': false,
'preventSwitchMessage': 'Switching is disabled.',
'messageDelay': 2000
},
initialize: function (options) {
this.container = $('#cms_toolbar');
this.options = $.extend(true, {}, this.options, options);
this.config = CMS.config;
this.settings = CMS.settings;
// elements
this.body = $('html');
this.toolbar = this.container.find('.cms_toolbar').hide();
this.toolbarTrigger = this.container.find('.cms_toolbar-trigger');
this.navigations = this.container.find('.cms_toolbar-item-navigation');
this.buttons = this.container.find('.cms_toolbar-item-buttons');
this.switcher = this.container.find('.cms_toolbar-item_switch');
this.messages = this.container.find('.cms_messages');
this.screenBlock = this.container.find('.cms_screenblock');
// states
this.click = 'click.cms';
this.timer = function () {};
this.lockToolbar = false;
// setup initial stuff
this._setup();
// setup events
this._events();
},
// initial methods
_setup: function () {
// setup toolbar visibility, we need to reverse the options to set the correct state
(this.settings.toolbar === 'expanded') ? this._showToolbar(0, true) : this._hideToolbar(0, true);
// hide publish button
var publishBtn = $('.cms_btn-publish').parent();
publishBtn.hide();
if($('.cms_btn-publish-active').length) publishBtn.show();
// check if debug is true
if(CMS.config.debug) this._debug();
// check if there are messages and display them
if(CMS.config.messages) this.openMessage(CMS.config.messages);
// check if there are error messages and display them
if(CMS.config.error) this.showError(CMS.config.error);
// enforce open state if user is not logged in but requests the toolbar
if(!CMS.config.auth || CMS.config.settings.version !== this.settings.version) {
this.toggleToolbar(true);
this.settings = this.setSettings(CMS.config.settings);
}
// should switcher indicate that there is an unpublished page?
if(CMS.config.publisher) {
this.openMessage(CMS.config.publisher, 'right');
setInterval(function () {
CMS.$('.cms_toolbar-item_switch').toggleClass('cms_toolbar-item_switch-highlight');
}, this.options.messageDelay);
}
// open sideframe if it was previously opened
if(this.settings.sideframe.url) {
var sideframe = new CMS.Sideframe();
sideframe.open(this.settings.sideframe.url, false);
}
// if there is a screenblock, do some resize magic
if(this.screenBlock.length) this._screenBlock();
// add toolbar ready class to body and fire event
this.body.addClass('cms-ready');
$(document).trigger('cms-ready');
},
_events: function () {
var that = this;
// attach event to the trigger handler
this.toolbarTrigger.bind(this.click, function (e) {
e.preventDefault();
that.toggleToolbar();
});
// attach event to the navigation elements
this.navigations.each(function () {
var item = $(this);
var lists = item.find('li');
var root = 'cms_toolbar-item-navigation';
var hover = 'cms_toolbar-item-navigation-hover';
var disabled = 'cms_toolbar-item-navigation-disabled';
var children = 'cms_toolbar-item-navigation-children';
// remove events from first level
item.find('a').bind(that.click, function (e) {
e.preventDefault();
if($(this).attr('href') !== ''
&& $(this).attr('href') !== '#'
&& !$(this).parent().hasClass(disabled)
&& !$(this).parent().hasClass(disabled)) {
that._delegate($(this));
reset();
return false;
}
});
// handle click states
lists.bind(that.click, function (e) {
e.stopPropagation();
var el = $(this);
// close if el is first item
if(el.parent().hasClass(root) && el.hasClass(hover) || el.hasClass(disabled)) {
reset();
return false;
} else {
reset();
el.addClass(hover);
}
// activate hover selection
item.find('> li').bind('mouseenter', function () {
// cancel if item is already active
if($(this).hasClass(hover)) return false;
$(this).trigger(that.click);
});
// create the document event
$(document).bind(that.click, reset);
});
// attach hover
lists.find('li').bind('mouseenter mouseleave', function () {
var el = $(this);
var parent = el.closest('.cms_toolbar-item-navigation-children').add(el.parents('.cms_toolbar-item-navigation-children'));
var hasChildren = el.hasClass(children) || parent.length;
// do not attach hover effect if disabled
// cancel event if element has already hover class
if(el.hasClass(disabled) || el.hasClass(hover)) return false;
// reset
lists.find('li').removeClass(hover);
// add hover effect
el.addClass(hover);
// handle children elements
if(hasChildren) {
el.find('> ul').show();
// add parent class
parent.addClass(hover);
} else {
lists.find('ul ul').hide();
}
// Remove stale submenus
el.siblings().find('> ul').hide();
});
// fix leave event
lists.find('> ul').bind('mouseleave', function () {
lists.find('li').removeClass(hover);
});
// removes classes and events
function reset() {
lists.removeClass(hover);
lists.find('ul ul').hide();
item.find('> li').unbind('mouseenter');
$(document).unbind(that.click);
}
});
// attach event to the switcher elements
this.switcher.each(function () {
$(this).bind(that.click, function (e) {
e.preventDefault();
that._setSwitcher($(e.currentTarget));
});
});
// attach event for first page publish
this.buttons.each(function () {
var btn = $(this);
// in case the button has a data-rel attribute
if(btn.find('a').attr('data-rel')) {
btn.on('click', function (e) {
e.preventDefault();
that._delegate($(this).find('a'));
})
}
// in case of the publish button
btn.find('.cms_publish-page').bind(that.click, function (e) {
if(!confirm(that.config.lang.publish)) e.preventDefault();
});
});
},
// public methods
toggleToolbar: function (show) {
// overwrite state when provided
if(show) this.settings.toolbar = 'collapsed';
// toggle bar
(this.settings.toolbar === 'collapsed') ? this._showToolbar(200) : this._hideToolbar(200);
},
openMessage: function (msg, dir, delay, error) {
// set toolbar freeze
this._lock(true);
// add content to element
this.messages.find('.cms_messages-inner').html(msg);
// clear timeout
clearTimeout(this.timer);
// determine width
var that = this;
var width = 320;
var height = this.messages.outerHeight(true);
var top = this.toolbar.outerHeight(true);
var close = this.messages.find('.cms_messages-close');
close.hide();
close.bind(this.click, function () {
that.closeMessage();
});
// set top to 0 if toolbar is collapsed
if(this.settings.toolbar === 'collapsed') top = 0;
// do we need to add debug styles?
if(this.config.debug) top = top + 5;
// set correct position and show
this.messages.css('top', -height).show();
// error handling
this.messages.removeClass('cms_messages-error');
if(error) this.messages.addClass('cms_messages-error');
// dir should be left, center, right
dir = dir || 'center';
// set correct direction and animation
switch(dir) {
case 'left':
this.messages.css({
'top': top,
'left': -width,
'right': 'auto',
'margin-left': 0
});
this.messages.animate({ 'left': 0 });
break;
case 'right':
this.messages.css({
'top': top,
'right': -width,
'left': 'auto',
'margin-left': 0
});
this.messages.animate({ 'right': 0 });
break;
default:
this.messages.css({
'left': '50%',
'right': 'auto',
'margin-left': -(width / 2)
});
this.messages.animate({ 'top': top });
}
// cancel autohide if delay is 0
if(delay === 0) {
close.show();
return false
}
// add delay to hide
this.timer = setTimeout(function () {
that.closeMessage();
}, delay || this.options.messageDelay);
},
closeMessage: function () {
this.messages.fadeOut(300);
// unlock toolbar
this._lock(false);
},
openAjax: function (url, post, text, callback, onSuccess) {
var that = this;
// check if we have a confirmation text
var question = (text) ? confirm(text) : true;
// cancel if question has been denied
if(!question) return false;
// set loader
this._loader(true);
$.ajax({
'type': 'POST',
'url': url,
'data': (post) ? JSON.parse(post) : {},
'success': function (response) {
CMS.API.locked = false;
if(callback) {
callback(that, response);
that._loader(false);
} else if(onSuccess) {
CMS.API.Helpers.reloadBrowser(onSuccess, false, true);
} else {
// reload
CMS.API.Helpers.reloadBrowser(false, false, true);
}
},
'error': function (jqXHR) {
CMS.API.locked = false;
that.showError(jqXHR.response + ' | ' + jqXHR.status + ' ' + jqXHR.statusText);
}
});
},
showError: function (msg, reload) {
this.openMessage(msg, 'center', 0, true);
// force reload if param is passed
if(reload) CMS.API.Helpers.reloadBrowser(false, this.options.messageDelay);
},
// private methods
_showToolbar: function (speed, init) {
this.toolbarTrigger.addClass('cms_toolbar-trigger-expanded');
this.toolbar.slideDown(speed);
// animate html
this.body.animate({ 'margin-top': (this.config.debug) ? 35 : 30 }, (init) ? 0 : speed, function () {
$(this).addClass('cms-toolbar-expanded')
});
// set messages top to toolbar height
this.messages.css('top', 31);
// set new settings
this.settings.toolbar = 'expanded';
if(!init) this.settings = this.setSettings(this.settings);
},
_hideToolbar: function (speed, init) {
// cancel if sideframe is active
if(this.lockToolbar) return false;
this.toolbarTrigger.removeClass('cms_toolbar-trigger-expanded');
this.toolbar.slideUp(speed);
// animate html
this.body.removeClass('cms-toolbar-expanded').animate({ 'margin-top': (this.config.debug) ? 5 : 0 }, speed);
// set messages top to 0
this.messages.css('top', 0);
// set new settings
this.settings.toolbar = 'collapsed';
if(!init) this.settings = this.setSettings(this.settings);
},
_setSwitcher: function (el) {
// save local vars
var active = el.hasClass('cms_toolbar-item_switch-active');
var anchor = el.find('a');
var knob = el.find('.cms_toolbar-item_switch-knob');
var duration = 300;
// prevent if switchopstion is passed
if(this.options.preventSwitch) {
this.openMessage(this.options.preventSwitchMessage, 'right');
return false;
}
// determin what to trigger
if(active) {
knob.animate({
'right': anchor.outerWidth(true) - (knob.outerWidth(true) + 2)
}, duration);
// move anchor behind the knob
anchor.css('z-index', 1).animate({
'padding-top': 6,
'padding-right': 14,
'padding-bottom': 4,
'padding-left': 28
}, duration);
} else {
knob.animate({
'left': anchor.outerWidth(true) - (knob.outerWidth(true) + 2)
}, duration);
// move anchor behind the knob
anchor.css('z-index', 1).animate({
'padding-top': 6,
'padding-right': 28,
'padding-bottom': 4,
'padding-left': 14
}, duration);
}
// reload
setTimeout(function () {
window.location.href = anchor.attr('href');
}, duration);
},
_delegate: function (el) {
// save local vars
var target = el.data('rel');
switch(target) {
case 'modal':
var modal = new CMS.Modal({'onClose': el.data('on-close')});
modal.open(el.attr('href'), el.data('name'));
break;
case 'message':
this.openMessage(el.data('text'));
break;
case 'sideframe':
var sideframe = new CMS.Sideframe({'onClose': el.data('on-close')});
sideframe.open(el.attr('href'), true);
break;
case 'ajax':
this.openAjax(el.attr('href'), JSON.stringify(el.data('post')), el.data('text'), null, el.data('on-success'));
break;
default:
window.location.href = el.attr('href');
}
},
_lock: function (lock) {
if(lock) {
this.lockToolbar = true;
// make button look disabled
this.toolbarTrigger.css('opacity', 0.2);
} else {
this.lockToolbar = false;
// make button look disabled
this.toolbarTrigger.css('opacity', 1);
}
},
_loader: function (loader) {
if(loader) {
this.toolbarTrigger.addClass('cms_toolbar-loader');
} else {
this.toolbarTrigger.removeClass('cms_toolbar-loader');
}
},
_debug: function () {
var that = this;
var timeout = 1000;
var timer = function () {};
// bind message event
var debug = this.container.find('.cms_debug-bar');
debug.bind('mouseenter mouseleave', function (e) {
clearTimeout(timer);
if(e.type === 'mouseenter') {
timer = setTimeout(function () {
that.openMessage(that.config.lang.debug);
}, timeout);
}
});
},
_screenBlock: function () {
var interval = 20;
var blocker = this.screenBlock;
var sideframe = $('.cms_sideframe');
// automatically resize screenblock window according to given attributes
$(window).on('resize.cms.screenblock', function () {
var width = $(this).width() - sideframe.width();
blocker.css({
'width': width,
'height': $(window).height()
});
}).trigger('resize');
// set update interval
setInterval(function () {
$(window).trigger('resize.cms.screenblock');
}, interval);
}
});
});
})(CMS.$);