app.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. /* ------------------------------------------------------------------------------
  2. *
  3. * # Template JS core
  4. *
  5. * Includes minimum required JS code for proper template functioning
  6. *
  7. * ---------------------------------------------------------------------------- */
  8. // Setup module
  9. // ------------------------------
  10. var App = function () {
  11. //
  12. // Setup module components
  13. //
  14. // Transitions
  15. // -------------------------
  16. // Disable all transitions
  17. var _transitionsDisabled = function() {
  18. $('body').addClass('no-transitions');
  19. };
  20. // Enable all transitions
  21. var _transitionsEnabled = function() {
  22. $('body').removeClass('no-transitions');
  23. };
  24. // Sidebars
  25. // -------------------------
  26. //
  27. // On desktop
  28. //
  29. // Resize main sidebar
  30. var _sidebarMainResize = function() {
  31. // Flip 2nd level if menu overflows
  32. // bottom edge of browser window
  33. var revertBottomMenus = function() {
  34. $('.sidebar-main').find('.nav-sidebar').children('.nav-item-submenu').hover(function() {
  35. var totalHeight = 0,
  36. $this = $(this),
  37. navSubmenuClass = 'nav-group-sub',
  38. navSubmenuReversedClass = 'nav-item-submenu-reversed';
  39. totalHeight += $this.find('.' + navSubmenuClass).filter(':visible').outerHeight();
  40. if($this.children('.' + navSubmenuClass).length) {
  41. if(($this.children('.' + navSubmenuClass).offset().top + $this.find('.' + navSubmenuClass).filter(':visible').outerHeight()) > document.body.clientHeight) {
  42. $this.addClass(navSubmenuReversedClass)
  43. }
  44. else {
  45. $this.removeClass(navSubmenuReversedClass)
  46. }
  47. }
  48. });
  49. }
  50. // If sidebar is resized by default
  51. if($('body').hasClass('sidebar-xs')) {
  52. revertBottomMenus();
  53. }
  54. // Toggle min sidebar class
  55. $('.sidebar-main-toggle').on('click', function (e) {
  56. e.preventDefault();
  57. $('body').toggleClass('sidebar-xs').removeClass('sidebar-mobile-main');
  58. revertBottomMenus();
  59. });
  60. };
  61. // Toggle main sidebar
  62. var _sidebarMainToggle = function() {
  63. $(document).on('click', '.sidebar-main-hide', function (e) {
  64. e.preventDefault();
  65. $('body').toggleClass('sidebar-main-hidden');
  66. });
  67. };
  68. // Toggle secondary sidebar
  69. var _sidebarSecondaryToggle = function() {
  70. $(document).on('click', '.sidebar-secondary-toggle', function (e) {
  71. e.preventDefault();
  72. $('body').toggleClass('sidebar-secondary-hidden');
  73. });
  74. };
  75. // Show right, resize main
  76. var _sidebarRightMainToggle = function() {
  77. $(document).on('click', '.sidebar-right-main-toggle', function (e) {
  78. e.preventDefault();
  79. // Right sidebar visibility
  80. $('body').toggleClass('sidebar-right-visible');
  81. // If visible
  82. if ($('body').hasClass('sidebar-right-visible')) {
  83. // Make main sidebar mini
  84. $('body').addClass('sidebar-xs');
  85. // Hide children lists if they are opened, since sliding animation adds inline CSS
  86. $('.sidebar-main .nav-sidebar').children('.nav-item').children('.nav-group-sub').css('display', '');
  87. }
  88. else {
  89. $('body').removeClass('sidebar-xs');
  90. }
  91. });
  92. };
  93. // Show right, hide main
  94. var _sidebarRightMainHide = function() {
  95. $(document).on('click', '.sidebar-right-main-hide', function (e) {
  96. e.preventDefault();
  97. // Opposite sidebar visibility
  98. $('body').toggleClass('sidebar-right-visible');
  99. // If visible
  100. if ($('body').hasClass('sidebar-right-visible')) {
  101. $('body').addClass('sidebar-main-hidden');
  102. }
  103. else {
  104. $('body').removeClass('sidebar-main-hidden');
  105. }
  106. });
  107. };
  108. // Toggle right sidebar
  109. var _sidebarRightToggle = function() {
  110. $(document).on('click', '.sidebar-right-toggle', function (e) {
  111. e.preventDefault();
  112. $('body').toggleClass('sidebar-right-visible');
  113. });
  114. };
  115. // Show right, hide secondary
  116. var _sidebarRightSecondaryToggle = function() {
  117. $(document).on('click', '.sidebar-right-secondary-toggle', function (e) {
  118. e.preventDefault();
  119. // Opposite sidebar visibility
  120. $('body').toggleClass('sidebar-right-visible');
  121. // If visible
  122. if ($('body').hasClass('sidebar-right-visible')) {
  123. $('body').addClass('sidebar-secondary-hidden');
  124. }
  125. else {
  126. $('body').removeClass('sidebar-secondary-hidden');
  127. }
  128. });
  129. };
  130. // Toggle content sidebar
  131. var _sidebarComponentToggle = function() {
  132. $(document).on('click', '.sidebar-component-toggle', function (e) {
  133. e.preventDefault();
  134. $('body').toggleClass('sidebar-component-hidden');
  135. });
  136. };
  137. //
  138. // On mobile
  139. //
  140. // Expand sidebar to full screen on mobile
  141. var _sidebarMobileFullscreen = function() {
  142. $('.sidebar-mobile-expand').on('click', function (e) {
  143. e.preventDefault();
  144. var $sidebar = $(this).parents('.sidebar'),
  145. sidebarFullscreenClass = 'sidebar-fullscreen'
  146. if(!$sidebar.hasClass(sidebarFullscreenClass)) {
  147. $sidebar.addClass(sidebarFullscreenClass);
  148. }
  149. else {
  150. $sidebar.removeClass(sidebarFullscreenClass);
  151. }
  152. });
  153. };
  154. // Toggle main sidebar on mobile
  155. var _sidebarMobileMainToggle = function() {
  156. $('.sidebar-mobile-main-toggle').on('click', function(e) {
  157. e.preventDefault();
  158. $('body').toggleClass('sidebar-mobile-main').removeClass('sidebar-mobile-secondary sidebar-mobile-right');
  159. if($('.sidebar-main').hasClass('sidebar-fullscreen')) {
  160. $('.sidebar-main').removeClass('sidebar-fullscreen');
  161. }
  162. });
  163. };
  164. // Toggle secondary sidebar on mobile
  165. var _sidebarMobileSecondaryToggle = function() {
  166. $('.sidebar-mobile-secondary-toggle').on('click', function (e) {
  167. e.preventDefault();
  168. $('body').toggleClass('sidebar-mobile-secondary').removeClass('sidebar-mobile-main sidebar-mobile-right');
  169. // Fullscreen mode
  170. if($('.sidebar-secondary').hasClass('sidebar-fullscreen')) {
  171. $('.sidebar-secondary').removeClass('sidebar-fullscreen');
  172. }
  173. });
  174. };
  175. // Toggle right sidebar on mobile
  176. var _sidebarMobileRightToggle = function() {
  177. $('.sidebar-mobile-right-toggle').on('click', function (e) {
  178. e.preventDefault();
  179. $('body').toggleClass('sidebar-mobile-right').removeClass('sidebar-mobile-main sidebar-mobile-secondary');
  180. // Hide sidebar if in fullscreen mode on mobile
  181. if($('.sidebar-right').hasClass('sidebar-fullscreen')) {
  182. $('.sidebar-right').removeClass('sidebar-fullscreen');
  183. }
  184. });
  185. };
  186. // Toggle component sidebar on mobile
  187. var _sidebarMobileComponentToggle = function() {
  188. $('.sidebar-mobile-component-toggle').on('click', function (e) {
  189. e.preventDefault();
  190. $('body').toggleClass('sidebar-mobile-component');
  191. });
  192. };
  193. // Navigations
  194. // -------------------------
  195. // Sidebar navigation
  196. var _navigationSidebar = function() {
  197. // Define default class names and options
  198. var navClass = 'nav-sidebar',
  199. navItemClass = 'nav-item',
  200. navItemOpenClass = 'nav-item-open',
  201. navLinkClass = 'nav-link',
  202. navSubmenuClass = 'nav-group-sub',
  203. navSlidingSpeed = 250;
  204. // Configure collapsible functionality
  205. $('.' + navClass).each(function() {
  206. $(this).find('.' + navItemClass).has('.' + navSubmenuClass).children('.' + navItemClass + ' > ' + '.' + navLinkClass).not('.disabled').on('click', function (e) {
  207. e.preventDefault();
  208. // Simplify stuff
  209. var $target = $(this),
  210. $navSidebarMini = $('.sidebar-xs').not('.sidebar-mobile-main').find('.sidebar-main .' + navClass).children('.' + navItemClass);
  211. // Collapsible
  212. if($target.parent('.' + navItemClass).hasClass(navItemOpenClass)) {
  213. $target.parent('.' + navItemClass).not($navSidebarMini).removeClass(navItemOpenClass).children('.' + navSubmenuClass).slideUp(navSlidingSpeed);
  214. }
  215. else {
  216. $target.parent('.' + navItemClass).not($navSidebarMini).addClass(navItemOpenClass).children('.' + navSubmenuClass).slideDown(navSlidingSpeed);
  217. }
  218. // Accordion
  219. if ($target.parents('.' + navClass).data('nav-type') == 'accordion') {
  220. $target.parent('.' + navItemClass).not($navSidebarMini).siblings(':has(.' + navSubmenuClass + ')').removeClass(navItemOpenClass).children('.' + navSubmenuClass).slideUp(navSlidingSpeed);
  221. }
  222. });
  223. });
  224. // Disable click in disabled navigation items
  225. $(document).on('click', '.' + navClass + ' .disabled', function(e) {
  226. e.preventDefault();
  227. });
  228. // Scrollspy navigation
  229. $('.nav-scrollspy').find('.' + navItemClass).has('.' + navSubmenuClass).children('.' + navItemClass + ' > ' + '.' + navLinkClass).off('click');
  230. };
  231. // Navbar navigation
  232. var _navigationNavbar = function() {
  233. // Prevent dropdown from closing on click
  234. $(document).on('click', '.dropdown-content', function(e) {
  235. e.stopPropagation();
  236. });
  237. // Disabled links
  238. $('.navbar-nav .disabled a, .nav-item-levels .disabled').on('click', function(e) {
  239. e.preventDefault();
  240. e.stopPropagation();
  241. });
  242. // Show tabs inside dropdowns
  243. $('.dropdown-content a[data-toggle="tab"]').on('click', function(e) {
  244. $(this).tab('show');
  245. });
  246. };
  247. // Components
  248. // -------------------------
  249. // Tooltip
  250. var _componentTooltip = function() {
  251. // Initialize
  252. $('[data-popup="tooltip"]').tooltip();
  253. // Demo tooltips, remove in production
  254. var demoTooltipSelector = '[data-popup="tooltip-demo"]';
  255. if($(demoTooltipSelector).is(':visible')) {
  256. $(demoTooltipSelector).tooltip('show');
  257. setTimeout(function() {
  258. $(demoTooltipSelector).tooltip('hide');
  259. }, 2000);
  260. }
  261. };
  262. // Popover
  263. var _componentPopover = function() {
  264. $('[data-popup="popover"]').popover();
  265. };
  266. // Card actions
  267. // -------------------------
  268. // Reload card (uses BlockUI extension)
  269. var _cardActionReload = function() {
  270. $('.card [data-action=reload]:not(.disabled)').on('click', function (e) {
  271. e.preventDefault();
  272. var $target = $(this),
  273. block = $target.closest('.card');
  274. // Block card
  275. $(block).block({
  276. message: '<i class="icon-spinner2 spinner"></i>',
  277. overlayCSS: {
  278. backgroundColor: '#fff',
  279. opacity: 0.8,
  280. cursor: 'wait',
  281. 'box-shadow': '0 0 0 1px #ddd'
  282. },
  283. css: {
  284. border: 0,
  285. padding: 0,
  286. backgroundColor: 'none'
  287. }
  288. });
  289. // For demo purposes
  290. window.setTimeout(function () {
  291. $(block).unblock();
  292. }, 2000);
  293. });
  294. };
  295. // Collapse card
  296. var _cardActionCollapse = function() {
  297. var $cardCollapsedClass = $('.card-collapsed');
  298. // Hide if collapsed by default
  299. $cardCollapsedClass.children('.card-header').nextAll().hide();
  300. // Rotate icon if collapsed by default
  301. $cardCollapsedClass.find('[data-action=collapse]').addClass('rotate-180');
  302. // Collapse on click
  303. $('.card [data-action=collapse]:not(.disabled)').on('click', function (e) {
  304. var $target = $(this),
  305. slidingSpeed = 150;
  306. e.preventDefault();
  307. $target.parents('.card').toggleClass('card-collapsed');
  308. $target.toggleClass('rotate-180');
  309. $target.closest('.card').children('.card-header').nextAll().slideToggle(slidingSpeed);
  310. });
  311. };
  312. // Remove card
  313. var _cardActionRemove = function() {
  314. $('.card [data-action=remove]').on('click', function (e) {
  315. e.preventDefault();
  316. var $target = $(this),
  317. slidingSpeed = 150;
  318. // If not disabled
  319. if(!$target.hasClass('disabled')) {
  320. $target.closest('.card').slideUp({
  321. duration: slidingSpeed,
  322. start: function() {
  323. $target.addClass('d-block');
  324. },
  325. complete: function() {
  326. $target.remove();
  327. }
  328. });
  329. }
  330. });
  331. };
  332. // Card fullscreen mode
  333. var _cardActionFullscreen = function() {
  334. $('.card [data-action=fullscreen]').on('click', function (e) {
  335. e.preventDefault();
  336. // Define vars
  337. var $target = $(this),
  338. cardFullscreen = $target.closest('.card'),
  339. overflowHiddenClass = 'overflow-hidden',
  340. collapsedClass = 'collapsed-in-fullscreen',
  341. fullscreenAttr = 'data-fullscreen';
  342. // Toggle classes on card
  343. cardFullscreen.toggleClass('fixed-top h-100 rounded-0');
  344. // Configure
  345. if (!cardFullscreen.hasClass('fixed-top')) {
  346. $target.removeAttr(fullscreenAttr);
  347. cardFullscreen.children('.' + collapsedClass).removeClass('show');
  348. $('body').removeClass(overflowHiddenClass);
  349. $target.siblings('[data-action=move], [data-action=remove], [data-action=collapse]').removeClass('d-none');
  350. }
  351. else {
  352. $target.attr(fullscreenAttr, 'active');
  353. cardFullscreen.removeAttr('style').children('.collapse:not(.show)').addClass('show ' + collapsedClass);
  354. $('body').addClass(overflowHiddenClass);
  355. $target.siblings('[data-action=move], [data-action=remove], [data-action=collapse]').addClass('d-none');
  356. }
  357. });
  358. };
  359. // Misc
  360. // -------------------------
  361. // Dropdown submenus. Trigger on click
  362. var _dropdownSubmenu = function() {
  363. // All parent levels require .dropdown-toggle class
  364. $('.dropdown-menu').find('.dropdown-submenu').not('.disabled').find('.dropdown-toggle').on('click', function(e) {
  365. e.stopPropagation();
  366. e.preventDefault();
  367. // Remove "show" class in all siblings
  368. $(this).parent().siblings().removeClass('show').find('.show').removeClass('show');
  369. // Toggle submenu
  370. $(this).parent().toggleClass('show').children('.dropdown-menu').toggleClass('show');
  371. // Hide all levels when parent dropdown is closed
  372. $(this).parents('.show').on('hidden.bs.dropdown', function(e) {
  373. $('.dropdown-submenu .show, .dropdown-submenu.show').removeClass('show');
  374. });
  375. });
  376. };
  377. // Header elements toggler
  378. var _headerElements = function() {
  379. // Toggle visible state of header elements
  380. $('.header-elements-toggle').on('click', function(e) {
  381. e.preventDefault();
  382. $(this).parents('[class*=header-elements-]').find('.header-elements').toggleClass('d-none');
  383. });
  384. // Toggle visible state of footer elements
  385. $('.footer-elements-toggle').on('click', function(e) {
  386. e.preventDefault();
  387. $(this).parents('.card-footer').find('.footer-elements').toggleClass('d-none');
  388. });
  389. };
  390. //
  391. // Return objects assigned to module
  392. //
  393. return {
  394. // Disable transitions before page is fully loaded
  395. initBeforeLoad: function() {
  396. _transitionsDisabled();
  397. },
  398. // Enable transitions when page is fully loaded
  399. initAfterLoad: function() {
  400. _transitionsEnabled();
  401. },
  402. // Initialize all sidebars
  403. initSidebars: function() {
  404. // On desktop
  405. _sidebarMainResize();
  406. _sidebarMainToggle();
  407. _sidebarSecondaryToggle();
  408. _sidebarRightMainToggle();
  409. _sidebarRightMainHide();
  410. _sidebarRightToggle();
  411. _sidebarRightSecondaryToggle();
  412. _sidebarComponentToggle();
  413. // On mobile
  414. _sidebarMobileFullscreen();
  415. _sidebarMobileMainToggle();
  416. _sidebarMobileSecondaryToggle();
  417. _sidebarMobileRightToggle();
  418. _sidebarMobileComponentToggle();
  419. },
  420. // Initialize all navigations
  421. initNavigations: function() {
  422. _navigationSidebar();
  423. _navigationNavbar();
  424. },
  425. // Initialize all components
  426. initComponents: function() {
  427. _componentTooltip();
  428. _componentPopover();
  429. },
  430. // Initialize all card actions
  431. initCardActions: function() {
  432. _cardActionReload();
  433. _cardActionCollapse();
  434. _cardActionRemove();
  435. _cardActionFullscreen();
  436. },
  437. // Dropdown submenu
  438. initDropdownSubmenu: function() {
  439. _dropdownSubmenu();
  440. },
  441. initHeaderElementsToggle: function() {
  442. _headerElements();
  443. },
  444. // Initialize core
  445. initCore: function() {
  446. App.initSidebars();
  447. App.initNavigations();
  448. App.initComponents();
  449. App.initCardActions();
  450. App.initDropdownSubmenu();
  451. App.initHeaderElementsToggle();
  452. }
  453. }
  454. }();
  455. // Initialize module
  456. // ------------------------------
  457. // When content is loaded
  458. document.addEventListener('DOMContentLoaded', function() {
  459. App.initBeforeLoad();
  460. App.initCore();
  461. });
  462. // When page is fully loaded
  463. window.addEventListener('load', function() {
  464. App.initAfterLoad();
  465. });