/** * 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);