3 * Main JS application file for AdminLTE v2. This file
4 * should be included in all pages. It controls some layout
5 * options and implements exclusive AdminLTE plugins.
7 * @Author Almsaeed Studio
8 * @Support <http://www.almsaeedstudio.com>
9 * @Email <abdullah@almsaeedstudio.com>
11 * @license MIT <http://opensource.org/licenses/MIT>
14 //Make sure jQuery has been loaded before app.js
15 if (typeof jQuery
=== "undefined") {
16 throw new Error("AdminLTE requires jQuery");
22 * @description $.AdminLTE is the main object for the template's app.
23 * It's used for implementing functions and options related
24 * to the template. Keeping everything wrapped in an object
25 * prevents conflict with other plugins and is a better
26 * way to organize our code.
30 /* --------------------
31 * - AdminLTE Options -
32 * --------------------
33 * Modify these options to suit your implementation
35 $.AdminLTE
.options
= {
36 //Add slimscroll to navbar menus
37 //This requires you to load the slimscroll plugin
38 //in every page before app.js
39 navbarMenuSlimscroll
: true,
40 navbarMenuSlimscrollWidth
: "3px", //The width of the scroll bar
41 navbarMenuHeight
: "200px", //The height of the inner menu
42 //General animation speed for JS animated elements such as box collapse/expand and
43 //sidebar treeview slide up/down. This options accepts an integer as milliseconds,
44 //'fast', 'normal', or 'slow'
46 //Sidebar push menu toggle button selector
47 sidebarToggleSelector
: "[data-toggle='offcanvas']",
48 //Activate sidebar push menu
49 sidebarPushMenu
: true,
50 //Activate sidebar slimscroll if the fixed layout is set (requires SlimScroll Plugin)
51 sidebarSlimScroll
: true,
52 //Enable sidebar expand on hover effect for sidebar mini
53 //This option is forced to true if both the fixed layout and sidebar mini
55 sidebarExpandOnHover
: false,
57 enableBoxRefresh
: true,
58 //Bootstrap.js tooltip
59 enableBSToppltip
: true,
60 BSTooltipSelector
: "[data-toggle='tooltip']",
61 //Enable Fast Click. Fastclick.js creates a more
62 //native touch experience with touch devices. If you
63 //choose to enable the plugin, make sure you load the script
64 //before AdminLTE's app.js
65 enableFastclick
: false,
66 //Control Sidebar Options
67 enableControlSidebar
: true,
68 controlSidebarOptions
: {
69 //Which button should trigger the open/close event
70 toggleBtnSelector
: "[data-toggle='control-sidebar']",
71 //The sidebar selector
72 selector
: ".control-sidebar",
73 //Enable slide over content
76 //Box Widget Plugin. Enable this plugin
77 //to allow boxes to be collapsed and/or removed
78 enableBoxWidget
: true,
79 //Box Widget plugin options
90 //Remove button selector
91 remove
: '[data-widget="remove"]',
92 //Collapse button selector
93 collapse
: '[data-widget="collapse"]'
96 //Direct Chat plugin options
98 //Enable direct chat by default
100 //The button to open and close the chat contacts pane
101 contactToggleSelector
: '[data-widget="chat-pane-toggle"]'
103 //Define the set of colors to use globally around the website
105 lightBlue
: "#3c8dbc",
122 //The standard screen sizes that bootstrap uses.
123 //If you change these in the variables.less file, change
133 /* ------------------
136 * The next block of code implements AdminLTE's
137 * functions and plugins as specified by the
143 //Fix for IE page transitions
144 $("body").removeClass("hold-transition");
146 //Extend options if external options exist
147 if (typeof AdminLTEOptions
!== "undefined") {
153 //Easy access to options
154 var o
= $.AdminLTE
.options
;
159 //Activate the layout maker
160 $.AdminLTE
.layout
.activate();
162 //Enable sidebar tree view controls
163 $.AdminLTE
.tree('.sidebar');
165 //Enable control sidebar
166 if (o
.enableControlSidebar
) {
167 $.AdminLTE
.controlSidebar
.activate();
170 //Add slimscroll to navbar dropdown
171 if (o
.navbarMenuSlimscroll
&& typeof $.fn
.slimscroll
!= 'undefined') {
172 $(".navbar .menu").slimscroll({
173 height
: o
.navbarMenuHeight
,
174 alwaysVisible
: false,
175 size
: o
.navbarMenuSlimscrollWidth
176 }).css("width", "100%");
179 //Activate sidebar push menu
180 if (o
.sidebarPushMenu
) {
181 $.AdminLTE
.pushMenu
.activate(o
.sidebarToggleSelector
);
184 //Activate Bootstrap tooltip
185 if (o
.enableBSToppltip
) {
187 selector
: o
.BSTooltipSelector
191 //Activate box widget
192 if (o
.enableBoxWidget
) {
193 $.AdminLTE
.boxWidget
.activate();
196 //Activate fast click
197 if (o
.enableFastclick
&& typeof FastClick
!= 'undefined') {
198 FastClick
.attach(document
.body
);
201 //Activate direct chat widget
202 if (o
.directChat
.enable
) {
203 $(document
).on('click', o
.directChat
.contactToggleSelector
, function () {
204 var box
= $(this).parents('.direct-chat').first();
205 box
.toggleClass('direct-chat-contacts-open');
210 * INITIALIZE BUTTON TOGGLE
211 * ------------------------
213 $('.btn-group[data-toggle="btn-toggle"]').each(function () {
215 $(this).find(".btn").on('click', function (e
) {
216 group
.find(".btn.active").removeClass("active");
217 $(this).addClass("active");
224 /* ----------------------------------
225 * - Initialize the AdminLTE Object -
226 * ----------------------------------
227 * All AdminLTE functions are implemented below.
233 * Fixes the layout height in case min-height fails.
236 * @usage $.AdminLTE.layout.activate()
237 * $.AdminLTE.layout.fix()
238 * $.AdminLTE.layout.fixSidebar()
240 $.AdminLTE
.layout
= {
241 activate: function () {
245 $(window
, ".wrapper").resize(function () {
251 //Get window height and the wrapper height
252 var neg
= $('.main-header').outerHeight() + $('.main-footer').outerHeight();
253 var window_height
= $(window
).height();
254 var sidebar_height
= $(".sidebar").height();
255 //Set the min-height of the content and sidebar based on the
256 //the height of the document.
257 if ($("body").hasClass("fixed")) {
258 $(".content-wrapper, .right-side").css('min-height', window_height
- $('.main-footer').outerHeight());
261 if (window_height
>= sidebar_height
) {
262 $(".content-wrapper, .right-side").css('min-height', window_height
- neg
);
263 postSetWidth
= window_height
- neg
;
265 $(".content-wrapper, .right-side").css('min-height', sidebar_height
);
266 postSetWidth
= sidebar_height
;
269 //Fix for the control sidebar height
270 var controlSidebar
= $($.AdminLTE
.options
.controlSidebarOptions
.selector
);
271 if (typeof controlSidebar
!== "undefined") {
272 if (controlSidebar
.height() > postSetWidth
)
273 $(".content-wrapper, .right-side").css('min-height', controlSidebar
.height());
278 fixSidebar: function () {
279 //Make sure the body tag has the .fixed class
280 if (!$("body").hasClass("fixed")) {
281 if (typeof $.fn
.slimScroll
!= 'undefined') {
282 $(".sidebar").slimScroll({destroy
: true}).height("auto");
285 } else if (typeof $.fn
.slimScroll
== 'undefined' && window
.console
) {
286 window
.console
.error("Error: the fixed layout requires the slimscroll plugin!");
288 //Enable slimscroll for fixed layout
289 if ($.AdminLTE
.options
.sidebarSlimScroll
) {
290 if (typeof $.fn
.slimScroll
!= 'undefined') {
291 //Destroy if it exists
292 $(".sidebar").slimScroll({destroy
: true}).height("auto");
294 $(".sidebar").slimscroll({
295 height
: ($(window
).height() - $(".main-header").height()) + "px",
296 color
: "rgba(0,0,0,0.2)",
306 * Adds the push menu functionality to the sidebar.
309 * @usage: $.AdminLTE.pushMenu("[data-toggle='offcanvas']")
311 $.AdminLTE
.pushMenu
= {
312 activate: function (toggleBtn
) {
313 //Get the screen sizes
314 var screenSizes
= $.AdminLTE
.options
.screenSizes
;
316 //Enable sidebar toggle
317 $(document
).on('click', toggleBtn
, function (e
) {
320 //Enable sidebar push menu
321 if ($(window
).width() > (screenSizes
.sm
- 1)) {
322 if ($("body").hasClass('sidebar-collapse')) {
323 $("body").removeClass('sidebar-collapse').trigger('expanded.pushMenu');
325 $("body").addClass('sidebar-collapse').trigger('collapsed.pushMenu');
328 //Handle sidebar push menu for small screens
330 if ($("body").hasClass('sidebar-open')) {
331 $("body").removeClass('sidebar-open').removeClass('sidebar-collapse').trigger('collapsed.pushMenu');
333 $("body").addClass('sidebar-open').trigger('expanded.pushMenu');
338 $(".content-wrapper").click(function () {
339 //Enable hide menu when clicking on the content-wrapper on small screens
340 if ($(window
).width() <= (screenSizes
.sm
- 1) && $("body").hasClass("sidebar-open")) {
341 $("body").removeClass('sidebar-open');
345 //Enable expand on hover for sidebar mini
346 if ($.AdminLTE
.options
.sidebarExpandOnHover
347 || ($('body').hasClass('fixed')
348 && $('body').hasClass('sidebar-mini'))) {
349 this.expandOnHover();
352 expandOnHover: function () {
354 var screenWidth
= $.AdminLTE
.options
.screenSizes
.sm
- 1;
355 //Expand sidebar on hover
356 $('.main-sidebar').hover(function () {
357 if ($('body').hasClass('sidebar-mini')
358 && $("body").hasClass('sidebar-collapse')
359 && $(window
).width() > screenWidth
) {
363 if ($('body').hasClass('sidebar-mini')
364 && $('body').hasClass('sidebar-expanded-on-hover')
365 && $(window
).width() > screenWidth
) {
370 expand: function () {
371 $("body").removeClass('sidebar-collapse').addClass('sidebar-expanded-on-hover');
373 collapse: function () {
374 if ($('body').hasClass('sidebar-expanded-on-hover')) {
375 $('body').removeClass('sidebar-expanded-on-hover').addClass('sidebar-collapse');
382 * Converts the sidebar into a multilevel
386 * @Usage: $.AdminLTE.tree('.sidebar')
388 $.AdminLTE
.tree = function (menu
) {
390 var animationSpeed
= $.AdminLTE
.options
.animationSpeed
;
391 $(document
).off('click', menu
+ ' li a')
392 .on('click', menu
+ ' li a', function (e
) {
393 //Get the clicked link and the next element
395 var checkElement
= $this.next();
397 //Check if the next element is a menu and is visible
398 if ((checkElement
.is('.treeview-menu')) && (checkElement
.is(':visible')) && (!$('body').hasClass('sidebar-collapse'))) {
400 checkElement
.slideUp(animationSpeed
, function () {
401 checkElement
.removeClass('menu-open');
402 //Fix the layout in case the sidebar stretches over the height of the window
403 //_this.layout.fix();
405 checkElement
.parent("li").removeClass("active");
407 //If the menu is not visible
408 else if ((checkElement
.is('.treeview-menu')) && (!checkElement
.is(':visible'))) {
409 //Get the parent menu
410 var parent
= $this.parents('ul').first();
411 //Close all open menus within the parent
412 var ul
= parent
.find('ul:visible').slideUp(animationSpeed
);
413 //Remove the menu-open class from the parent
414 ul
.removeClass('menu-open');
416 var parent_li
= $this.parent("li");
418 //Open the target menu and add the menu-open class
419 checkElement
.slideDown(animationSpeed
, function () {
420 //Add the class active to the parent li
421 checkElement
.addClass('menu-open');
422 parent
.find('li.active').removeClass('active');
423 parent_li
.addClass('active');
424 //Fix the layout in case the sidebar stretches over the height of the window
428 //if this isn't a link, prevent the page from being redirected
429 if (checkElement
.is('.treeview-menu')) {
437 * Adds functionality to the right sidebar
440 * @usage $.AdminLTE.controlSidebar.activate(options)
442 $.AdminLTE
.controlSidebar
= {
443 //instantiate the object
444 activate: function () {
448 var o
= $.AdminLTE
.options
.controlSidebarOptions
;
450 var sidebar
= $(o
.selector
);
452 var btn
= $(o
.toggleBtnSelector
);
454 //Listen to the click event
455 btn
.on('click', function (e
) {
457 //If the sidebar is not open
458 if (!sidebar
.hasClass('control-sidebar-open')
459 && !$('body').hasClass('control-sidebar-open')) {
461 _this
.open(sidebar
, o
.slide
);
463 _this
.close(sidebar
, o
.slide
);
467 //If the body has a boxed layout, fix the sidebar bg position
468 var bg
= $(".control-sidebar-bg");
471 //If the body has a fixed layout, make the control sidebar fixed
472 if ($('body').hasClass('fixed')) {
473 _this
._fixForFixed(sidebar
);
475 //If the content height is less than the sidebar's height, force max height
476 if ($('.content-wrapper, .right-side').height() < sidebar
.height()) {
477 _this
._fixForContent(sidebar
);
481 //Open the control sidebar
482 open: function (sidebar
, slide
) {
485 sidebar
.addClass('control-sidebar-open');
487 //Push the content by adding the open class to the body instead
488 //of the sidebar itself
489 $('body').addClass('control-sidebar-open');
492 //Close the control sidebar
493 close: function (sidebar
, slide
) {
495 sidebar
.removeClass('control-sidebar-open');
497 $('body').removeClass('control-sidebar-open');
500 _fix: function (sidebar
) {
502 if ($("body").hasClass('layout-boxed')) {
503 sidebar
.css('position', 'absolute');
504 sidebar
.height($(".wrapper").height());
505 if (_this
.hasBindedResize
) {
508 $(window
).resize(function () {
511 _this
.hasBindedResize
= true;
519 _fixForFixed: function (sidebar
) {
522 'max-height': '100%',
524 'padding-bottom': '50px'
527 _fixForContent: function (sidebar
) {
528 $(".content-wrapper, .right-side").css('min-height', sidebar
.height());
534 * BoxWidget is a plugin to handle collapsing and
535 * removing boxes from the screen.
538 * @usage $.AdminLTE.boxWidget.activate()
539 * Set all your options in the main $.AdminLTE.options object
541 $.AdminLTE
.boxWidget
= {
542 selectors
: $.AdminLTE
.options
.boxWidgetOptions
.boxWidgetSelectors
,
543 icons
: $.AdminLTE
.options
.boxWidgetOptions
.boxWidgetIcons
,
544 animationSpeed
: $.AdminLTE
.options
.animationSpeed
,
545 activate: function (_box
) {
548 _box
= document
; // activate all boxes per default
550 //Listen for collapse event triggers
551 $(_box
).on('click', _this
.selectors
.collapse
, function (e
) {
553 _this
.collapse($(this));
556 //Listen for remove event triggers
557 $(_box
).on('click', _this
.selectors
.remove
, function (e
) {
559 _this
.remove($(this));
562 collapse: function (element
) {
564 //Find the box parent
565 var box
= element
.parents(".box").first();
566 //Find the body and the footer
567 var box_content
= box
.find("> .box-body, > .box-footer, > form >.box-body, > form > .box-footer");
568 if (!box
.hasClass("collapsed-box")) {
569 //Convert minus into plus
570 element
.children(":first")
571 .removeClass(_this
.icons
.collapse
)
572 .addClass(_this
.icons
.open
);
574 box_content
.slideUp(_this
.animationSpeed
, function () {
575 box
.addClass("collapsed-box");
578 //Convert plus into minus
579 element
.children(":first")
580 .removeClass(_this
.icons
.open
)
581 .addClass(_this
.icons
.collapse
);
583 box_content
.slideDown(_this
.animationSpeed
, function () {
584 box
.removeClass("collapsed-box");
588 remove: function (element
) {
589 //Find the box parent
590 var box
= element
.parents(".box").first();
591 box
.slideUp(this.animationSpeed
);
596 /* ------------------
599 * All custom plugins are defined below.
605 * This is a custom plugin to use with the component BOX. It allows you to add
606 * a refresh button to the box. It converts the box's state to a loading state.
609 * @usage $("#box-widget").boxRefresh( options );
615 $.fn
.boxRefresh = function (options
) {
618 var settings
= $.extend({
619 //Refresh button selector
620 trigger
: ".refresh-btn",
621 //File source to be loaded (e.g: ajax/src.php)
624 onLoadStart: function (box
) {
626 }, //Right after the button has been clicked
627 onLoadDone: function (box
) {
629 } //When the source has been loaded
634 var overlay
= $('<div class="overlay"><div class="fa fa-refresh fa-spin"></div></div>');
636 return this.each(function () {
637 //if a source is specified
638 if (settings
.source
=== "") {
639 if (window
.console
) {
640 window
.console
.log("Please specify a source first - boxRefresh()");
647 var rBtn
= box
.find(settings
.trigger
).first();
650 rBtn
.on('click', function (e
) {
652 //Add loading overlay
656 box
.find(".box-body").load(settings
.source
, function () {
662 function start(box
) {
663 //Add overlay and loading img
666 settings
.onLoadStart
.call(box
);
670 //Remove overlay and loading img
671 box
.find(overlay
).remove();
673 settings
.onLoadDone
.call(box
);
681 * EXPLICIT BOX CONTROLS
682 * -----------------------
683 * This is a custom plugin to use with the component BOX. It allows you to activate
684 * a box inserted in the DOM after the app.js was loaded, toggle and remove box.
687 * @usage $("#box-widget").activateBox();
688 * @usage $("#box-widget").toggleBox();
689 * @usage $("#box-widget").removeBox();
695 $.fn
.activateBox = function () {
696 $.AdminLTE
.boxWidget
.activate(this);
699 $.fn
.toggleBox = function () {
700 var button
= $($.AdminLTE
.boxWidget
.selectors
.collapse
, this);
701 $.AdminLTE
.boxWidget
.collapse(button
);
704 $.fn
.removeBox = function () {
705 var button
= $($.AdminLTE
.boxWidget
.selectors
.remove
, this);
706 $.AdminLTE
.boxWidget
.remove(button
);
712 * TODO LIST CUSTOM PLUGIN
713 * -----------------------
714 * This plugin depends on iCheck plugin for checkbox and radio inputs
717 * @usage $("#todo-widget").todolist( options );
723 $.fn
.todolist = function (options
) {
725 var settings
= $.extend({
726 //When the user checks the input
727 onCheck: function (ele
) {
730 //When the user unchecks the input
731 onUncheck: function (ele
) {
736 return this.each(function () {
738 if (typeof $.fn
.iCheck
!= 'undefined') {
739 $('input', this).on('ifChecked', function () {
740 var ele
= $(this).parents("li").first();
741 ele
.toggleClass("done");
742 settings
.onCheck
.call(ele
);
745 $('input', this).on('ifUnchecked', function () {
746 var ele
= $(this).parents("li").first();
747 ele
.toggleClass("done");
748 settings
.onUncheck
.call(ele
);
751 $('input', this).on('change', function () {
752 var ele
= $(this).parents("li").first();
753 ele
.toggleClass("done");
754 if ($('input', ele
).is(":checked")) {
755 settings
.onCheck
.call(ele
);
757 settings
.onUncheck
.call(ele
);