/**
* Widgster plugin.
*/
!function ($) {
"use strict";
// WIDGSTER CLASS DEFINITION
// ======================
var Widgster = function (el, options) {
this.$element = $(el);
this.$collapse = this.$element.find('[data-widgster=collapse]');
this.$expand = this.$element.find('[data-widgster=expand]');
this.$fullscreen = this.$element.find('[data-widgster=fullscreen]');
this.$restore = this.$element.find('[data-widgster=restore]');
this.options = options;
this.collapsed = options.collapsed;
this.fullscreened = options.fullscreened;
this._initHandlers();
if (this.collapsed){
this.collapse(false);
} else {
this.$expand.hide();
}
if (this.fullscreened){
this.fullscreen();
} else {
this.$restore.hide();
}
this.options.autoload && this.load();
var interval = parseInt(this.options.autoload);
if (!isNaN(interval)){
var widgster = this;
this._autoloadInterval = setInterval(function(){
widgster.load();
}, interval)
}
};
Widgster.DEFAULTS = {
collapsed: false,
fullscreened: false,
transitionDuration: 150,
bodySelector: '.body',
showLoader: true,
autoload: false,
loaderTemplate: '
Loading...
',
/**
* provide a way to insert a prompt before removing widget
* @param callback
*/
closePrompt: function(callback){
callback()
}
};
Widgster.prototype.toleft = function(e){
e.preventDefault();
var e = $.Event('toleft.widgster');
this.$element.trigger(e);
if (e.isDefaultPrevented()) return;
const colDiv = this.$element.closest('.col-layer');
if(colDiv.length <= 0) return;
adjustSize(colDiv, false);
return false;
};
Widgster.prototype.toright = function(e){
e.preventDefault();
var e = $.Event('toright.widgster');
this.$element.trigger(e);
if (e.isDefaultPrevented()) return;
const colDiv = this.$element.closest('.col-layer');
if(colDiv.length <= 0) return;
adjustSize(colDiv, true);
return false;
};
function adjustSize(colDiv, increase) {
const proportions = Array.from($('.col-layer'));
let result = [];
let layer = 1;
let sum = 0;
proportions.forEach(current => {
const sizeRegex = /col-lg-(\d+)/;
const match = current.className.match(sizeRegex);
const sizeValue = match ? parseInt(match[1], 10) : 0;
sum += sizeValue;
result.push({
current,
layer
});
if (sum % 12 === 0) {
layer++;
}
});
const colDivItem = result.find(item => item.current === colDiv[0]);
if (!colDivItem) return;
const colDivLayer = colDivItem.layer;
const filteredResult = result.filter(item => item.layer === colDivLayer);
const filteredLength = filteredResult.length;
for (let i = 0; i < filteredLength; i++) {
const left = filteredResult[(i - 1 + filteredLength) % filteredLength];
const right = filteredResult[(i + 1) % filteredLength];
filteredResult[i].left = left.current;
filteredResult[i].right = right.current;
}
if (increase) {
if (canIncrease(colDivItem.current) && canDecrease(colDivItem.right)) {
adjustColSize(colDivItem.right, -1, function() {
adjustColSize(colDivItem.current, 1);
});
}
} else {
if (canDecrease(colDivItem.current) && canIncrease(colDivItem.right)) {
adjustColSize(colDivItem.current, -1, function() {
adjustColSize(colDivItem.right, 1);
});
}
}
}
function canDecrease(node) {
const sizeRegex = /col-lg-(\d+)/;
const match = node.className.match(sizeRegex);
if (!match) {
return false;
}
const size = parseInt(match[1], 10);
return size > 1;
}
function canIncrease(node) {
const sizeRegex = /col-lg-(\d+)/;
const match = node.className.match(sizeRegex);
if (!match) {
return false;
}
const size = parseInt(match[1], 10);
return size < 12;
}
function adjustColSize(node, change, callback) {
const sizeRegex = /col-lg-(\d+)/;
const match = node.className.match(sizeRegex);
if (!match) {
callback && callback();
return;
}
let newSize = parseInt(match[1], 10) + change;
const newWidthPercentage = ((parseInt(match[1], 10) + change) / 12) * 100;
$(node).animate({
width: newWidthPercentage + '%'
}, 200, function() {
node.className = node.className.replace(sizeRegex, `col-lg-${newSize}`);
$(node).css('width', '');
callback && callback();
});
}
Widgster.prototype.collapse = function(animate){
animate = typeof animate == "undefined" ? true : animate;
var e = $.Event('collapse.widgster');
this.$element.trigger(e);
if (e.isDefaultPrevented()) return;
var widgster = this,
duration = animate ? this.options.transitionDuration : 0;
this.$element.find(this.options.bodySelector).slideUp(duration, function(){
widgster.$element.addClass('collapsed');
widgster.$element.trigger($.Event('collapsed.widgster'));
widgster.collapsed = true;
});
this.$collapse.hide();
this.$expand.show();
return false;
};
Widgster.prototype.expand = function(animate){
animate = typeof animate == "undefined" ? true : animate;
var e = $.Event('expand.widgster');
this.$element.trigger(e);
if (e.isDefaultPrevented()) return;
var widgster = this,
duration = animate ? this.options.transitionDuration : 0;
this.$element.find(this.options.bodySelector).slideDown(duration, function(){
widgster.$element.removeClass('collapsed');
widgster.$element.trigger($.Event('expanded.widgster'));
widgster.collapsed = false;
});
this.$collapse.show();
this.$expand.hide();
return false;
};
Widgster.prototype.close = function(){
this.options.closePrompt && this.options.closePrompt($.proxy(this._doClose, this));
return false;
};
Widgster.prototype.load = function(){
var e = $.Event('load.widgster');
this.$element.trigger(e);
if (e.isDefaultPrevented()) return;
var widgster = this;
this.$element.find(this.options.bodySelector).load(this.options.load, function(responseText, textStatus, xhr){
widgster.expand();
widgster.options.showLoader && widgster._hideLoader();
widgster.$element.trigger($.Event('loaded.widgster', {
responseText: responseText,
textStatus: textStatus,
xhr: xhr
}))
});
this.options.showLoader && this._showLoader();
return false;
};
Widgster.prototype.fullscreen = function(){
var e = $.Event('fullscreen.widgster');
this.$element.trigger(e);
if (e.isDefaultPrevented()) return;
this.$element.css({
position: 'fixed',
top: 0,
right: 0,
bottom: 0,
left: 0,
margin: 0,
'z-index': 10000
});
$('body').css('overflow', 'hidden');
this.wasCollapsed = this.collapsed;
this.expand(false);
this.$fullscreen.hide();
this.$restore.show();
this.$collapse.hide(); this.$expand.hide();
this.$element.addClass('fullscreened');
this.$element.addClass('modalDarkBack');
this.$element.trigger($.Event('fullscreened.widgster'));
return false;
};
Widgster.prototype.restore = function(){
var e = $.Event('restore.widgster');
this.$element.trigger(e);
if (e.isDefaultPrevented()) return;
this.$element.css({
position: '',
top: '',
right: '',
bottom: '',
left: '',
margin: '',
'z-index': ''
});
$('body').css('overflow', '');
this.$fullscreen.show();
this.$restore.hide();
if (this.collapsed){
this.$collapse.hide(); this.$expand.show();
} else {
this.$collapse.show(); this.$expand.hide();
}
this.wasCollapsed && this.collapse(false);
this.$element.removeClass('fullscreened');
this.$element.removeClass('modalDarkBack');
this.$element.trigger($.Event('restored.widgster'));
return false;
};
Widgster.prototype._doClose = function(){
//could have been remove.widgster, but http://bugs.jquery.com/ticket/14600
var e = $.Event('close.widgster');
this.$element.trigger(e);
if (e.isDefaultPrevented()) return;
$('body').css('overflow', '');
this.$element.detach();
e = $.Event('closed.widgster', {$element: this.$element});
this.$element.trigger(e);
};
Widgster.prototype._showLoader = function(){
var $body = this.$element.find(this.options.bodySelector);
this.$loaderWrap = this.$element.find('.widgster-loader-wrap');
//create loader html if does not exist
if (this.$loaderWrap.length == 0){
this.$loaderWrap = $('');
this.$element.append(this.$loaderWrap);
}
this.$loaderWrap.html(this.options.loaderTemplate);
this.$loaderWrap.css({
'margin-top': $body.position().top
});
if (!this.collapsed){
$body.fadeTo(this.options.transitionDuration, 0);
this.$loaderWrap.fadeIn(this.options.transitionDuration)
}
};
Widgster.prototype._hideLoader = function(){
this.$loaderWrap.fadeOut(this.options.transitionDuration);
this.$element.find(this.options.bodySelector).fadeTo(this.options.transitionDuration, 1);
};
/**
* Attach all required widgster functions to data-widgster elements.
* @private
*/
Widgster.prototype._initHandlers = function(){
this.$element.on('click.toleft.widgster', '[data-widgster=toleft]', $.proxy(this.toleft, this));
this.$element.on('click.toright.widgster', '[data-widgster=toright]', $.proxy(this.toright, this));
this.$element.on('click.collapse.widgster', '[data-widgster=collapse]', $.proxy(this.collapse, this));
this.$element.on('click.expand.widgster', '[data-widgster=expand]', $.proxy(this.expand, this));
this.$element.on('click.close.widgster', '[data-widgster=close]', $.proxy(this.close, this));
this.$element.on('click.load.widgster', '[data-widgster=load]', $.proxy(this.load, this));
this.$element.on('click.fullscreen.widgster', '[data-widgster=fullscreen]', $.proxy(this.fullscreen, this));
this.$element.on('click.restore.widgster', '[data-widgster=restore]', $.proxy(this.restore, this));
};
// NAMESPACED DATA ATTRIBUTES
// =======================
function getNamespacedData(namespace, data){
var namespacedData = {};
for (var key in data){
// key starts with namespace
if (key.slice(0, namespace.length) == namespace){
var namespacedKey = key.slice(namespace.length, key.length);
namespacedKey = namespacedKey.charAt(0).toLowerCase() + namespacedKey.slice(1);
namespacedData[namespacedKey] = data[key];
}
}
return namespacedData;
}
// WIDGSTER PLUGIN DEFINITION
// =======================
$.fn.widgster = function (option) {
return this.each(function () {
var $this = $(this);
var data = $this.data('widgster');
var options = $.extend({}, Widgster.DEFAULTS, getNamespacedData('widgster', $this.data()), typeof option == 'object' && option);
if (!data) $this.data('widgster', new Widgster(this, options));
if (typeof option == 'string') data[option]();
})
};
$.fn.widgster.Constructor = Widgster;
}(window.jQuery);