/* * AdminPanels.js was created solely for this theme. * Author: AdminDesigns.com * */ ; (function($, window, document, undefined) { // Plugin definition. $.fn.adminpanel = function(options) { // Default plugin options. var defaults = { grid: '.admin-grid', draggable: false, mobile: false, preserveGrid: false, onPanel: function() { console.log('callback:', 'onPanel'); }, onStart: function() { console.log('callback:', 'onStart'); }, onSave: function() { console.log('callback:', 'onSave'); }, onDrop: function() { // An "onSave" callback will also be called if // the drop also changes the elements DOM position console.log('callback:', 'onDrop'); }, onFinish: function() { console.log('callback:', 'onFinish'); }, }; // Extend default options. var options = $.extend({}, defaults, options); // Variables. var plugin = $(this); var pluginID = plugin.attr('id'); var pluginGrid = options.grid; var dragSetting = options.draggable; var mobileSetting = options.mobile; var preserveSetting = options.preserveGrid; var panels = plugin.find('.panel'); // HTML5 LocalStorage Keys var settingsKey = 'panel-settings_' + location.pathname; var positionsKey = 'panel-positions_' + location.pathname; // HTML5 LocalStorage Gets var settingsGet = localStorage.getItem(settingsKey); var positionsGet = localStorage.getItem(positionsKey); // Control Menu Click Handler $('.panel').on('click', '.panel-controls > a', function(e) { e.preventDefault(); // if a panel is being dragged disable menu clicks if ($('body.ui-drag-active').length) { return; } // determine appropriate event response methods.controlHandlers.call(this, options); }); var methods = { init: function(options) { var This = $(this); // onStart callback if (typeof options.onStart == 'function') { options.onStart(); } // Check onload to see if positions key is empty if (!positionsGet) { localStorage.setItem(positionsKey, methods.findPositions()); } else { methods.setPositions(); } // Check onload to see if settings key is empty if (!settingsGet) { localStorage.setItem(settingsKey, methods.modifySettings()); } // Helper function that adds unique ID's to grid elements $(pluginGrid).each(function(i, e) { $(e).attr('id', 'grid-' + i); }); // Check if empty columns should be preserved using an invisible panel if (preserveSetting) { var Panel = "
"; $(pluginGrid).each(function(i, e) { $(e).append(Panel); }); } // Prep admin panel/container prior to menu creation methods.createControls(options); // Create Mobile Menus methods.createMobileControls(options); // Loop through settings key and apply options to panels methods.applySettings(); if (dragSetting === true) { // Activate jQuery sortable on declared grids/panels plugin.sortable({ items: plugin.find('.panel:not(".sort-disable")'), connectWith: pluginGrid, cursor: 'default', revert: 250, handle: '.panel-heading', opacity: 1, delay: 100, tolerance: "pointer", scroll: true, placeholder: 'panel-placeholder', forcePlaceholderSize: true, forceHelperSize: true, start: function(e, ui) { $('body').addClass('ui-drag-active'); ui.placeholder.height(ui.helper.outerHeight() - 4); }, beforeStop: function() { // onMove callback if (typeof options.onDrop == 'function') { options.onDrop(); } }, stop: function() { $('body').removeClass('ui-drag-active'); }, update: function(event, ui) { // toggle loading indicator methods.toggleLoader(); // store the positions of the plugins */ methods.updatePositions(options); } }); } // onFinish callback if (typeof options.onFinish == 'function') { options.onFinish(); } }, createMobileControls: function(options) { var controls = panels.find('.panel-controls'); var arr = {}; $.each(controls, function(i, e) { var This = $(e); var ID = $(e).parents('.panel').attr('id'); var controlW = This.width(); var titleW = This.siblings('.panel-title').width(); var headingW = This.parent('.panel-heading').width(); var mobile = (controlW + titleW); arr[ID] = mobile; }); console.log(arr) $.each(arr, function(i, e) { var This = $('#' + i); var headingW = This.width() - 75; var controls = This.find('.panel-controls'); if (mobileSetting === true || headingW < e) { This.addClass('mobile-controls'); var options = { html: true, placement: "left", content: function(e) { var Content = $(this).clone(); return Content; }, template: '' } controls.popover(options); } else { controls.removeClass('mobile-controls'); } }); // Toggle mobile controls menu open on click $('.mobile-controls .panel-heading > .panel-controls').on('click', function() { $(this).toggleClass('panel-controls-open'); }); }, applySettings: function(options) { // Variables. var obj = this; var localSettings = localStorage.getItem(settingsKey); var parseSettings = JSON.parse(localSettings); // Possible panel colors var panelColors = "panel-primary panel-success panel-info panel-warning panel-danger panel-alert panel-system panel-dark panel-default"; // Pull localstorage obj, parse the data, and then loop // through each panel and apply its given settings $.each(parseSettings, function(i, e) { $.each(e, function(i, e) { var panelID = e['id']; var panelTitle = e['title']; var panelCollapsed = e['collapsed']; var panelHidden = e['hidden']; var panelColor = e['color']; var Target = $('#' + panelID); if (panelTitle) { Target.children('.panel-heading').find('.panel-title').text(panelTitle); } if (panelCollapsed === 1) { Target.addClass('panel-collapsed') .children('.panel-body, .panel-menu, .panel-footer').hide(); } if (panelColor) { Target.removeClass(panelColors).addClass(panelColor).attr('data-panel-color', panelColor); } if (panelHidden === 1) { Target.addClass('panel-hidden').hide().remove(); } }); }); }, createControls: function(options) { // List of available panel controls var panelControls = ''; var panelTitle = ''; var panelColor = ''; var panelCollapse = ''; var panelFullscreen = ''; var panelRemove = ''; var panelCallback = ''; var panelDock = ''; var panelExpose = ''; var panelLoader = ''; panels.each(function(i, e) { var This = $(e); // Create panel menu container var panelHeader = This.children('.panel-heading'); $(panelControls).appendTo(panelHeader); // Check panel for settings specific attr. Use this // value to determine if menu item should be displayed var title = This.attr('data-panel-title'); var color = This.attr('data-panel-color'); var collapse = This.attr('data-panel-collapse'); var fullscreen = This.attr('data-panel-fullscreen'); var remove = This.attr('data-panel-remove'); var callback = This.attr('data-panel-callback'); var paneldock = This.attr('data-panel-dockable'); var expose = This.attr('data-panel-expose'); var loader = This.attr('data-panel-loader'); // attach loading indicator like any other button if (!loader) { // Create button var panelMenu = panelHeader.find('.panel-controls'); $(panelLoader).appendTo(panelMenu); } // Upcoming feature, not currently implemented if (expose) { // Create button var panelMenu = panelHeader.find('.panel-controls'); $(panelExpose).appendTo(panelMenu); } // Upcoming feature, not currently implemented if (paneldock) { // Create button var panelMenu = panelHeader.find('.panel-controls'); $(panelDock).appendTo(panelMenu); } // callback attr must be set true, else icon hidden if (callback) { // Create button var panelMenu = panelHeader.find('.panel-controls'); $(panelCallback).appendTo(panelMenu); } if (!remove) { // Create button var panelMenu = panelHeader.find('.panel-controls'); $(panelRemove).appendTo(panelMenu); } if (!title) { // Create button var panelMenu = panelHeader.find('.panel-controls'); $(panelTitle).appendTo(panelMenu); } if (!color) { var panelMenu = panelHeader.find('.panel-controls'); $(panelColor).appendTo(panelMenu); } if (!collapse) { // Create button var panelMenu = panelHeader.find('.panel-controls'); $(panelCollapse).appendTo(panelMenu); } if (!fullscreen) { // Create button var panelMenu = panelHeader.find('.panel-controls'); $(panelFullscreen).appendTo(panelMenu); } }); }, controlHandlers: function(e) { var This = $(this); // Control button indentifiers var action = This.attr('class'); var panel = This.parents('.panel'); // Panel header variables var panelHeading = panel.children('.panel-heading'); var panelTitle = panel.find('.panel-title'); // Edit Title definition var panelEditTitle = function() { // function for toggling the editbox menu var toggleBox = function() { var panelEditBox = panel.find('.panel-editbox'); panelEditBox.slideToggle('fast', function() { panel.toggleClass('panel-editbox-open'); // Save settings to key if editbox is being closed if (!panel.hasClass('panel-editbox-open')) { panelTitle.text(panelEditBox.children('input').val()); methods.updateSettings(options); } }); }; // If editbox not found, create one and attach handlers if (!panel.find('.panel-editbox').length) { var editBox = '
'; panelHeading.after(editBox); // New editbox container var panelEditBox = panel.find('.panel-editbox'); // Update panel title on key up panelEditBox.children('input').on('keyup', function() { panelTitle.text(panelEditBox.children('input').val()); }); // Save panel title on enter key press panelEditBox.children('input').on('keypress', function(e) { if (e.which == 13) { toggleBox(); } }); // Toggle editbox toggleBox(); } else { // If found simply toggle the menu toggleBox(); } }; // Panel color definition var panelColor = function() { // Create an editbox if one is not found if (!panel.find('.panel-colorbox').length) { var colorBox = '
' panelHeading.after(colorBox); } // Editbox container var panelColorBox = panel.find('.panel-colorbox'); // Update panel contextual color on click panelColorBox.on('click', '> span', function(e) { var dataColor = $(this).data('panel-color'); var altColors = 'panel-primary panel-info panel-success panel-warning panel-danger panel-alert panel-system panel-dark panel-default panel-white'; panel.removeClass(altColors).addClass(dataColor).data('panel-color', dataColor) methods.updateSettings(options); }); // Toggle elements visability and '.panel-editbox' class // If the box is being closed update settings key panelColorBox.slideToggle('fast', function() { panel.toggleClass('panel-colorbox-open'); }); }; // Collapse definition var panelCollapse = function() { // Toggle class panel.toggleClass('panel-collapsed'); // Toggle elements visability panel.children('.panel-body, .panel-menu, .panel-footer').slideToggle('fast', function() { methods.updateSettings(options); }); }; // Fullscreen definition var panelFullscreen = function() { // If fullscreen mode is active, remove class and enable panel sorting if ($('body.panel-fullscreen-active').length) { $('body').removeClass('panel-fullscreen-active'); panel.removeClass('panel-fullscreen'); if (dragSetting === true) { plugin.sortable("enable"); } } // if not active add fullscreen classes and disable panel sorting else { $('body').addClass('panel-fullscreen-active'); panel.addClass('panel-fullscreen'); if (dragSetting === true) { plugin.sortable("disable"); } } // Hide any open mobile menus or popovers $('.panel-controls').removeClass('panel-controls-open'); $('.popover').popover('hide'); // Trigger a global window resize to resize any plugins // the fullscreened content might contain. setTimeout(function() { $(window).trigger('resize'); }, 100); }; // Remove definition var panelRemove = function() { // check for Bootbox plugin - should be in core if (bootbox.confirm) { bootbox.confirm("Are You Sure?!", function(e) { // e returns true if user clicks "accept" // false if "cancel" or dismiss icon are clicked if (e) { // Timeout simply gives the user a second for the modal to // fade away so they can visibly see the panel disappear setTimeout(function() { panel.addClass('panel-removed').hide(); methods.updateSettings(options); }, 200); } }); } else { panel.addClass('panel-removed').hide(); methods.updateSettings(options); } }; // Remove definition var panelCallback = function() { if (typeof options.onPanel == 'function') { options.onPanel(); } }; // Expose.js definition var panelExpose = function() { // Code removed, feature will be added to next update // once all of the dynamic/responsive aspects of resizing // an exposed panel are worked out }; // Responses if ($(this).hasClass('panel-control-collapse')) { panelCollapse(); } if ($(this).hasClass('panel-control-title')) { panelEditTitle(); } if ($(this).hasClass('panel-control-color')) { panelColor(); } if ($(this).hasClass('panel-control-fullscreen')) { panelFullscreen(); } if ($(this).hasClass('panel-control-remove')) { panelRemove(); } if ($(this).hasClass('panel-control-callback')) { panelCallback(); } if ($(this).hasClass('panel-control-expose')) { panelExpose(); } if ($(this).hasClass('panel-control-dockable')) { return } if ($(this).hasClass('panel-control-loader')) { return; } // Toggle Loader indicator in response to action methods.toggleLoader.call(this); }, toggleLoader: function(options) { var This = $(this); var panel = This.parents('.panel'); // Add loader to panel panel.addClass('panel-loader-active'); // Remove loader after specified duration setTimeout(function() { panel.removeClass('panel-loader-active'); }, 650); }, modifySettings: function(options) { // Settings obj var settingsArr = []; // Determine settings of each panel. panels.each(function(i, e) { var This = $(e); var panelObj = {}; // Settings variables. var panelID = This.attr('id'); var panelTitle = This.children('.panel-heading').find('.panel-title').text(); var panelCollapsed = (This.hasClass('panel-collapsed') ? 1 : 0); var panelHidden = (This.is(':hidden') ? 1 : 0); var panelColor = This.data('panel-color'); panelObj['id'] = This.attr('id'); panelObj['title'] = This.children('.panel-heading').find('.panel-title').text(); panelObj['collapsed'] = (This.hasClass('panel-collapsed') ? 1 : 0); panelObj['hidden'] = (This.is(':hidden') ? 1 : 0); panelObj['color'] = (panelColor ? panelColor : null); settingsArr.push({ 'panel': panelObj }); }); var checkedSettings = JSON.stringify(settingsArr); // Log Results // console.log('Key contains: ', checkedSettings); // return panel positions array return checkedSettings; }, findPositions: function(options) { var grids = plugin.find(pluginGrid); var gridsArr = []; // Determine panels present. grids.each(function(index, ele) { var panels = $(ele).find('.panel'); var panelArr = []; $(ele).attr('id', 'grid-' + index); panels.each(function(i, e) { var panelID = $(e).attr('id'); panelArr.push(panelID); }); gridsArr[index] = panelArr; }); var checkedPosition = JSON.stringify(gridsArr); // return panel positions array return checkedPosition; }, setPositions: function(options) { // Variables var obj = this; var localPositions = localStorage.getItem(positionsKey); var parsePosition = JSON.parse(localPositions); // Pull localstorage obj, parse the data, and then loop // through each panel and set its position $(pluginGrid).each(function(i, e) { var rowID = $(e) $.each(parsePosition[i], function(i, ele) { $('#' + ele).appendTo(rowID); }); }); }, updatePositions: function(options) { localStorage.setItem(positionsKey, methods.findPositions()); // onSave callback if (typeof options.onSave == 'function') { options.onSave(); } }, updateSettings: function(options) { localStorage.setItem(settingsKey, methods.modifySettings()); // onSave callback if (typeof options.onSave == 'function') { options.onSave(); } } } // Plugin implementation return this.each(function() { methods.init.call(plugin, options); }); }; })(jQuery, window, document);