layout.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. /**
  2. Core script to handle the entire theme and core functions
  3. **/
  4. var Layout = function() {
  5. var layoutImgPath = 'admin/layout/img/';
  6. var layoutCssPath = 'admin/layout/css/';
  7. var resBreakpointMd = Metronic.getResponsiveBreakpoint('md');
  8. //* BEGIN:CORE HANDLERS *//
  9. // this function handles responsive layout on screen size resize or mobile device rotate.
  10. // Handle sidebar menu links
  11. var handleSidebarMenuActiveLink = function(mode, el) {
  12. var url = location.hash.toLowerCase();
  13. var menu = $('.page-sidebar-menu');
  14. if (mode === 'click' || mode === 'set') {
  15. el = $(el);
  16. } else if (mode === 'match') {
  17. menu.find("li > a").each(function() {
  18. var path = $(this).attr("href").toLowerCase();
  19. // url match condition
  20. if (path.length > 1 && url.substr(1, path.length - 1) == path.substr(1)) {
  21. el = $(this);
  22. return;
  23. }
  24. });
  25. }
  26. if (!el || el.size() == 0) {
  27. return;
  28. }
  29. if (el.attr('href').toLowerCase() === 'javascript:;' || el.attr('href').toLowerCase() === '#') {
  30. return;
  31. }
  32. var slideSpeed = parseInt(menu.data("slide-speed"));
  33. var keepExpand = menu.data("keep-expanded");
  34. // disable active states
  35. menu.find('li.active').removeClass('active');
  36. menu.find('li > a > .selected').remove();
  37. if (menu.hasClass('page-sidebar-menu-hover-submenu') === false) {
  38. menu.find('li.open').each(function(){
  39. if ($(this).children('.sub-menu').size() === 0) {
  40. $(this).removeClass('open');
  41. $(this).find('> a > .arrow.open').removeClass('open');
  42. }
  43. });
  44. } else {
  45. menu.find('li.open').removeClass('open');
  46. }
  47. el.parents('li').each(function () {
  48. $(this).addClass('active');
  49. $(this).find('> a > span.arrow').addClass('open');
  50. if ($(this).parent('ul.page-sidebar-menu').size() === 1) {
  51. $(this).find('> a').append('<span class="selected"></span>');
  52. }
  53. if ($(this).children('ul.sub-menu').size() === 1) {
  54. $(this).addClass('open');
  55. }
  56. });
  57. if (mode === 'click') {
  58. if (Metronic.getViewPort().width < resBreakpointMd && $('.page-sidebar').hasClass("in")) { // close the menu on mobile view while laoding a page
  59. $('.page-header .responsive-toggler').click();
  60. }
  61. }
  62. };
  63. // Handle sidebar menu
  64. var handleSidebarMenu = function() {
  65. $('.page-sidebar').on('click', 'li > a', function(e) {
  66. if (Metronic.getViewPort().width >= resBreakpointMd && $(this).parents('.page-sidebar-menu-hover-submenu').size() === 1) { // exit of hover sidebar menu
  67. return;
  68. }
  69. if ($(this).next().hasClass('sub-menu') === false) {
  70. if (Metronic.getViewPort().width < resBreakpointMd && $('.page-sidebar').hasClass("in")) { // close the menu on mobile view while laoding a page
  71. $('.page-header .responsive-toggler').click();
  72. }
  73. return;
  74. }
  75. if ($(this).next().hasClass('sub-menu always-open')) {
  76. return;
  77. }
  78. var parent = $(this).parent().parent();
  79. var the = $(this);
  80. var menu = $('.page-sidebar-menu');
  81. var sub = $(this).next();
  82. var autoScroll = menu.data("auto-scroll");
  83. var slideSpeed = parseInt(menu.data("slide-speed"));
  84. var keepExpand = menu.data("keep-expanded");
  85. if (keepExpand !== true) {
  86. parent.children('li.open').children('a').children('.arrow').removeClass('open');
  87. parent.children('li.open').children('.sub-menu:not(.always-open)').slideUp(slideSpeed);
  88. parent.children('li.open').removeClass('open');
  89. }
  90. var slideOffeset = -200;
  91. if (sub.is(":visible")) {
  92. $('.arrow', $(this)).removeClass("open");
  93. $(this).parent().removeClass("open");
  94. sub.slideUp(slideSpeed, function() {
  95. if (autoScroll === true && $('body').hasClass('page-sidebar-closed') === false) {
  96. if ($('body').hasClass('page-sidebar-fixed')) {
  97. menu.slimScroll({
  98. 'scrollTo': (the.position()).top
  99. });
  100. } else {
  101. Metronic.scrollTo(the, slideOffeset);
  102. }
  103. }
  104. });
  105. } else {
  106. $('.arrow', $(this)).addClass("open");
  107. $(this).parent().addClass("open");
  108. sub.slideDown(slideSpeed, function() {
  109. if (autoScroll === true && $('body').hasClass('page-sidebar-closed') === false) {
  110. if ($('body').hasClass('page-sidebar-fixed')) {
  111. menu.slimScroll({
  112. 'scrollTo': (the.position()).top
  113. });
  114. } else {
  115. Metronic.scrollTo(the, slideOffeset);
  116. }
  117. }
  118. });
  119. }
  120. e.preventDefault();
  121. });
  122. // handle ajax links within sidebar menu
  123. $('.page-sidebar').on('click', ' li > a.ajaxify', function(e) {
  124. e.preventDefault();
  125. Metronic.scrollTop();
  126. var url = $(this).attr("href");
  127. var menuContainer = $('.page-sidebar ul');
  128. var pageContent = $('.page-content');
  129. var pageContentBody = $('.page-content .page-content-body');
  130. menuContainer.children('li.active').removeClass('active');
  131. menuContainer.children('arrow.open').removeClass('open');
  132. $(this).parents('li').each(function() {
  133. $(this).addClass('active');
  134. $(this).children('a > span.arrow').addClass('open');
  135. });
  136. $(this).parents('li').addClass('active');
  137. if (Metronic.getViewPort().width < resBreakpointMd && $('.page-sidebar').hasClass("in")) { // close the menu on mobile view while laoding a page
  138. $('.page-header .responsive-toggler').click();
  139. }
  140. Metronic.startPageLoading();
  141. var the = $(this);
  142. $.ajax({
  143. type: "GET",
  144. cache: false,
  145. url: url,
  146. dataType: "html",
  147. success: function(res) {
  148. if (the.parents('li.open').size() === 0) {
  149. $('.page-sidebar-menu > li.open > a').click();
  150. }
  151. Metronic.stopPageLoading();
  152. pageContentBody.html(res);
  153. Layout.fixContentHeight(); // fix content height
  154. Metronic.initAjax(); // initialize core stuff
  155. },
  156. error: function(xhr, ajaxOptions, thrownError) {
  157. Metronic.stopPageLoading();
  158. pageContentBody.html('<h4>Could not load the requested content.</h4>');
  159. }
  160. });
  161. });
  162. // handle ajax link within main content
  163. $('.page-content').on('click', '.ajaxify', function(e) {
  164. e.preventDefault();
  165. Metronic.scrollTop();
  166. var url = $(this).attr("href");
  167. var pageContent = $('.page-content');
  168. var pageContentBody = $('.page-content .page-content-body');
  169. Metronic.startPageLoading();
  170. if (Metronic.getViewPort().width < resBreakpointMd && $('.page-sidebar').hasClass("in")) { // close the menu on mobile view while laoding a page
  171. $('.page-header .responsive-toggler').click();
  172. }
  173. $.ajax({
  174. type: "GET",
  175. cache: false,
  176. url: url,
  177. dataType: "html",
  178. success: function(res) {
  179. Metronic.stopPageLoading();
  180. pageContentBody.html(res);
  181. Layout.fixContentHeight(); // fix content height
  182. Metronic.initAjax(); // initialize core stuff
  183. },
  184. error: function(xhr, ajaxOptions, thrownError) {
  185. pageContentBody.html('<h4>Could not load the requested content.</h4>');
  186. Metronic.stopPageLoading();
  187. }
  188. });
  189. });
  190. // handle scrolling to top on responsive menu toggler click when header is fixed for mobile view
  191. $(document).on('click', '.page-header-fixed-mobile .responsive-toggler', function(){
  192. Metronic.scrollTop();
  193. });
  194. };
  195. // Helper function to calculate sidebar height for fixed sidebar layout.
  196. var _calculateFixedSidebarViewportHeight = function() {
  197. var sidebarHeight = Metronic.getViewPort().height - $('.page-header').outerHeight() - 30;
  198. if ($('body').hasClass("page-footer-fixed")) {
  199. sidebarHeight = sidebarHeight - $('.page-footer').outerHeight();
  200. }
  201. return sidebarHeight;
  202. };
  203. // Handles fixed sidebar
  204. var handleFixedSidebar = function() {
  205. var menu = $('.page-sidebar-menu');
  206. Metronic.destroySlimScroll(menu);
  207. if ($('.page-sidebar-fixed').size() === 0) {
  208. return;
  209. }
  210. if (Metronic.getViewPort().width >= resBreakpointMd) {
  211. menu.attr("data-height", _calculateFixedSidebarViewportHeight());
  212. Metronic.initSlimScroll(menu);
  213. }
  214. };
  215. // Handles sidebar toggler to close/hide the sidebar.
  216. var handleFixedSidebarHoverEffect = function () {
  217. var body = $('body');
  218. if (body.hasClass('page-sidebar-fixed')) {
  219. $('.page-sidebar').on('mouseenter', function () {
  220. if (body.hasClass('page-sidebar-closed')) {
  221. $(this).find('.page-sidebar-menu').removeClass('page-sidebar-menu-closed');
  222. }
  223. }).on('mouseleave', function () {
  224. if (body.hasClass('page-sidebar-closed')) {
  225. $(this).find('.page-sidebar-menu').addClass('page-sidebar-menu-closed');
  226. }
  227. });
  228. }
  229. };
  230. // Hanles sidebar toggler
  231. var handleSidebarToggler = function() {
  232. var body = $('body');
  233. if ($.cookie && $.cookie('sidebar_closed') === '1' && Metronic.getViewPort().width >= resBreakpointMd) {
  234. $('body').addClass('page-sidebar-closed');
  235. $('.page-sidebar-menu').addClass('page-sidebar-menu-closed');
  236. }
  237. // handle sidebar show/hide
  238. $('body').on('click', '.sidebar-toggler', function(e) {
  239. var sidebar = $('.page-sidebar');
  240. var sidebarMenu = $('.page-sidebar-menu');
  241. $(".sidebar-search", sidebar).removeClass("open");
  242. if (body.hasClass("page-sidebar-closed")) {
  243. body.removeClass("page-sidebar-closed");
  244. sidebarMenu.removeClass("page-sidebar-menu-closed");
  245. if ($.cookie) {
  246. $.cookie('sidebar_closed', '0');
  247. }
  248. } else {
  249. body.addClass("page-sidebar-closed");
  250. sidebarMenu.addClass("page-sidebar-menu-closed");
  251. if (body.hasClass("page-sidebar-fixed")) {
  252. sidebarMenu.trigger("mouseleave");
  253. }
  254. if ($.cookie) {
  255. $.cookie('sidebar_closed', '1');
  256. }
  257. }
  258. $(window).trigger('resize');
  259. });
  260. handleFixedSidebarHoverEffect();
  261. // handle the search bar close
  262. $('.page-sidebar').on('click', '.sidebar-search .remove', function(e) {
  263. e.preventDefault();
  264. $('.sidebar-search').removeClass("open");
  265. });
  266. // handle the search query submit on enter press
  267. $('.page-sidebar .sidebar-search').on('keypress', 'input.form-control', function(e) {
  268. if (e.which == 13) {
  269. $('.sidebar-search').submit();
  270. return false; //<---- Add this line
  271. }
  272. });
  273. // handle the search submit(for sidebar search and responsive mode of the header search)
  274. $('.sidebar-search .submit').on('click', function(e) {
  275. e.preventDefault();
  276. if ($('body').hasClass("page-sidebar-closed")) {
  277. if ($('.sidebar-search').hasClass('open') === false) {
  278. if ($('.page-sidebar-fixed').size() === 1) {
  279. $('.page-sidebar .sidebar-toggler').click(); //trigger sidebar toggle button
  280. }
  281. $('.sidebar-search').addClass("open");
  282. } else {
  283. $('.sidebar-search').submit();
  284. }
  285. } else {
  286. $('.sidebar-search').submit();
  287. }
  288. });
  289. // handle close on body click
  290. if ($('.sidebar-search').size() !== 0) {
  291. $('.sidebar-search .input-group').on('click', function(e) {
  292. e.stopPropagation();
  293. });
  294. $('body').on('click', function() {
  295. if ($('.sidebar-search').hasClass('open')) {
  296. $('.sidebar-search').removeClass("open");
  297. }
  298. });
  299. }
  300. };
  301. // Handles the horizontal menu
  302. var handleHeader = function() {
  303. // handle search box expand/collapse
  304. $('.page-header').on('click', '.search-form', function(e) {
  305. $(this).addClass("open");
  306. $(this).find('.form-control').focus();
  307. $('.page-header .search-form .form-control').on('blur', function(e) {
  308. $(this).closest('.search-form').removeClass("open");
  309. $(this).unbind("blur");
  310. });
  311. });
  312. // handle hor menu search form on enter press
  313. $('.page-header').on('keypress', '.hor-menu .search-form .form-control', function(e) {
  314. if (e.which == 13) {
  315. $(this).closest('.search-form').submit();
  316. return false;
  317. }
  318. });
  319. // handle header search button click
  320. $('.page-header').on('mousedown', '.search-form.open .submit', function(e) {
  321. e.preventDefault();
  322. e.stopPropagation();
  323. $(this).closest('.search-form').submit();
  324. });
  325. };
  326. // Handles the go to top button at the footer
  327. var handleGoTop = function() {
  328. var offset = 300;
  329. var duration = 500;
  330. if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) { // ios supported
  331. $(window).bind("touchend touchcancel touchleave", function(e) {
  332. if ($(this).scrollTop() > offset) {
  333. $('.scroll-to-top').fadeIn(duration);
  334. } else {
  335. $('.scroll-to-top').fadeOut(duration);
  336. }
  337. });
  338. } else { // general
  339. $(window).scroll(function() {
  340. if ($(this).scrollTop() > offset) {
  341. $('.scroll-to-top').fadeIn(duration);
  342. } else {
  343. $('.scroll-to-top').fadeOut(duration);
  344. }
  345. });
  346. }
  347. $('.scroll-to-top').click(function(e) {
  348. e.preventDefault();
  349. $('html, body').animate({
  350. scrollTop: 0
  351. }, duration);
  352. return false;
  353. });
  354. };
  355. //* END:CORE HANDLERS *//
  356. return {
  357. // Main init methods to initialize the layout
  358. // IMPORTANT!!!: Do not modify the core handlers call order.
  359. initHeader: function() {
  360. handleHeader(); // handles horizontal menu
  361. },
  362. setSidebarMenuActiveLink: function(mode, el) {
  363. handleSidebarMenuActiveLink(mode, el);
  364. },
  365. initSidebar: function() {
  366. //layout handlers
  367. handleFixedSidebar(); // handles fixed sidebar menu
  368. handleSidebarMenu(); // handles main menu
  369. handleSidebarToggler(); // handles sidebar hide/show
  370. if (Metronic.isAngularJsApp()) {
  371. handleSidebarMenuActiveLink('match'); // init sidebar active links
  372. }
  373. Metronic.addResizeHandler(handleFixedSidebar); // reinitialize fixed sidebar on window resize
  374. },
  375. initContent: function() {
  376. return;
  377. },
  378. initFooter: function() {
  379. handleGoTop(); //handles scroll to top functionality in the footer
  380. },
  381. init: function () {
  382. this.initHeader();
  383. this.initSidebar();
  384. this.initContent();
  385. this.initFooter();
  386. },
  387. //public function to fix the sidebar and content height accordingly
  388. fixContentHeight: function() {
  389. return;
  390. },
  391. initFixedSidebarHoverEffect: function() {
  392. handleFixedSidebarHoverEffect();
  393. },
  394. initFixedSidebar: function() {
  395. handleFixedSidebar();
  396. },
  397. getLayoutImgPath: function() {
  398. return Metronic.getAssetsPath() + layoutImgPath;
  399. },
  400. getLayoutCssPath: function() {
  401. return Metronic.getAssetsPath() + layoutCssPath;
  402. }
  403. };
  404. }();