adminlte.js 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160
  1. /*! AdminLTE app.js
  2. * ================
  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.
  6. *
  7. * @author Colorlib
  8. * @support <https://github.com/ColorlibHQ/AdminLTE/issues>
  9. * @version v2.4.18
  10. * @repository git://github.com/ColorlibHQ/AdminLTE.git
  11. * @license MIT <http://opensource.org/licenses/MIT>
  12. */
  13. // Make sure jQuery has been loaded
  14. if (typeof jQuery === 'undefined') {
  15. throw new Error('AdminLTE requires jQuery')
  16. }
  17. /* BoxRefresh()
  18. * =========
  19. * Adds AJAX content control to a box.
  20. *
  21. * @Usage: $('#my-box').boxRefresh(options)
  22. * or add [data-widget="box-refresh"] to the box element
  23. * Pass any option as data-option="value"
  24. */
  25. +function ($) {
  26. 'use strict';
  27. var DataKey = 'lte.boxrefresh';
  28. var Default = {
  29. source : '',
  30. params : {},
  31. trigger : '.refresh-btn',
  32. content : '.box-body',
  33. loadInContent : true,
  34. responseType : '',
  35. overlayTemplate: '<div class="overlay"><div class="fa fa-refresh fa-spin"></div></div>',
  36. onLoadStart : function () {
  37. },
  38. onLoadDone : function (response) {
  39. return response;
  40. }
  41. };
  42. var Selector = {
  43. data: '[data-widget="box-refresh"]'
  44. };
  45. // BoxRefresh Class Definition
  46. // =========================
  47. var BoxRefresh = function (element, options) {
  48. this.element = element;
  49. this.options = options;
  50. this.$overlay = $(options.overlayTemplate);
  51. if (options.source === '') {
  52. throw new Error('Source url was not defined. Please specify a url in your BoxRefresh source option.');
  53. }
  54. this._setUpListeners();
  55. this.load();
  56. };
  57. BoxRefresh.prototype.load = function () {
  58. this._addOverlay();
  59. this.options.onLoadStart.call($(this));
  60. $.get(this.options.source, this.options.params, function (response) {
  61. if (this.options.loadInContent) {
  62. $(this.element).find(this.options.content).html(response);
  63. }
  64. this.options.onLoadDone.call($(this), response);
  65. this._removeOverlay();
  66. }.bind(this), this.options.responseType !== '' && this.options.responseType);
  67. };
  68. // Private
  69. BoxRefresh.prototype._setUpListeners = function () {
  70. $(this.element).on('click', this.options.trigger, function (event) {
  71. if (event) event.preventDefault();
  72. this.load();
  73. }.bind(this));
  74. };
  75. BoxRefresh.prototype._addOverlay = function () {
  76. $(this.element).append(this.$overlay);
  77. };
  78. BoxRefresh.prototype._removeOverlay = function () {
  79. $(this.$overlay).remove();
  80. };
  81. // Plugin Definition
  82. // =================
  83. function Plugin(option) {
  84. return this.each(function () {
  85. var $this = $(this);
  86. var data = $this.data(DataKey);
  87. if (!data) {
  88. var options = $.extend({}, Default, $this.data(), typeof option == 'object' && option);
  89. $this.data(DataKey, (data = new BoxRefresh($this, options)));
  90. }
  91. if (typeof data == 'string') {
  92. if (typeof data[option] == 'undefined') {
  93. throw new Error('No method named ' + option);
  94. }
  95. data[option]();
  96. }
  97. });
  98. }
  99. var old = $.fn.boxRefresh;
  100. $.fn.boxRefresh = Plugin;
  101. $.fn.boxRefresh.Constructor = BoxRefresh;
  102. // No Conflict Mode
  103. // ================
  104. $.fn.boxRefresh.noConflict = function () {
  105. $.fn.boxRefresh = old;
  106. return this;
  107. };
  108. // BoxRefresh Data API
  109. // =================
  110. $(window).on('load', function () {
  111. $(Selector.data).each(function () {
  112. Plugin.call($(this));
  113. });
  114. });
  115. }(jQuery);
  116. /* BoxWidget()
  117. * ======
  118. * Adds box widget functions to boxes.
  119. *
  120. * @Usage: $('.my-box').boxWidget(options)
  121. * This plugin auto activates on any element using the `.box` class
  122. * Pass any option as data-option="value"
  123. */
  124. +function ($) {
  125. 'use strict';
  126. var DataKey = 'lte.boxwidget';
  127. var Default = {
  128. animationSpeed : 500,
  129. collapseTrigger: '[data-widget="collapse"]',
  130. removeTrigger : '[data-widget="remove"]',
  131. collapseIcon : 'fa-minus',
  132. expandIcon : 'fa-plus',
  133. removeIcon : 'fa-times'
  134. };
  135. var Selector = {
  136. data : '.box',
  137. collapsed: '.collapsed-box',
  138. header : '.box-header',
  139. body : '.box-body',
  140. footer : '.box-footer',
  141. tools : '.box-tools'
  142. };
  143. var ClassName = {
  144. collapsed: 'collapsed-box'
  145. };
  146. var Event = {
  147. collapsing: 'collapsing.boxwidget',
  148. collapsed: 'collapsed.boxwidget',
  149. expanding: 'expanding.boxwidget',
  150. expanded: 'expanded.boxwidget',
  151. removing: 'removing.boxwidget',
  152. removed: 'removed.boxwidget'
  153. };
  154. // BoxWidget Class Definition
  155. // =====================
  156. var BoxWidget = function (element, options) {
  157. this.element = element;
  158. this.options = options;
  159. this._setUpListeners();
  160. };
  161. BoxWidget.prototype.toggle = function () {
  162. var isOpen = !$(this.element).is(Selector.collapsed);
  163. if (isOpen) {
  164. this.collapse();
  165. } else {
  166. this.expand();
  167. }
  168. };
  169. BoxWidget.prototype.expand = function () {
  170. var expandedEvent = $.Event(Event.expanded);
  171. var expandingEvent = $.Event(Event.expanding);
  172. var collapseIcon = this.options.collapseIcon;
  173. var expandIcon = this.options.expandIcon;
  174. $(this.element).removeClass(ClassName.collapsed);
  175. $(this.element)
  176. .children(Selector.header + ', ' + Selector.body + ', ' + Selector.footer)
  177. .children(Selector.tools)
  178. .find('.' + expandIcon)
  179. .removeClass(expandIcon)
  180. .addClass(collapseIcon);
  181. $(this.element).children(Selector.body + ', ' + Selector.footer)
  182. .slideDown(this.options.animationSpeed, function () {
  183. $(this.element).trigger(expandedEvent);
  184. }.bind(this))
  185. .trigger(expandingEvent);
  186. };
  187. BoxWidget.prototype.collapse = function () {
  188. var collapsedEvent = $.Event(Event.collapsed);
  189. var collapsingEvent = $.Event(Event.collapsing);
  190. var collapseIcon = this.options.collapseIcon;
  191. var expandIcon = this.options.expandIcon;
  192. $(this.element)
  193. .children(Selector.header + ', ' + Selector.body + ', ' + Selector.footer)
  194. .children(Selector.tools)
  195. .find('.' + collapseIcon)
  196. .removeClass(collapseIcon)
  197. .addClass(expandIcon);
  198. $(this.element).children(Selector.body + ', ' + Selector.footer)
  199. .slideUp(this.options.animationSpeed, function () {
  200. $(this.element).addClass(ClassName.collapsed);
  201. $(this.element).trigger(collapsedEvent);
  202. }.bind(this))
  203. .trigger(collapsingEvent);
  204. };
  205. BoxWidget.prototype.remove = function () {
  206. var removedEvent = $.Event(Event.removed);
  207. var removingEvent = $.Event(Event.removing);
  208. $(this.element).slideUp(this.options.animationSpeed, function () {
  209. $(this.element).trigger(removedEvent);
  210. $(this.element).remove();
  211. }.bind(this))
  212. .trigger(removingEvent);
  213. };
  214. // Private
  215. BoxWidget.prototype._setUpListeners = function () {
  216. var that = this;
  217. $(this.element).on('click', this.options.collapseTrigger, function (event) {
  218. if (event) event.preventDefault();
  219. that.toggle($(this));
  220. return false;
  221. });
  222. $(this.element).on('click', this.options.removeTrigger, function (event) {
  223. if (event) event.preventDefault();
  224. that.remove($(this));
  225. return false;
  226. });
  227. };
  228. // Plugin Definition
  229. // =================
  230. function Plugin(option) {
  231. return this.each(function () {
  232. var $this = $(this);
  233. var data = $this.data(DataKey);
  234. if (!data) {
  235. var options = $.extend({}, Default, $this.data(), typeof option == 'object' && option);
  236. $this.data(DataKey, (data = new BoxWidget($this, options)));
  237. }
  238. if (typeof option == 'string') {
  239. if (typeof data[option] == 'undefined') {
  240. throw new Error('No method named ' + option);
  241. }
  242. data[option]();
  243. }
  244. });
  245. }
  246. var old = $.fn.boxWidget;
  247. $.fn.boxWidget = Plugin;
  248. $.fn.boxWidget.Constructor = BoxWidget;
  249. // No Conflict Mode
  250. // ================
  251. $.fn.boxWidget.noConflict = function () {
  252. $.fn.boxWidget = old;
  253. return this;
  254. };
  255. // BoxWidget Data API
  256. // ==================
  257. $(window).on('load', function () {
  258. $(Selector.data).each(function () {
  259. Plugin.call($(this));
  260. });
  261. });
  262. }(jQuery);
  263. /* ControlSidebar()
  264. * ===============
  265. * Toggles the state of the control sidebar
  266. *
  267. * @Usage: $('#control-sidebar-trigger').controlSidebar(options)
  268. * or add [data-toggle="control-sidebar"] to the trigger
  269. * Pass any option as data-option="value"
  270. */
  271. +function ($) {
  272. 'use strict';
  273. var DataKey = 'lte.controlsidebar';
  274. var Default = {
  275. controlsidebarSlide: true
  276. };
  277. var Selector = {
  278. sidebar: '.control-sidebar',
  279. data : '[data-toggle="control-sidebar"]',
  280. open : '.control-sidebar-open',
  281. bg : '.control-sidebar-bg',
  282. wrapper: '.wrapper',
  283. content: '.content-wrapper',
  284. boxed : '.layout-boxed'
  285. };
  286. var ClassName = {
  287. open: 'control-sidebar-open',
  288. transition: 'control-sidebar-hold-transition',
  289. fixed: 'fixed'
  290. };
  291. var Event = {
  292. collapsed: 'collapsed.controlsidebar',
  293. expanded : 'expanded.controlsidebar'
  294. };
  295. // ControlSidebar Class Definition
  296. // ===============================
  297. var ControlSidebar = function (element, options) {
  298. this.element = element;
  299. this.options = options;
  300. this.hasBindedResize = false;
  301. this.init();
  302. };
  303. ControlSidebar.prototype.init = function () {
  304. // Add click listener if the element hasn't been
  305. // initialized using the data API
  306. if (!$(this.element).is(Selector.data)) {
  307. $(this).on('click', this.toggle);
  308. }
  309. this.fix();
  310. $(window).resize(function () {
  311. this.fix();
  312. }.bind(this));
  313. };
  314. ControlSidebar.prototype.toggle = function (event) {
  315. if (event) event.preventDefault();
  316. this.fix();
  317. if (!$(Selector.sidebar).is(Selector.open) && !$('body').is(Selector.open)) {
  318. this.expand();
  319. } else {
  320. this.collapse();
  321. }
  322. };
  323. ControlSidebar.prototype.expand = function () {
  324. $(Selector.sidebar).show();
  325. if (!this.options.controlsidebarSlide) {
  326. $('body').addClass(ClassName.transition).addClass(ClassName.open).delay(50).queue(function(){
  327. $('body').removeClass(ClassName.transition);
  328. $(this).dequeue()
  329. })
  330. } else {
  331. $(Selector.sidebar).addClass(ClassName.open);
  332. }
  333. $(this.element).trigger($.Event(Event.expanded));
  334. };
  335. ControlSidebar.prototype.collapse = function () {
  336. if (!this.options.controlsidebarSlide) {
  337. $('body').addClass(ClassName.transition).removeClass(ClassName.open).delay(50).queue(function(){
  338. $('body').removeClass(ClassName.transition);
  339. $(this).dequeue()
  340. })
  341. } else {
  342. $(Selector.sidebar).removeClass(ClassName.open);
  343. }
  344. $(Selector.sidebar).fadeOut();
  345. $(this.element).trigger($.Event(Event.collapsed));
  346. };
  347. ControlSidebar.prototype.fix = function () {
  348. if ($('body').is(Selector.boxed)) {
  349. this._fixForBoxed($(Selector.bg));
  350. }
  351. };
  352. // Private
  353. ControlSidebar.prototype._fixForBoxed = function (bg) {
  354. bg.css({
  355. position: 'absolute',
  356. height : $(Selector.wrapper).height()
  357. });
  358. };
  359. // Plugin Definition
  360. // =================
  361. function Plugin(option) {
  362. return this.each(function () {
  363. var $this = $(this);
  364. var data = $this.data(DataKey);
  365. if (!data) {
  366. var options = $.extend({}, Default, $this.data(), typeof option == 'object' && option);
  367. $this.data(DataKey, (data = new ControlSidebar($this, options)));
  368. }
  369. if (typeof option == 'string') data.toggle();
  370. });
  371. }
  372. var old = $.fn.controlSidebar;
  373. $.fn.controlSidebar = Plugin;
  374. $.fn.controlSidebar.Constructor = ControlSidebar;
  375. // No Conflict Mode
  376. // ================
  377. $.fn.controlSidebar.noConflict = function () {
  378. $.fn.controlSidebar = old;
  379. return this;
  380. };
  381. // ControlSidebar Data API
  382. // =======================
  383. $(document).on('click', Selector.data, function (event) {
  384. if (event) event.preventDefault();
  385. Plugin.call($(this), 'toggle');
  386. });
  387. }(jQuery);
  388. /* DirectChat()
  389. * ===============
  390. * Toggles the state of the control sidebar
  391. *
  392. * @Usage: $('#my-chat-box').directChat()
  393. * or add [data-widget="direct-chat"] to the trigger
  394. */
  395. +function ($) {
  396. 'use strict';
  397. var DataKey = 'lte.directchat';
  398. var Selector = {
  399. data: '[data-widget="chat-pane-toggle"]',
  400. box : '.direct-chat'
  401. };
  402. var ClassName = {
  403. open: 'direct-chat-contacts-open'
  404. };
  405. // DirectChat Class Definition
  406. // ===========================
  407. var DirectChat = function (element) {
  408. this.element = element;
  409. };
  410. DirectChat.prototype.toggle = function ($trigger) {
  411. $trigger.parents(Selector.box).first().toggleClass(ClassName.open);
  412. };
  413. // Plugin Definition
  414. // =================
  415. function Plugin(option) {
  416. return this.each(function () {
  417. var $this = $(this);
  418. var data = $this.data(DataKey);
  419. if (!data) {
  420. $this.data(DataKey, (data = new DirectChat($this)));
  421. }
  422. if (typeof option == 'string') data.toggle($this);
  423. });
  424. }
  425. var old = $.fn.directChat;
  426. $.fn.directChat = Plugin;
  427. $.fn.directChat.Constructor = DirectChat;
  428. // No Conflict Mode
  429. // ================
  430. $.fn.directChat.noConflict = function () {
  431. $.fn.directChat = old;
  432. return this;
  433. };
  434. // DirectChat Data API
  435. // ===================
  436. $(document).on('click', Selector.data, function (event) {
  437. if (event) event.preventDefault();
  438. Plugin.call($(this), 'toggle');
  439. });
  440. }(jQuery);
  441. /* PushMenu()
  442. * ==========
  443. * Adds the push menu functionality to the sidebar.
  444. *
  445. * @usage: $('.btn').pushMenu(options)
  446. * or add [data-toggle="push-menu"] to any button
  447. * Pass any option as data-option="value"
  448. */
  449. +function ($) {
  450. 'use strict';
  451. var DataKey = 'lte.pushmenu';
  452. var Default = {
  453. collapseScreenSize : 767,
  454. expandOnHover : false,
  455. expandTransitionDelay: 200
  456. };
  457. var Selector = {
  458. collapsed : '.sidebar-collapse',
  459. open : '.sidebar-open',
  460. mainSidebar : '.main-sidebar',
  461. contentWrapper: '.content-wrapper',
  462. searchInput : '.sidebar-form .form-control',
  463. button : '[data-toggle="push-menu"]',
  464. mini : '.sidebar-mini',
  465. expanded : '.sidebar-expanded-on-hover',
  466. layoutFixed : '.fixed'
  467. };
  468. var ClassName = {
  469. collapsed : 'sidebar-collapse',
  470. open : 'sidebar-open',
  471. mini : 'sidebar-mini',
  472. expanded : 'sidebar-expanded-on-hover',
  473. expandFeature: 'sidebar-mini-expand-feature',
  474. layoutFixed : 'fixed'
  475. };
  476. var Event = {
  477. expanded : 'expanded.pushMenu',
  478. collapsed: 'collapsed.pushMenu'
  479. };
  480. // PushMenu Class Definition
  481. // =========================
  482. var PushMenu = function (options) {
  483. this.options = options;
  484. this.init();
  485. };
  486. PushMenu.prototype.init = function () {
  487. if (this.options.expandOnHover
  488. || ($('body').is(Selector.mini + Selector.layoutFixed))) {
  489. this.expandOnHover();
  490. $('body').addClass(ClassName.expandFeature);
  491. }
  492. $(Selector.contentWrapper).click(function () {
  493. // Enable hide menu when clicking on the content-wrapper on small screens
  494. if ($(window).width() <= this.options.collapseScreenSize && $('body').hasClass(ClassName.open)) {
  495. this.close();
  496. }
  497. }.bind(this));
  498. // __Fix for android devices
  499. $(Selector.searchInput).click(function (e) {
  500. e.stopPropagation();
  501. });
  502. };
  503. PushMenu.prototype.toggle = function () {
  504. var windowWidth = $(window).width();
  505. var isOpen = !$('body').hasClass(ClassName.collapsed);
  506. if (windowWidth <= this.options.collapseScreenSize) {
  507. isOpen = $('body').hasClass(ClassName.open);
  508. }
  509. if (!isOpen) {
  510. this.open();
  511. } else {
  512. this.close();
  513. }
  514. };
  515. PushMenu.prototype.open = function () {
  516. var windowWidth = $(window).width();
  517. if (windowWidth > this.options.collapseScreenSize) {
  518. $('body').removeClass(ClassName.collapsed)
  519. .trigger($.Event(Event.expanded));
  520. }
  521. else {
  522. $('body').addClass(ClassName.open)
  523. .trigger($.Event(Event.expanded));
  524. }
  525. };
  526. PushMenu.prototype.close = function () {
  527. var windowWidth = $(window).width();
  528. if (windowWidth > this.options.collapseScreenSize) {
  529. $('body').addClass(ClassName.collapsed)
  530. .trigger($.Event(Event.collapsed));
  531. } else {
  532. $('body').removeClass(ClassName.open + ' ' + ClassName.collapsed)
  533. .trigger($.Event(Event.collapsed));
  534. }
  535. };
  536. PushMenu.prototype.expandOnHover = function () {
  537. $(Selector.mainSidebar).hover(function () {
  538. if ($('body').is(Selector.mini + Selector.collapsed)
  539. && $(window).width() > this.options.collapseScreenSize) {
  540. this.expand();
  541. }
  542. }.bind(this), function () {
  543. if ($('body').is(Selector.expanded)) {
  544. this.collapse();
  545. }
  546. }.bind(this));
  547. };
  548. PushMenu.prototype.expand = function () {
  549. setTimeout(function () {
  550. $('body').removeClass(ClassName.collapsed)
  551. .addClass(ClassName.expanded);
  552. }, this.options.expandTransitionDelay);
  553. };
  554. PushMenu.prototype.collapse = function () {
  555. setTimeout(function () {
  556. $('body').removeClass(ClassName.expanded)
  557. .addClass(ClassName.collapsed);
  558. }, this.options.expandTransitionDelay);
  559. };
  560. // PushMenu Plugin Definition
  561. // ==========================
  562. function Plugin(option) {
  563. return this.each(function () {
  564. var $this = $(this);
  565. var data = $this.data(DataKey);
  566. if (!data) {
  567. var options = $.extend({}, Default, $this.data(), typeof option == 'object' && option);
  568. $this.data(DataKey, (data = new PushMenu(options)));
  569. }
  570. if (option === 'toggle') data.toggle();
  571. });
  572. }
  573. var old = $.fn.pushMenu;
  574. $.fn.pushMenu = Plugin;
  575. $.fn.pushMenu.Constructor = PushMenu;
  576. // No Conflict Mode
  577. // ================
  578. $.fn.pushMenu.noConflict = function () {
  579. $.fn.pushMenu = old;
  580. return this;
  581. };
  582. // Data API
  583. // ========
  584. $(document).on('click', Selector.button, function (e) {
  585. e.preventDefault();
  586. Plugin.call($(this), 'toggle');
  587. });
  588. $(window).on('load', function () {
  589. Plugin.call($(Selector.button));
  590. });
  591. }(jQuery);
  592. /* TodoList()
  593. * =========
  594. * Converts a list into a todoList.
  595. *
  596. * @Usage: $('.my-list').todoList(options)
  597. * or add [data-widget="todo-list"] to the ul element
  598. * Pass any option as data-option="value"
  599. */
  600. +function ($) {
  601. 'use strict';
  602. var DataKey = 'lte.todolist';
  603. var Default = {
  604. onCheck : function (item) {
  605. return item;
  606. },
  607. onUnCheck: function (item) {
  608. return item;
  609. }
  610. };
  611. var Selector = {
  612. data: '[data-widget="todo-list"]'
  613. };
  614. var ClassName = {
  615. done: 'done'
  616. };
  617. // TodoList Class Definition
  618. // =========================
  619. var TodoList = function (element, options) {
  620. this.element = element;
  621. this.options = options;
  622. this._setUpListeners();
  623. };
  624. TodoList.prototype.toggle = function (item) {
  625. item.parents(Selector.li).first().toggleClass(ClassName.done);
  626. if (!item.prop('checked')) {
  627. this.unCheck(item);
  628. return;
  629. }
  630. this.check(item);
  631. };
  632. TodoList.prototype.check = function (item) {
  633. this.options.onCheck.call(item);
  634. };
  635. TodoList.prototype.unCheck = function (item) {
  636. this.options.onUnCheck.call(item);
  637. };
  638. // Private
  639. TodoList.prototype._setUpListeners = function () {
  640. var that = this;
  641. $(this.element).on('change ifChanged', 'input:checkbox', function () {
  642. that.toggle($(this));
  643. });
  644. };
  645. // Plugin Definition
  646. // =================
  647. function Plugin(option) {
  648. return this.each(function () {
  649. var $this = $(this);
  650. var data = $this.data(DataKey);
  651. if (!data) {
  652. var options = $.extend({}, Default, $this.data(), typeof option == 'object' && option);
  653. $this.data(DataKey, (data = new TodoList($this, options)));
  654. }
  655. if (typeof data == 'string') {
  656. if (typeof data[option] == 'undefined') {
  657. throw new Error('No method named ' + option);
  658. }
  659. data[option]();
  660. }
  661. });
  662. }
  663. var old = $.fn.todoList;
  664. $.fn.todoList = Plugin;
  665. $.fn.todoList.Constructor = TodoList;
  666. // No Conflict Mode
  667. // ================
  668. $.fn.todoList.noConflict = function () {
  669. $.fn.todoList = old;
  670. return this;
  671. };
  672. // TodoList Data API
  673. // =================
  674. $(window).on('load', function () {
  675. $(Selector.data).each(function () {
  676. Plugin.call($(this));
  677. });
  678. });
  679. }(jQuery);
  680. /* Tree()
  681. * ======
  682. * Converts a nested list into a multilevel
  683. * tree view menu.
  684. *
  685. * @Usage: $('.my-menu').tree(options)
  686. * or add [data-widget="tree"] to the ul element
  687. * Pass any option as data-option="value"
  688. */
  689. +function ($) {
  690. 'use strict';
  691. var DataKey = 'lte.tree';
  692. var Default = {
  693. animationSpeed: 500,
  694. accordion : true,
  695. followLink : false,
  696. trigger : '.treeview a'
  697. };
  698. var Selector = {
  699. tree : '.tree',
  700. treeview : '.treeview',
  701. treeviewMenu: '.treeview-menu',
  702. open : '.menu-open, .active',
  703. li : 'li',
  704. data : '[data-widget="tree"]',
  705. active : '.active'
  706. };
  707. var ClassName = {
  708. open: 'menu-open',
  709. tree: 'tree'
  710. };
  711. var Event = {
  712. collapsed: 'collapsed.tree',
  713. expanded : 'expanded.tree'
  714. };
  715. // Tree Class Definition
  716. // =====================
  717. var Tree = function (element, options) {
  718. this.element = element;
  719. this.options = options;
  720. $(this.element).addClass(ClassName.tree);
  721. $(Selector.treeview + Selector.active, this.element).addClass(ClassName.open);
  722. this._setUpListeners();
  723. };
  724. Tree.prototype.toggle = function (link, event) {
  725. var treeviewMenu = link.next(Selector.treeviewMenu);
  726. var parentLi = link.parent();
  727. var isOpen = parentLi.hasClass(ClassName.open);
  728. if (!parentLi.is(Selector.treeview)) {
  729. return;
  730. }
  731. if (!this.options.followLink || link.attr('href') === '#') {
  732. event.preventDefault();
  733. }
  734. if (isOpen) {
  735. this.collapse(treeviewMenu, parentLi);
  736. } else {
  737. this.expand(treeviewMenu, parentLi);
  738. }
  739. };
  740. Tree.prototype.expand = function (tree, parent) {
  741. var expandedEvent = $.Event(Event.expanded);
  742. if (this.options.accordion) {
  743. var openMenuLi = parent.siblings(Selector.open);
  744. var openTree = openMenuLi.children(Selector.treeviewMenu);
  745. this.collapse(openTree, openMenuLi);
  746. }
  747. parent.addClass(ClassName.open);
  748. tree.stop().slideDown(this.options.animationSpeed, function () {
  749. $(this.element).trigger(expandedEvent);
  750. parent.height('auto');
  751. }.bind(this));
  752. };
  753. Tree.prototype.collapse = function (tree, parentLi) {
  754. var collapsedEvent = $.Event(Event.collapsed);
  755. //tree.find(Selector.open).removeClass(ClassName.open);
  756. parentLi.removeClass(ClassName.open);
  757. tree.stop().slideUp(this.options.animationSpeed, function () {
  758. //tree.find(Selector.open + ' > ' + Selector.treeview).slideUp();
  759. $(this.element).trigger(collapsedEvent);
  760. // Collapse child items
  761. parentLi.find(Selector.treeview).removeClass(ClassName.open).find(Selector.treeviewMenu).hide();
  762. }.bind(this));
  763. };
  764. // Private
  765. Tree.prototype._setUpListeners = function () {
  766. var that = this;
  767. $(this.element).on('click', this.options.trigger, function (event) {
  768. that.toggle($(this), event);
  769. });
  770. };
  771. // Plugin Definition
  772. // =================
  773. function Plugin(option) {
  774. return this.each(function () {
  775. var $this = $(this);
  776. var data = $this.data(DataKey);
  777. if (!data) {
  778. var options = $.extend({}, Default, $this.data(), typeof option == 'object' && option);
  779. $this.data(DataKey, new Tree($this, options));
  780. }
  781. });
  782. }
  783. var old = $.fn.tree;
  784. $.fn.tree = Plugin;
  785. $.fn.tree.Constructor = Tree;
  786. // No Conflict Mode
  787. // ================
  788. $.fn.tree.noConflict = function () {
  789. $.fn.tree = old;
  790. return this;
  791. };
  792. // Tree Data API
  793. // =============
  794. $(window).on('load', function () {
  795. $(Selector.data).each(function () {
  796. Plugin.call($(this));
  797. });
  798. });
  799. }(jQuery);
  800. /* Layout()
  801. * ========
  802. * Implements AdminLTE layout.
  803. * Fixes the layout height in case min-height fails.
  804. *
  805. * @usage activated automatically upon window load.
  806. * Configure any options by passing data-option="value"
  807. * to the body tag.
  808. */
  809. +function ($) {
  810. 'use strict';
  811. var DataKey = 'lte.layout';
  812. var Default = {
  813. slimscroll : true,
  814. resetHeight: true
  815. };
  816. var Selector = {
  817. wrapper : '.wrapper',
  818. contentWrapper: '.content-wrapper',
  819. layoutBoxed : '.layout-boxed',
  820. mainFooter : '.main-footer',
  821. mainHeader : '.main-header',
  822. mainSidebar : '.main-sidebar',
  823. slimScrollDiv : 'slimScrollDiv',
  824. sidebar : '.sidebar',
  825. controlSidebar: '.control-sidebar',
  826. fixed : '.fixed',
  827. sidebarMenu : '.sidebar-menu',
  828. logo : '.main-header .logo'
  829. };
  830. var ClassName = {
  831. fixed : 'fixed',
  832. holdTransition: 'hold-transition'
  833. };
  834. var Layout = function (options) {
  835. this.options = options;
  836. this.bindedResize = false;
  837. this.activate();
  838. };
  839. Layout.prototype.activate = function () {
  840. this.fix();
  841. this.fixSidebar();
  842. $('body').removeClass(ClassName.holdTransition);
  843. if (this.options.resetHeight) {
  844. $('body, html, ' + Selector.wrapper).css({
  845. 'height' : 'auto',
  846. 'min-height': '100%'
  847. });
  848. }
  849. if (!this.bindedResize) {
  850. $(window).resize(function () {
  851. this.fix();
  852. this.fixSidebar();
  853. $(Selector.logo + ', ' + Selector.sidebar).one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function () {
  854. this.fix();
  855. this.fixSidebar();
  856. }.bind(this));
  857. }.bind(this));
  858. this.bindedResize = true;
  859. }
  860. $(Selector.sidebarMenu).on('expanded.tree', function () {
  861. this.fix();
  862. this.fixSidebar();
  863. }.bind(this));
  864. $(Selector.sidebarMenu).on('collapsed.tree', function () {
  865. this.fix();
  866. this.fixSidebar();
  867. }.bind(this));
  868. };
  869. Layout.prototype.fix = function () {
  870. // Remove overflow from .wrapper if layout-boxed exists
  871. $(Selector.layoutBoxed + ' > ' + Selector.wrapper).css('overflow', 'hidden');
  872. // Get window height and the wrapper height
  873. var footerHeight = $(Selector.mainFooter).outerHeight() || 0;
  874. var headerHeight = $(Selector.mainHeader).outerHeight() || 0;
  875. var neg = headerHeight + footerHeight;
  876. var windowHeight = $(window).height();
  877. var sidebarHeight = $(Selector.sidebar).outerHeight() || 0;
  878. // Set the min-height of the content and sidebar based on
  879. // the height of the document.
  880. if ($('body').hasClass(ClassName.fixed)) {
  881. $(Selector.contentWrapper).css('min-height', windowHeight - footerHeight);
  882. } else {
  883. var postSetHeight;
  884. if (windowHeight >= sidebarHeight + headerHeight) {
  885. $(Selector.contentWrapper).css('min-height', windowHeight - neg);
  886. postSetHeight = windowHeight - neg;
  887. } else {
  888. $(Selector.contentWrapper).css('min-height', sidebarHeight);
  889. postSetHeight = sidebarHeight;
  890. }
  891. // Fix for the control sidebar height
  892. var $controlSidebar = $(Selector.controlSidebar);
  893. if (typeof $controlSidebar !== 'undefined') {
  894. if ($controlSidebar.height() > postSetHeight)
  895. $(Selector.contentWrapper).css('min-height', $controlSidebar.height());
  896. }
  897. }
  898. };
  899. Layout.prototype.fixSidebar = function () {
  900. // Make sure the body tag has the .fixed class
  901. if (!$('body').hasClass(ClassName.fixed)) {
  902. if (typeof $.fn.slimScroll !== 'undefined') {
  903. $(Selector.sidebar).slimScroll({ destroy: true }).height('auto');
  904. }
  905. return;
  906. }
  907. // Enable slimscroll for fixed layout
  908. if (this.options.slimscroll) {
  909. if (typeof $.fn.slimScroll !== 'undefined') {
  910. // Destroy if it exists
  911. // $(Selector.sidebar).slimScroll({ destroy: true }).height('auto')
  912. // Add slimscroll
  913. if ($(Selector.mainSidebar).find(Selector.slimScrollDiv).length === 0) {
  914. $(Selector.sidebar).slimScroll({
  915. height: ($(window).height() - $(Selector.mainHeader).height()) + 'px'
  916. });
  917. }
  918. }
  919. }
  920. };
  921. // Plugin Definition
  922. // =================
  923. function Plugin(option) {
  924. return this.each(function () {
  925. var $this = $(this);
  926. var data = $this.data(DataKey);
  927. if (!data) {
  928. var options = $.extend({}, Default, $this.data(), typeof option === 'object' && option);
  929. $this.data(DataKey, (data = new Layout(options)));
  930. }
  931. if (typeof option === 'string') {
  932. if (typeof data[option] === 'undefined') {
  933. throw new Error('No method named ' + option);
  934. }
  935. data[option]();
  936. }
  937. });
  938. }
  939. var old = $.fn.layout;
  940. $.fn.layout = Plugin;
  941. $.fn.layout.Constuctor = Layout;
  942. // No conflict mode
  943. // ================
  944. $.fn.layout.noConflict = function () {
  945. $.fn.layout = old;
  946. return this;
  947. };
  948. // Layout DATA-API
  949. // ===============
  950. $(window).on('load', function () {
  951. Plugin.call($('body'));
  952. });
  953. }(jQuery);