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 <support@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: true,
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 $(toggleBtn
).on('click', 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
).on('click', menu
+ ' li a', function (e
) {
392 //Get the clicked link and the next element
394 var checkElement
= $this.next();
396 //Check if the next element is a menu and is visible
397 if ((checkElement
.is('.treeview-menu')) && (checkElement
.is(':visible'))) {
399 checkElement
.slideUp(animationSpeed
, function () {
400 checkElement
.removeClass('menu-open');
401 //Fix the layout in case the sidebar stretches over the height of the window
402 //_this.layout.fix();
404 checkElement
.parent("li").removeClass("active");
406 //If the menu is not visible
407 else if ((checkElement
.is('.treeview-menu')) && (!checkElement
.is(':visible'))) {
408 //Get the parent menu
409 var parent
= $this.parents('ul').first();
410 //Close all open menus within the parent
411 var ul
= parent
.find('ul:visible').slideUp(animationSpeed
);
412 //Remove the menu-open class from the parent
413 ul
.removeClass('menu-open');
415 var parent_li
= $this.parent("li");
417 //Open the target menu and add the menu-open class
418 checkElement
.slideDown(animationSpeed
, function () {
419 //Add the class active to the parent li
420 checkElement
.addClass('menu-open');
421 parent
.find('li.active').removeClass('active');
422 parent_li
.addClass('active');
423 //Fix the layout in case the sidebar stretches over the height of the window
427 //if this isn't a link, prevent the page from being redirected
428 if (checkElement
.is('.treeview-menu')) {
436 * Adds functionality to the right sidebar
439 * @usage $.AdminLTE.controlSidebar.activate(options)
441 $.AdminLTE
.controlSidebar
= {
442 //instantiate the object
443 activate: function () {
447 var o
= $.AdminLTE
.options
.controlSidebarOptions
;
449 var sidebar
= $(o
.selector
);
451 var btn
= $(o
.toggleBtnSelector
);
453 //Listen to the click event
454 btn
.on('click', function (e
) {
456 //If the sidebar is not open
457 if (!sidebar
.hasClass('control-sidebar-open')
458 && !$('body').hasClass('control-sidebar-open')) {
460 _this
.open(sidebar
, o
.slide
);
462 _this
.close(sidebar
, o
.slide
);
466 //If the body has a boxed layout, fix the sidebar bg position
467 var bg
= $(".control-sidebar-bg");
470 //If the body has a fixed layout, make the control sidebar fixed
471 if ($('body').hasClass('fixed')) {
472 _this
._fixForFixed(sidebar
);
474 //If the content height is less than the sidebar's height, force max height
475 if ($('.content-wrapper, .right-side').height() < sidebar
.height()) {
476 _this
._fixForContent(sidebar
);
480 //Open the control sidebar
481 open: function (sidebar
, slide
) {
484 sidebar
.addClass('control-sidebar-open');
486 //Push the content by adding the open class to the body instead
487 //of the sidebar itself
488 $('body').addClass('control-sidebar-open');
491 //Close the control sidebar
492 close: function (sidebar
, slide
) {
494 sidebar
.removeClass('control-sidebar-open');
496 $('body').removeClass('control-sidebar-open');
499 _fix: function (sidebar
) {
501 if ($("body").hasClass('layout-boxed')) {
502 sidebar
.css('position', 'absolute');
503 sidebar
.height($(".wrapper").height());
504 $(window
).resize(function () {
514 _fixForFixed: function (sidebar
) {
517 'max-height': '100%',
519 'padding-bottom': '50px'
522 _fixForContent: function (sidebar
) {
523 $(".content-wrapper, .right-side").css('min-height', sidebar
.height());
529 * BoxWidget is a plugin to handle collapsing and
530 * removing boxes from the screen.
533 * @usage $.AdminLTE.boxWidget.activate()
534 * Set all your options in the main $.AdminLTE.options object
536 $.AdminLTE
.boxWidget
= {
537 selectors: $.AdminLTE
.options
.boxWidgetOptions
.boxWidgetSelectors
,
538 icons: $.AdminLTE
.options
.boxWidgetOptions
.boxWidgetIcons
,
539 animationSpeed: $.AdminLTE
.options
.animationSpeed
,
540 activate: function (_box
) {
543 _box
= document
; // activate all boxes per default
545 //Listen for collapse event triggers
546 $(_box
).on('click', _this
.selectors
.collapse
, function (e
) {
548 _this
.collapse($(this));
551 //Listen for remove event triggers
552 $(_box
).on('click', _this
.selectors
.remove
, function (e
) {
554 _this
.remove($(this));
557 collapse: function (element
) {
559 //Find the box parent
560 var box
= element
.parents(".box").first();
561 //Find the body and the footer
562 var box_content
= box
.find("> .box-body, > .box-footer, > form >.box-body, > form > .box-footer");
563 if (!box
.hasClass("collapsed-box")) {
564 //Convert minus into plus
565 element
.children(":first")
566 .removeClass(_this
.icons
.collapse
)
567 .addClass(_this
.icons
.open
);
569 box_content
.slideUp(_this
.animationSpeed
, function () {
570 box
.addClass("collapsed-box");
573 //Convert plus into minus
574 element
.children(":first")
575 .removeClass(_this
.icons
.open
)
576 .addClass(_this
.icons
.collapse
);
578 box_content
.slideDown(_this
.animationSpeed
, function () {
579 box
.removeClass("collapsed-box");
583 remove: function (element
) {
584 //Find the box parent
585 var box
= element
.parents(".box").first();
586 box
.slideUp(this.animationSpeed
);
591 /* ------------------
594 * All custom plugins are defined below.
600 * This is a custom plugin to use with the component BOX. It allows you to add
601 * a refresh button to the box. It converts the box's state to a loading state.
604 * @usage $("#box-widget").boxRefresh( options );
610 $.fn
.boxRefresh = function (options
) {
613 var settings
= $.extend({
614 //Refresh button selector
615 trigger: ".refresh-btn",
616 //File source to be loaded (e.g: ajax/src.php)
619 onLoadStart: function (box
) {
621 }, //Right after the button has been clicked
622 onLoadDone: function (box
) {
624 } //When the source has been loaded
629 var overlay
= $('<div class="overlay"><div class="fa fa-refresh fa-spin"></div></div>');
631 return this.each(function () {
632 //if a source is specified
633 if (settings
.source
=== "") {
634 if (window
.console
) {
635 window
.console
.log("Please specify a source first - boxRefresh()");
642 var rBtn
= box
.find(settings
.trigger
).first();
645 rBtn
.on('click', function (e
) {
647 //Add loading overlay
651 box
.find(".box-body").load(settings
.source
, function () {
657 function start(box
) {
658 //Add overlay and loading img
661 settings
.onLoadStart
.call(box
);
665 //Remove overlay and loading img
666 box
.find(overlay
).remove();
668 settings
.onLoadDone
.call(box
);
676 * EXPLICIT BOX ACTIVATION
677 * -----------------------
678 * This is a custom plugin to use with the component BOX. It allows you to activate
679 * a box inserted in the DOM after the app.js was loaded.
682 * @usage $("#box-widget").activateBox();
688 $.fn
.activateBox = function () {
689 $.AdminLTE
.boxWidget
.activate(this);
695 * TODO LIST CUSTOM PLUGIN
696 * -----------------------
697 * This plugin depends on iCheck plugin for checkbox and radio inputs
700 * @usage $("#todo-widget").todolist( options );
706 $.fn
.todolist = function (options
) {
708 var settings
= $.extend({
709 //When the user checks the input
710 onCheck: function (ele
) {
713 //When the user unchecks the input
714 onUncheck: function (ele
) {
719 return this.each(function () {
721 if (typeof $.fn
.iCheck
!= 'undefined') {
722 $('input', this).on('ifChecked', function () {
723 var ele
= $(this).parents("li").first();
724 ele
.toggleClass("done");
725 settings
.onCheck
.call(ele
);
728 $('input', this).on('ifUnchecked', function () {
729 var ele
= $(this).parents("li").first();
730 ele
.toggleClass("done");
731 settings
.onUncheck
.call(ele
);
734 $('input', this).on('change', function () {
735 var ele
= $(this).parents("li").first();
736 ele
.toggleClass("done");
737 if ($('input', ele
).is(":checked")) {
738 settings
.onCheck
.call(ele
);
740 settings
.onUncheck
.call(ele
);