diff --git a/Gruntfile.js b/Gruntfile.js index 5b43551fcc1..23b4eda9972 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -12,7 +12,7 @@ module.exports = function (grunt) { // jshint ignore:line }, js : { // Compile js files upon saving - files: ['build/js/*.js', 'dist/js/app.js'], + files: ['build/js/*.js'], tasks: ['js', 'notify:js'] }, skins: { @@ -117,7 +117,6 @@ module.exports = function (grunt) { // jshint ignore:line }, production: { files: { - 'dist/js/app.min.js' : ['dist/js/app.js'], 'dist/js/adminlte.min.js': ['dist/js/adminlte.js'] } } @@ -147,13 +146,14 @@ module.exports = function (grunt) { // jshint ignore:line }, dist : { src : [ + 'build/js/BoxRefresh.js', + 'build/js/BoxWidget.js', + 'build/js/ControlSidebar.js', + 'build/js/DirectChat.js', 'build/js/Layout.js', 'build/js/PushMenu.js', - 'build/js/Tree.js', - 'build/js/ControlSidebar.js', - 'build/js/BoxWidget.js', 'build/js/TodoList.js', - 'build/js/DirectChat.js' + 'build/js/Tree.js' ], dest: 'dist/js/adminlte.js' } diff --git a/dist/js/adminlte.js b/dist/js/adminlte.js index 3c6ed372cc3..533a8433df0 100644 --- a/dist/js/adminlte.js +++ b/dist/js/adminlte.js @@ -17,144 +17,81 @@ if (typeof jQuery === 'undefined') { throw new Error('AdminLTE requires jQuery') } -/* Layout() - * ======== - * Implements AdminLTE layout. - * Fixes the layout height in case min-height fails. +/* BoxRefresh() + * ========= + * Adds AJAX content control to a box. * - * @usage activated automatically upon window load. - * Configure any options by passing data-option="value" - * to the body tag. + * @Usage: $('#my-box').boxRefresh(options) + * or add [data-widget="box-refresh"] to the box element + * Pass any option as data-option="value" */ +function ($) { 'use strict' - var DataKey = 'lte.layout' + var DataKey = 'lte.boxrefresh' var Default = { - slimscroll : true, - resetHeight: true + source : '', + params : {}, + trigger : '.refresh-btn', + content : '.box-body', + loadInContent : true, + responseType : '', + overlayTemplate: '
', + onLoadStart : function () { + }, + onLoadDone : function (response) { + return response + } } var Selector = { - wrapper : '.wrapper', - contentWrapper: '.content-wrapper', - layoutBoxed : '.layout-boxed', - mainFooter : '.main-footer', - mainHeader : '.main-header', - sidebar : '.sidebar', - controlSidebar: '.control-sidebar', - fixed : '.fixed', - sidebarMenu : '.sidebar-menu', - logo : '.main-header .logo' - } - - var ClassName = { - fixed : 'fixed', - holdTransition: 'hold-transition' - } - - var Layout = function (options) { - this.options = options - this.bindedResize = false - this.activate() + data: '[data-widget="box-refresh"]' } - Layout.prototype.activate = function () { - this.fix() - this.fixSidebar() - - $('body').removeClass(ClassName.holdTransition) + // BoxRefresh Class Definition + // ========================= + var BoxRefresh = function (element, options) { + this.element = element + this.options = options + this.$overlay = $(options.overlay) - if (this.options.resetHeight) { - $('body, html, ' + Selector.wrapper).css({ - 'height' : 'auto', - 'min-height': '100%' - }) + if (options.source === '') { + throw new Error('Source url was not defined. Please specify a url in your BoxRefresh source option.') } - if (!this.bindedResize) { - $(window).resize(function () { - this.fix() - this.fixSidebar() + this._setUpListeners() + this.load() + } - $(Selector.logo + ', ' + Selector.sidebar).one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function () { - this.fix() - this.fixSidebar() - }.bind(this)) - }.bind(this)) + BoxRefresh.prototype.load = function () { + this._addOverlay() + this.options.onLoadStart.call($(this)) - this.bindedResize = true - } + $.get(this.options.source, this.options.params, function (response) { + if (this.options.loadInContent) { + $(this.options.content).html(response) + } + this.options.onLoadDone.call($(this), response) + this._removeOverlay() + }.bind(this), this.options.responseType !== '' && this.options.responseType) + } - $(Selector.sidebarMenu).on('expanded.tree', function () { - this.fix() - this.fixSidebar() - }.bind(this)) + // Private - $(Selector.sidebarMenu).on('collapsed.tree', function () { - this.fix() - this.fixSidebar() + BoxRefresh.prototype._setUpListeners = function () { + $(this.element).on('click', Selector.trigger, function (event) { + if (event) event.preventDefault() + this.load() }.bind(this)) } - Layout.prototype.fix = function () { - // Remove overflow from .wrapper if layout-boxed exists - $(Selector.layoutBoxed + ' > ' + Selector.wrapper).css('overflow', 'hidden') - - // Get window height and the wrapper height - var footerHeight = $(Selector.mainFooter).outerHeight() || 0 - var neg = $(Selector.mainHeader).outerHeight() + footerHeight - var windowHeight = $(window).height() - var sidebarHeight = $(Selector.sidebar).height() || 0 - - // Set the min-height of the content and sidebar based on - // the height of the document. - if ($('body').hasClass(ClassName.fixed)) { - $(Selector.contentWrapper).css('min-height', windowHeight - footerHeight) - } else { - var postSetHeight - - if (windowHeight >= sidebarHeight) { - $(Selector.contentWrapper).css('min-height', windowHeight - neg) - postSetHeight = windowHeight - neg - } else { - $(Selector.contentWrapper).css('min-height', sidebarHeight) - postSetHeight = sidebarHeight - } - - // Fix for the control sidebar height - var $controlSidebar = $(Selector.controlSidebar) - if (typeof $controlSidebar !== 'undefined') { - if ($controlSidebar.height() > postSetHeight) - $(Selector.contentWrapper).css('min-height', $controlSidebar.height()) - } - } + BoxRefresh.prototype._addOverlay = function () { + $(this.element).append(this.$overlay) } - Layout.prototype.fixSidebar = function () { - // Make sure the body tag has the .fixed class - if (!$('body').hasClass(ClassName.fixed)) { - if (typeof $.fn.slimScroll !== 'undefined') { - $(Selector.sidebar).slimScroll({ destroy: true }).height('auto') - } - return - } - - // Enable slimscroll for fixed layout - if (this.options.slimscroll) { - if (typeof $.fn.slimScroll !== 'undefined') { - // Destroy if it exists - $(Selector.sidebar).slimScroll({ destroy: true }).height('auto') - - // Add slimscroll - $(Selector.sidebar).slimScroll({ - height: ($(window).height() - $(Selector.mainHeader).height()) + 'px', - color : 'rgba(0,0,0,0.2)', - size : '3px' - }) - } - } + BoxRefresh.prototype._removeOverlay = function () { + $(this.element).remove(this.$overlay) } // Plugin Definition @@ -165,12 +102,12 @@ throw new Error('AdminLTE requires jQuery') var data = $this.data(DataKey) if (!data) { - var options = $.extend({}, Default, $this.data(), typeof option === 'object' && option) - $this.data(DataKey, (data = new Layout(options))) + var options = $.extend({}, Default, $this.data(), typeof option == 'object' && option) + $this.data(DataKey, (data = new BoxRefresh($this, options))) } - if (typeof option === 'string') { - if (typeof data[option] === 'undefined') { + if (typeof data == 'string') { + if (typeof data[option] == 'undefined') { throw new Error('No method named ' + option) } data[option]() @@ -178,311 +115,147 @@ throw new Error('AdminLTE requires jQuery') }) } - var old = $.fn.layout + var old = $.fn.boxRefresh - $.fn.layout = Plugin - $.fn.layout.Constuctor = Layout + $.fn.boxRefresh = Plugin + $.fn.boxRefresh.Constructor = BoxRefresh - // No conflict mode + // No Conflict Mode // ================ - $.fn.layout.noConflict = function () { - $.fn.layout = old + $.fn.boxRefresh.noConflict = function () { + $.fn.boxRefresh = old return this } - // Layout DATA-API - // =============== + // BoxRefresh Data API + // ================= $(window).on('load', function () { - Plugin.call($('body')) + $(Selector.data).each(function () { + Plugin.call($(this)) + }) }) + }(jQuery) -/* PushMenu() - * ========== - * Adds the push menu functionality to the sidebar. +/* BoxWidget() + * ====== + * Adds box widget functions to boxes. * - * @usage: $('.btn').pushMenu(options) - * or add [data-toggle="push-menu"] to any button - * Pass any option as data-option="value" + * @Usage: $('.my-box').boxWidget(options) + * This plugin auto activates on any element using the `.box` class + * Pass any option as data-option="value" */ +function ($) { 'use strict' - var DataKey = 'lte.pushmenu' + var DataKey = 'lte.boxwidget' var Default = { - collapseScreenSize : 767, - expandOnHover : false, - expandTransitionDelay: 200 + animationSpeed : 500, + collapseTrigger: '[data-widget="collapse"]', + removeTrigger : '[data-widget="remove"]', + collapseIcon : 'fa-minus', + expandIcon : 'fa-plus', + removeIcon : 'fa-times' } var Selector = { - collapsed : '.sidebar-collapse', - open : '.sidebar-open', - mainSidebar : '.main-sidebar', - contentWrapper: '.content-wrapper', - searchInput : '.sidebar-form .form-control', - button : '[data-toggle="push-menu"]', - mini : '.sidebar-mini', - expanded : '.sidebar-expanded-on-hover', - layoutFixed : '.fixed' + data : '.box', + collapsed: '.collapsed-box', + body : '.box-body', + footer : '.box-footer', + tools : '.box-tools' } var ClassName = { - collapsed : 'sidebar-collapse', - open : 'sidebar-open', - mini : 'sidebar-mini', - expanded : 'sidebar-expanded-on-hover', - expandFeature: 'sidebar-mini-expand-feature', - layoutFixed : 'fixed' + collapsed: 'collapsed-box' } var Event = { - expanded : 'expanded.pushMenu', - collapsed: 'collapsed.pushMenu' + collapsed: 'collapsed.boxwidget', + expanded : 'expanded.boxwidget', + removed : 'removed.boxwidget' } - // PushMenu Class Definition - // ========================= - var PushMenu = function (options) { + // BoxWidget Class Definition + // ===================== + var BoxWidget = function (element, options) { + this.element = element this.options = options - this.init() - } - - PushMenu.prototype.init = function () { - if (this.options.expandOnHover - || ($('body').is(Selector.mini + Selector.layoutFixed))) { - this.expandOnHover() - $('body').addClass(ClassName.expandFeature) - } - - $(Selector.contentWrapper).click(function () { - // Enable hide menu when clicking on the content-wrapper on small screens - if ($(window).width() <= this.options.collapseScreenSize && $('body').hasClass(ClassName.open)) { - this.close() - } - }.bind(this)) - // __Fix for android devices - $(Selector.searchInput).click(function (e) { - e.stopPropagation() - }) + this._setUpListeners() } - PushMenu.prototype.toggle = function () { - var windowWidth = $(window).width() - var isOpen = !$('body').hasClass(ClassName.collapsed) - - if (windowWidth <= this.options.collapseScreenSize) { - isOpen = $('body').hasClass(ClassName.open) - } + BoxWidget.prototype.toggle = function () { + var isOpen = !$(this.element).is(Selector.collapsed) - if (!isOpen) { - this.open() + if (isOpen) { + this.collapse() } else { - this.close() + this.expand() } } - PushMenu.prototype.open = function () { - var windowWidth = $(window).width() + BoxWidget.prototype.expand = function () { + var expandedEvent = $.Event(Event.expanded) + var collapseIcon = this.options.collapseIcon + var expandIcon = this.options.expandIcon - if (windowWidth > this.options.collapseScreenSize) { - $('body').removeClass(ClassName.collapsed) - .trigger($.Event(Event.expanded)) - } - else { - $('body').addClass(ClassName.open) - .trigger($.Event(Event.expanded)) - } - } + $(this.element).removeClass(ClassName.collapsed) - PushMenu.prototype.close = function () { - var windowWidth = $(window).width() - if (windowWidth > this.options.collapseScreenSize) { - $('body').addClass(ClassName.collapsed) - .trigger($.Event(Event.collapsed)) - } else { - $('body').removeClass(ClassName.open + ' ' + ClassName.collapsed) - .trigger($.Event(Event.collapsed)) - } - } - - PushMenu.prototype.expandOnHover = function () { - $(Selector.mainSidebar).hover(function () { - if ($('body').is(Selector.mini + Selector.collapsed) - && $(window).width() > this.options.collapseScreenSize) { - this.expand() - } - }.bind(this), function () { - if ($('body').is(Selector.expanded)) { - this.collapse() - } - }.bind(this)) - } - - PushMenu.prototype.expand = function () { - setTimeout(function () { - $('body').removeClass(ClassName.collapsed) - .addClass(ClassName.expanded) - }, this.options.expandTransitionDelay) - } - - PushMenu.prototype.collapse = function () { - setTimeout(function () { - $('body').removeClass(ClassName.expanded) - .addClass(ClassName.collapsed) - }, this.options.expandTransitionDelay) - } - - // PushMenu Plugin Definition - // ========================== - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data(DataKey) - - if (!data) { - var options = $.extend({}, Default, $this.data(), typeof option == 'object' && option) - $this.data(DataKey, (data = new PushMenu(options))) - } - - if (option == 'toggle') data.toggle() - }) - } - - var old = $.fn.pushMenu - - $.fn.pushMenu = Plugin - $.fn.pushMenu.Constructor = PushMenu - - // No Conflict Mode - // ================ - $.fn.pushMenu.noConflict = function () { - $.fn.pushMenu = old - return this - } - - // Data API - // ======== - $(document).on('click', Selector.button, function (e) { - e.preventDefault() - Plugin.call($(this), 'toggle') - }) - $(window).on('load', function () { - Plugin.call($(Selector.button)) - }) -}(jQuery) - - -/* Tree() - * ====== - * Converts a nested list into a multilevel - * tree view menu. - * - * @Usage: $('.my-menu').tree(options) - * or add [data-widget="tree"] to the ul element - * Pass any option as data-option="value" - */ -+function ($) { - 'use strict' - - var DataKey = 'lte.tree' - - var Default = { - animationSpeed: 500, - accordion : true, - followLink : false, - trigger : '.treeview a' - } - - var Selector = { - tree : '.tree', - treeview : '.treeview', - treeviewMenu: '.treeview-menu', - open : '.menu-open, .active', - li : 'li', - data : '[data-widget="tree"]', - active : '.active' - } - - var ClassName = { - open: 'menu-open', - tree: 'tree' - } - - var Event = { - collapsed: 'collapsed.tree', - expanded : 'expanded.tree' - } - - // Tree Class Definition - // ===================== - var Tree = function (element, options) { - this.element = element - this.options = options - - $(this.element).addClass(ClassName.tree) - - $(Selector.treeview + Selector.active, this.element).addClass(ClassName.open) - - this._setUpListeners() - } - - Tree.prototype.toggle = function (link, event) { - var treeviewMenu = link.next(Selector.treeviewMenu) - var parentLi = link.parent() - var isOpen = parentLi.hasClass(ClassName.open) - - if (!parentLi.is(Selector.treeview)) { - return - } - - if (!this.options.followLink || link.attr('href') == '#') { - event.preventDefault() - } + $(this.element) + .find(Selector.tools) + .find('.' + expandIcon) + .removeClass(expandIcon) + .addClass(collapseIcon) - if (isOpen) { - this.collapse(treeviewMenu, parentLi) - } else { - this.expand(treeviewMenu, parentLi) - } + $(this.element).find(Selector.body + ', ' + Selector.footer) + .slideDown(this.options.animationSpeed, function () { + $(this.element).trigger(expandedEvent) + }.bind(this)) } - Tree.prototype.expand = function (tree, parent) { - var expandedEvent = $.Event(Event.expanded) + BoxWidget.prototype.collapse = function () { + var collapsedEvent = $.Event(Event.collapsed) + var collapseIcon = this.options.collapseIcon + var expandIcon = this.options.expandIcon - if (this.options.accordion) { - var openMenuLi = parent.siblings(Selector.open) - var openTree = openMenuLi.children(Selector.treeviewMenu) - this.collapse(openTree, openMenuLi) - } + $(this.element) + .find(Selector.tools) + .find('.' + collapseIcon) + .removeClass(collapseIcon) + .addClass(expandIcon) - parent.addClass(ClassName.open) - tree.slideDown(this.options.animationSpeed, function () { - $(this.element).trigger(expandedEvent) - }.bind(this)) + $(this.element).find(Selector.body + ', ' + Selector.footer) + .slideUp(this.options.animationSpeed, function () { + $(this.element).addClass(ClassName.collapsed) + $(this.element).trigger(collapsedEvent) + }.bind(this)) } - Tree.prototype.collapse = function (tree, parentLi) { - var collapsedEvent = $.Event(Event.collapsed) + BoxWidget.prototype.remove = function () { + var removedEvent = $.Event(Event.removed) - tree.find(Selector.open).removeClass(ClassName.open) - parentLi.removeClass(ClassName.open) - tree.slideUp(this.options.animationSpeed, function () { - tree.find(Selector.open + ' > ' + Selector.treeview).slideUp() - $(this.element).trigger(collapsedEvent) + $(this.element).slideUp(this.options.animationSpeed, function () { + $(this.element).trigger(removedEvent) + $(this.element).remove() }.bind(this)) } // Private - Tree.prototype._setUpListeners = function () { + BoxWidget.prototype._setUpListeners = function () { var that = this - $(this.element).on('click', this.options.trigger, function (event) { - that.toggle($(this), event) + $(this.element).on('click', this.options.collapseTrigger, function (event) { + if (event) event.preventDefault() + that.toggle() + }) + + $(this.element).on('click', this.options.removeTrigger, function (event) { + if (event) event.preventDefault() + that.remove() }) } @@ -495,25 +268,32 @@ throw new Error('AdminLTE requires jQuery') if (!data) { var options = $.extend({}, Default, $this.data(), typeof option == 'object' && option) - $this.data(DataKey, new Tree($this, options)) + $this.data(DataKey, (data = new BoxWidget($this, options))) + } + + if (typeof option == 'string') { + if (typeof data[option] == 'undefined') { + throw new Error('No method named ' + option) + } + data[option]() } }) } - var old = $.fn.tree + var old = $.fn.boxWidget - $.fn.tree = Plugin - $.fn.tree.Constructor = Tree + $.fn.boxWidget = Plugin + $.fn.boxWidget.Constructor = BoxWidget // No Conflict Mode // ================ - $.fn.tree.noConflict = function () { - $.fn.tree = old + $.fn.boxWidget.noConflict = function () { + $.fn.boxWidget = old return this } - // Tree Data API - // ============= + // BoxWidget Data API + // ================== $(window).on('load', function () { $(Selector.data).each(function () { Plugin.call($(this)) @@ -663,129 +443,395 @@ throw new Error('AdminLTE requires jQuery') }(jQuery) -/* BoxWidget() - * ====== - * Adds box widget functions to boxes. +/* DirectChat() + * =============== + * Toggles the state of the control sidebar * - * @Usage: $('.my-box').boxWidget(options) - * This plugin auto activates on any element using the `.box` class - * Pass any option as data-option="value" + * @Usage: $('#my-chat-box').directChat() + * or add [data-widget="direct-chat"] to the trigger */ +function ($) { 'use strict' - var DataKey = 'lte.boxwidget' + var DataKey = 'lte.directchat' - var Default = { - animationSpeed : 500, - collapseTrigger: '[data-widget="collapse"]', - removeTrigger : '[data-widget="remove"]', - collapseIcon : 'fa-minus', - expandIcon : 'fa-plus', - removeIcon : 'fa-times' + var Selector = { + data: '[data-widget="chat-pane-toggle"]', + box : '.direct-chat' } - var Selector = { - data : '.box', - collapsed: '.collapsed-box', - body : '.box-body', - footer : '.box-footer', - tools : '.box-tools' + var ClassName = { + open: 'direct-chat-contacts-open' + } + + // DirectChat Class Definition + // =========================== + var DirectChat = function (element) { + this.element = element + } + + DirectChat.prototype.toggle = function ($trigger) { + $trigger.parents(Selector.box).first().toggleClass(ClassName.open) + } + + // Plugin Definition + // ================= + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data(DataKey) + + if (!data) { + $this.data(DataKey, (data = new DirectChat($this))) + } + + if (typeof option == 'string') data.toggle($this) + }) + } + + var old = $.fn.directChat + + $.fn.directChat = Plugin + $.fn.directChat.Constructor = DirectChat + + // No Conflict Mode + // ================ + $.fn.directChat.noConflict = function () { + $.fn.directChat = old + return this + } + + // DirectChat Data API + // =================== + $(document).on('click', Selector.data, function (event) { + if (event) event.preventDefault() + Plugin.call($(this), 'toggle') + }) + +}(jQuery) + + +/* Layout() + * ======== + * Implements AdminLTE layout. + * Fixes the layout height in case min-height fails. + * + * @usage activated automatically upon window load. + * Configure any options by passing data-option="value" + * to the body tag. + */ ++function ($) { + 'use strict' + + var DataKey = 'lte.layout' + + var Default = { + slimscroll : true, + resetHeight: true + } + + var Selector = { + wrapper : '.wrapper', + contentWrapper: '.content-wrapper', + layoutBoxed : '.layout-boxed', + mainFooter : '.main-footer', + mainHeader : '.main-header', + sidebar : '.sidebar', + controlSidebar: '.control-sidebar', + fixed : '.fixed', + sidebarMenu : '.sidebar-menu', + logo : '.main-header .logo' } var ClassName = { - collapsed: 'collapsed-box' + fixed : 'fixed', + holdTransition: 'hold-transition' } - var Event = { - collapsed: 'collapsed.boxwidget', - expanded : 'expanded.boxwidget', - removed : 'removed.boxwidget' + var Layout = function (options) { + this.options = options + this.bindedResize = false + this.activate() } - // BoxWidget Class Definition - // ===================== - var BoxWidget = function (element, options) { - this.element = element - this.options = options + Layout.prototype.activate = function () { + this.fix() + this.fixSidebar() - this._setUpListeners() + $('body').removeClass(ClassName.holdTransition) + + if (this.options.resetHeight) { + $('body, html, ' + Selector.wrapper).css({ + 'height' : 'auto', + 'min-height': '100%' + }) + } + + if (!this.bindedResize) { + $(window).resize(function () { + this.fix() + this.fixSidebar() + + $(Selector.logo + ', ' + Selector.sidebar).one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function () { + this.fix() + this.fixSidebar() + }.bind(this)) + }.bind(this)) + + this.bindedResize = true + } + + $(Selector.sidebarMenu).on('expanded.tree', function () { + this.fix() + this.fixSidebar() + }.bind(this)) + + $(Selector.sidebarMenu).on('collapsed.tree', function () { + this.fix() + this.fixSidebar() + }.bind(this)) } - BoxWidget.prototype.toggle = function () { - var isOpen = !$(this.element).is(Selector.collapsed) + Layout.prototype.fix = function () { + // Remove overflow from .wrapper if layout-boxed exists + $(Selector.layoutBoxed + ' > ' + Selector.wrapper).css('overflow', 'hidden') - if (isOpen) { - this.collapse() + // Get window height and the wrapper height + var footerHeight = $(Selector.mainFooter).outerHeight() || 0 + var neg = $(Selector.mainHeader).outerHeight() + footerHeight + var windowHeight = $(window).height() + var sidebarHeight = $(Selector.sidebar).height() || 0 + + // Set the min-height of the content and sidebar based on + // the height of the document. + if ($('body').hasClass(ClassName.fixed)) { + $(Selector.contentWrapper).css('min-height', windowHeight - footerHeight) } else { - this.expand() + var postSetHeight + + if (windowHeight >= sidebarHeight) { + $(Selector.contentWrapper).css('min-height', windowHeight - neg) + postSetHeight = windowHeight - neg + } else { + $(Selector.contentWrapper).css('min-height', sidebarHeight) + postSetHeight = sidebarHeight + } + + // Fix for the control sidebar height + var $controlSidebar = $(Selector.controlSidebar) + if (typeof $controlSidebar !== 'undefined') { + if ($controlSidebar.height() > postSetHeight) + $(Selector.contentWrapper).css('min-height', $controlSidebar.height()) + } } } - BoxWidget.prototype.expand = function () { - var expandedEvent = $.Event(Event.expanded) - var collapseIcon = this.options.collapseIcon - var expandIcon = this.options.expandIcon + Layout.prototype.fixSidebar = function () { + // Make sure the body tag has the .fixed class + if (!$('body').hasClass(ClassName.fixed)) { + if (typeof $.fn.slimScroll !== 'undefined') { + $(Selector.sidebar).slimScroll({ destroy: true }).height('auto') + } + return + } - $(this.element).removeClass(ClassName.collapsed) + // Enable slimscroll for fixed layout + if (this.options.slimscroll) { + if (typeof $.fn.slimScroll !== 'undefined') { + // Destroy if it exists + $(Selector.sidebar).slimScroll({ destroy: true }).height('auto') - $(this.element) - .find(Selector.tools) - .find('.' + expandIcon) - .removeClass(expandIcon) - .addClass(collapseIcon) + // Add slimscroll + $(Selector.sidebar).slimScroll({ + height: ($(window).height() - $(Selector.mainHeader).height()) + 'px', + color : 'rgba(0,0,0,0.2)', + size : '3px' + }) + } + } + } - $(this.element).find(Selector.body + ', ' + Selector.footer) - .slideDown(this.options.animationSpeed, function () { - $(this.element).trigger(expandedEvent) - }.bind(this)) + // Plugin Definition + // ================= + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data(DataKey) + + if (!data) { + var options = $.extend({}, Default, $this.data(), typeof option === 'object' && option) + $this.data(DataKey, (data = new Layout(options))) + } + + if (typeof option === 'string') { + if (typeof data[option] === 'undefined') { + throw new Error('No method named ' + option) + } + data[option]() + } + }) + } + + var old = $.fn.layout + + $.fn.layout = Plugin + $.fn.layout.Constuctor = Layout + + // No conflict mode + // ================ + $.fn.layout.noConflict = function () { + $.fn.layout = old + return this + } + + // Layout DATA-API + // =============== + $(window).on('load', function () { + Plugin.call($('body')) + }) +}(jQuery) + + +/* PushMenu() + * ========== + * Adds the push menu functionality to the sidebar. + * + * @usage: $('.btn').pushMenu(options) + * or add [data-toggle="push-menu"] to any button + * Pass any option as data-option="value" + */ ++function ($) { + 'use strict' + + var DataKey = 'lte.pushmenu' + + var Default = { + collapseScreenSize : 767, + expandOnHover : false, + expandTransitionDelay: 200 + } + + var Selector = { + collapsed : '.sidebar-collapse', + open : '.sidebar-open', + mainSidebar : '.main-sidebar', + contentWrapper: '.content-wrapper', + searchInput : '.sidebar-form .form-control', + button : '[data-toggle="push-menu"]', + mini : '.sidebar-mini', + expanded : '.sidebar-expanded-on-hover', + layoutFixed : '.fixed' + } + + var ClassName = { + collapsed : 'sidebar-collapse', + open : 'sidebar-open', + mini : 'sidebar-mini', + expanded : 'sidebar-expanded-on-hover', + expandFeature: 'sidebar-mini-expand-feature', + layoutFixed : 'fixed' + } + + var Event = { + expanded : 'expanded.pushMenu', + collapsed: 'collapsed.pushMenu' + } + + // PushMenu Class Definition + // ========================= + var PushMenu = function (options) { + this.options = options + this.init() + } + + PushMenu.prototype.init = function () { + if (this.options.expandOnHover + || ($('body').is(Selector.mini + Selector.layoutFixed))) { + this.expandOnHover() + $('body').addClass(ClassName.expandFeature) + } + + $(Selector.contentWrapper).click(function () { + // Enable hide menu when clicking on the content-wrapper on small screens + if ($(window).width() <= this.options.collapseScreenSize && $('body').hasClass(ClassName.open)) { + this.close() + } + }.bind(this)) + + // __Fix for android devices + $(Selector.searchInput).click(function (e) { + e.stopPropagation() + }) } - BoxWidget.prototype.collapse = function () { - var collapsedEvent = $.Event(Event.collapsed) - var collapseIcon = this.options.collapseIcon - var expandIcon = this.options.expandIcon + PushMenu.prototype.toggle = function () { + var windowWidth = $(window).width() + var isOpen = !$('body').hasClass(ClassName.collapsed) - $(this.element) - .find(Selector.tools) - .find('.' + collapseIcon) - .removeClass(collapseIcon) - .addClass(expandIcon) + if (windowWidth <= this.options.collapseScreenSize) { + isOpen = $('body').hasClass(ClassName.open) + } - $(this.element).find(Selector.body + ', ' + Selector.footer) - .slideUp(this.options.animationSpeed, function () { - $(this.element).addClass(ClassName.collapsed) - $(this.element).trigger(collapsedEvent) - }.bind(this)) + if (!isOpen) { + this.open() + } else { + this.close() + } } - BoxWidget.prototype.remove = function () { - var removedEvent = $.Event(Event.removed) + PushMenu.prototype.open = function () { + var windowWidth = $(window).width() - $(this.element).slideUp(this.options.animationSpeed, function () { - $(this.element).trigger(removedEvent) - $(this.element).remove() - }.bind(this)) + if (windowWidth > this.options.collapseScreenSize) { + $('body').removeClass(ClassName.collapsed) + .trigger($.Event(Event.expanded)) + } + else { + $('body').addClass(ClassName.open) + .trigger($.Event(Event.expanded)) + } } - // Private + PushMenu.prototype.close = function () { + var windowWidth = $(window).width() + if (windowWidth > this.options.collapseScreenSize) { + $('body').addClass(ClassName.collapsed) + .trigger($.Event(Event.collapsed)) + } else { + $('body').removeClass(ClassName.open + ' ' + ClassName.collapsed) + .trigger($.Event(Event.collapsed)) + } + } - BoxWidget.prototype._setUpListeners = function () { - var that = this + PushMenu.prototype.expandOnHover = function () { + $(Selector.mainSidebar).hover(function () { + if ($('body').is(Selector.mini + Selector.collapsed) + && $(window).width() > this.options.collapseScreenSize) { + this.expand() + } + }.bind(this), function () { + if ($('body').is(Selector.expanded)) { + this.collapse() + } + }.bind(this)) + } - $(this.element).on('click', this.options.collapseTrigger, function (event) { - if (event) event.preventDefault() - that.toggle() - }) + PushMenu.prototype.expand = function () { + setTimeout(function () { + $('body').removeClass(ClassName.collapsed) + .addClass(ClassName.expanded) + }, this.options.expandTransitionDelay) + } - $(this.element).on('click', this.options.removeTrigger, function (event) { - if (event) event.preventDefault() - that.remove() - }) + PushMenu.prototype.collapse = function () { + setTimeout(function () { + $('body').removeClass(ClassName.expanded) + .addClass(ClassName.collapsed) + }, this.options.expandTransitionDelay) } - // Plugin Definition - // ================= + // PushMenu Plugin Definition + // ========================== function Plugin(option) { return this.each(function () { var $this = $(this) @@ -793,38 +839,34 @@ throw new Error('AdminLTE requires jQuery') if (!data) { var options = $.extend({}, Default, $this.data(), typeof option == 'object' && option) - $this.data(DataKey, (data = new BoxWidget($this, options))) + $this.data(DataKey, (data = new PushMenu(options))) } - if (typeof option == 'string') { - if (typeof data[option] == 'undefined') { - throw new Error('No method named ' + option) - } - data[option]() - } + if (option == 'toggle') data.toggle() }) } - var old = $.fn.boxWidget + var old = $.fn.pushMenu - $.fn.boxWidget = Plugin - $.fn.boxWidget.Constructor = BoxWidget + $.fn.pushMenu = Plugin + $.fn.pushMenu.Constructor = PushMenu // No Conflict Mode // ================ - $.fn.boxWidget.noConflict = function () { - $.fn.boxWidget = old + $.fn.pushMenu.noConflict = function () { + $.fn.pushMenu = old return this } - // BoxWidget Data API - // ================== + // Data API + // ======== + $(document).on('click', Selector.button, function (e) { + e.preventDefault() + Plugin.call($(this), 'toggle') + }) $(window).on('load', function () { - $(Selector.data).each(function () { - Plugin.call($(this)) - }) + Plugin.call($(Selector.button)) }) - }(jQuery) @@ -842,10 +884,11 @@ throw new Error('AdminLTE requires jQuery') var DataKey = 'lte.todolist' var Default = { - iCheck : false, - onCheck : function () { + onCheck : function (item) { + return item }, - onUnCheck: function () { + onUnCheck: function (item) { + return item } } @@ -937,35 +980,114 @@ throw new Error('AdminLTE requires jQuery') }(jQuery) -/* DirectChat() - * =============== - * Toggles the state of the control sidebar +/* Tree() + * ====== + * Converts a nested list into a multilevel + * tree view menu. * - * @Usage: $('#my-chat-box').directChat() - * or add [data-widget="direct-chat"] to the trigger + * @Usage: $('.my-menu').tree(options) + * or add [data-widget="tree"] to the ul element + * Pass any option as data-option="value" */ +function ($) { 'use strict' - var DataKey = 'lte.directchat' + var DataKey = 'lte.tree' + + var Default = { + animationSpeed: 500, + accordion : true, + followLink : false, + trigger : '.treeview a' + } var Selector = { - data: '[data-widget="chat-pane-toggle"]', - box : '.direct-chat' + tree : '.tree', + treeview : '.treeview', + treeviewMenu: '.treeview-menu', + open : '.menu-open, .active', + li : 'li', + data : '[data-widget="tree"]', + active : '.active' } var ClassName = { - open: 'direct-chat-contacts-open' + open: 'menu-open', + tree: 'tree' } - // DirectChat Class Definition - // =========================== - var DirectChat = function (element) { + var Event = { + collapsed: 'collapsed.tree', + expanded : 'expanded.tree' + } + + // Tree Class Definition + // ===================== + var Tree = function (element, options) { this.element = element + this.options = options + + $(this.element).addClass(ClassName.tree) + + $(Selector.treeview + Selector.active, this.element).addClass(ClassName.open) + + this._setUpListeners() } - DirectChat.prototype.toggle = function ($trigger) { - $trigger.parents(Selector.box).first().toggleClass(ClassName.open) + Tree.prototype.toggle = function (link, event) { + var treeviewMenu = link.next(Selector.treeviewMenu) + var parentLi = link.parent() + var isOpen = parentLi.hasClass(ClassName.open) + + if (!parentLi.is(Selector.treeview)) { + return + } + + if (!this.options.followLink || link.attr('href') == '#') { + event.preventDefault() + } + + if (isOpen) { + this.collapse(treeviewMenu, parentLi) + } else { + this.expand(treeviewMenu, parentLi) + } + } + + Tree.prototype.expand = function (tree, parent) { + var expandedEvent = $.Event(Event.expanded) + + if (this.options.accordion) { + var openMenuLi = parent.siblings(Selector.open) + var openTree = openMenuLi.children(Selector.treeviewMenu) + this.collapse(openTree, openMenuLi) + } + + parent.addClass(ClassName.open) + tree.slideDown(this.options.animationSpeed, function () { + $(this.element).trigger(expandedEvent) + }.bind(this)) + } + + Tree.prototype.collapse = function (tree, parentLi) { + var collapsedEvent = $.Event(Event.collapsed) + + tree.find(Selector.open).removeClass(ClassName.open) + parentLi.removeClass(ClassName.open) + tree.slideUp(this.options.animationSpeed, function () { + tree.find(Selector.open + ' > ' + Selector.treeview).slideUp() + $(this.element).trigger(collapsedEvent) + }.bind(this)) + } + + // Private + + Tree.prototype._setUpListeners = function () { + var that = this + + $(this.element).on('click', this.options.trigger, function (event) { + that.toggle($(this), event) + }) } // Plugin Definition @@ -976,30 +1098,30 @@ throw new Error('AdminLTE requires jQuery') var data = $this.data(DataKey) if (!data) { - $this.data(DataKey, (data = new DirectChat($this))) + var options = $.extend({}, Default, $this.data(), typeof option == 'object' && option) + $this.data(DataKey, new Tree($this, options)) } - - if (typeof option == 'string') data.toggle($this) }) } - var old = $.fn.directChat + var old = $.fn.tree - $.fn.directChat = Plugin - $.fn.directChat.Constructor = DirectChat + $.fn.tree = Plugin + $.fn.tree.Constructor = Tree // No Conflict Mode // ================ - $.fn.directChat.noConflict = function () { - $.fn.directChat = old + $.fn.tree.noConflict = function () { + $.fn.tree = old return this } - // DirectChat Data API - // =================== - $(document).on('click', Selector.data, function (event) { - if (event) event.preventDefault() - Plugin.call($(this), 'toggle') + // Tree Data API + // ============= + $(window).on('load', function () { + $(Selector.data).each(function () { + Plugin.call($(this)) + }) }) }(jQuery) diff --git a/dist/js/adminlte.min.js b/dist/js/adminlte.min.js index c8525103454..b9ab62653ac 100644 --- a/dist/js/adminlte.min.js +++ b/dist/js/adminlte.min.js @@ -11,4 +11,4 @@ * @repository git://github.com/almasaeed2010/AdminLTE.git * @license MIT