github.com/apremalal/vamps-core@v1.0.1-0.20161221121535-d430b56ec174/server/webapps/app/base/js/layout.js (about)

     1  /**
     2  Core script to handle the entire theme and core functions
     3  **/
     4  var Layout = function () {
     5  
     6      var layoutImgPath = 'admin/layout/img/';
     7  
     8      var layoutCssPath = 'admin/layout/css/';
     9  
    10      var resBreakpointMd = Metronic.getResponsiveBreakpoint('md');
    11  
    12      //* BEGIN:CORE HANDLERS *//
    13      // this function handles responsive layout on screen size resize or mobile device rotate.
    14  
    15      // Set proper height for sidebar and content. The content and sidebar height must be synced always.
    16      var handleSidebarAndContentHeight = function () {
    17          var content = $('.page-content');
    18          var sidebar = $('.page-sidebar');
    19          var body = $('body');
    20          var height;
    21  
    22          if (body.hasClass("page-footer-fixed") === true && body.hasClass("page-sidebar-fixed") === false) {
    23              var available_height = Metronic.getViewPort().height - $('.page-footer').outerHeight() - $('.page-header').outerHeight();
    24              if (content.height() < available_height) {
    25                  content.attr('style', 'min-height:' + available_height + 'px');
    26              }
    27          } else {
    28              if (body.hasClass('page-sidebar-fixed')) {
    29                  height = _calculateFixedSidebarViewportHeight();
    30                  if (body.hasClass('page-footer-fixed') === false) {
    31                      height = height - $('.page-footer').outerHeight();
    32                  }
    33              } else {
    34                  var headerHeight = $('.page-header').outerHeight();
    35                  var footerHeight = $('.page-footer').outerHeight();
    36  
    37                  if (Metronic.getViewPort().width < resBreakpointMd) {
    38                      height = Metronic.getViewPort().height - headerHeight - footerHeight;
    39                  } else {
    40                      height = sidebar.height() + 20;
    41                  }
    42  
    43                  if ((height + headerHeight + footerHeight) <= Metronic.getViewPort().height) {
    44                      height = Metronic.getViewPort().height - headerHeight - footerHeight;
    45                  }
    46              }
    47              content.attr('style', 'min-height:' + height + 'px');
    48          }
    49      };
    50  
    51      // Handle sidebar menu links
    52      var handleSidebarMenuActiveLink = function(mode, el) {
    53          var url = location.hash.toLowerCase();    
    54  
    55          var menu = $('.page-sidebar-menu');
    56  
    57          if (mode === 'click' || mode === 'set') {
    58              el = $(el);
    59          } else if (mode === 'match') {
    60              menu.find("li > a").each(function() {
    61                  var path = $(this).attr("href").toLowerCase();       
    62                  // url match condition         
    63                  if (path.length > 1 && url.substr(1, path.length - 1) == path.substr(1)) {
    64                      el = $(this);
    65                      return; 
    66                  }
    67              });
    68          }
    69  
    70          if (!el || el.size() == 0) {
    71              return;
    72          }
    73  
    74          if (el.attr('href').toLowerCase() === 'javascript:;' || el.attr('href').toLowerCase() === '#') {
    75              return;
    76          }        
    77  
    78          var slideSpeed = parseInt(menu.data("slide-speed"));
    79          var keepExpand = menu.data("keep-expanded");
    80  
    81          // disable active states
    82          menu.find('li.active').removeClass('active');
    83          menu.find('li > a > .selected').remove();
    84  
    85          if (menu.hasClass('page-sidebar-menu-hover-submenu') === false) {
    86              menu.find('li.open').each(function(){
    87                  if ($(this).children('.sub-menu').size() === 0) {
    88                      $(this).removeClass('open');
    89                      $(this).find('> a > .arrow.open').removeClass('open');
    90                  }                             
    91              }); 
    92          } else {
    93               menu.find('li.open').removeClass('open');
    94          }
    95  
    96          el.parents('li').each(function () {
    97              $(this).addClass('active');
    98              $(this).find('> a > span.arrow').addClass('open');
    99  
   100              if ($(this).parent('ul.page-sidebar-menu').size() === 1) {
   101                  $(this).find('> a').append('<span class="selected"></span>');
   102              }
   103              
   104              if ($(this).children('ul.sub-menu').size() === 1) {
   105                  $(this).addClass('open');
   106              }
   107          });
   108  
   109          if (mode === 'click') {
   110              if (Metronic.getViewPort().width < resBreakpointMd && $('.page-sidebar').hasClass("in")) { // close the menu on mobile view while laoding a page 
   111                  $('.page-header .responsive-toggler').click();
   112              }
   113          }
   114      };
   115  
   116      // Handle sidebar menu
   117      var handleSidebarMenu = function () {
   118          // handle sidebar link click
   119          $('.page-sidebar').on('click', 'li > a', function (e) {
   120              var hasSubMenu = $(this).next().hasClass('sub-menu');
   121  
   122              if (Metronic.getViewPort().width >= resBreakpointMd && $(this).parents('.page-sidebar-menu-hover-submenu').size() === 1) { // exit of hover sidebar menu
   123                  return;
   124              }
   125  
   126              if (hasSubMenu === false) {
   127                  if (Metronic.getViewPort().width < resBreakpointMd && $('.page-sidebar').hasClass("in")) { // close the menu on mobile view while laoding a page 
   128                      $('.page-header .responsive-toggler').click();
   129                  }
   130                  return;
   131              }
   132  
   133              if ($(this).next().hasClass('sub-menu always-open')) {
   134                  return;
   135              }
   136  
   137              var parent = $(this).parent().parent();
   138              var the = $(this);
   139              var menu = $('.page-sidebar-menu');
   140              var sub = $(this).next();
   141  
   142              var autoScroll = menu.data("auto-scroll");
   143              var slideSpeed = parseInt(menu.data("slide-speed"));
   144              var keepExpand = menu.data("keep-expanded");
   145  
   146              if (keepExpand !== true) {
   147                  parent.children('li.open').children('a').children('.arrow').removeClass('open');
   148                  parent.children('li.open').children('.sub-menu:not(.always-open)').slideUp(slideSpeed);
   149                  parent.children('li.open').removeClass('open');
   150              }
   151  
   152              var slideOffeset = -200;
   153  
   154              if (sub.is(":visible")) {
   155                  $('.arrow', $(this)).removeClass("open");
   156                  $(this).parent().removeClass("open");
   157                  sub.slideUp(slideSpeed, function () {
   158                      if (autoScroll === true && $('body').hasClass('page-sidebar-closed') === false) {
   159                          if ($('body').hasClass('page-sidebar-fixed')) {
   160                              menu.slimScroll({
   161                                  'scrollTo': (the.position()).top
   162                              });
   163                          } else {
   164                              Metronic.scrollTo(the, slideOffeset);
   165                          }
   166                      }
   167                      handleSidebarAndContentHeight();
   168                  });
   169              } else if (hasSubMenu) {
   170                  $('.arrow', $(this)).addClass("open");
   171                  $(this).parent().addClass("open");
   172                  sub.slideDown(slideSpeed, function () {
   173                      if (autoScroll === true && $('body').hasClass('page-sidebar-closed') === false) {
   174                          if ($('body').hasClass('page-sidebar-fixed')) {
   175                              menu.slimScroll({
   176                                  'scrollTo': (the.position()).top
   177                              });
   178                          } else {
   179                              Metronic.scrollTo(the, slideOffeset);
   180                          }
   181                      }
   182                      handleSidebarAndContentHeight();
   183                  });
   184              }
   185  
   186              e.preventDefault();
   187          });
   188  
   189          // handle ajax links within sidebar menu
   190          $('.page-sidebar').on('click', ' li > a.ajaxify', function (e) {
   191              e.preventDefault();
   192              Metronic.scrollTop();
   193  
   194              var url = $(this).attr("href");
   195              var menuContainer = $('.page-sidebar ul');
   196              var pageContent = $('.page-content');
   197              var pageContentBody = $('.page-content .page-content-body');
   198  
   199              menuContainer.children('li.active').removeClass('active');
   200              menuContainer.children('arrow.open').removeClass('open');
   201  
   202              $(this).parents('li').each(function () {
   203                  $(this).addClass('active');
   204                  $(this).children('a > span.arrow').addClass('open');
   205              });
   206              $(this).parents('li').addClass('active');
   207  
   208              if (Metronic.getViewPort().width < resBreakpointMd && $('.page-sidebar').hasClass("in")) { // close the menu on mobile view while laoding a page 
   209                  $('.page-header .responsive-toggler').click();
   210              }
   211  
   212              Metronic.startPageLoading();
   213  
   214              var the = $(this);
   215              
   216              $.ajax({
   217                  type: "GET",
   218                  cache: false,
   219                  url: url,
   220                  dataType: "html",
   221                  success: function (res) {
   222                      if (the.parents('li.open').size() === 0) {
   223                          $('.page-sidebar-menu > li.open > a').click();
   224                      }
   225  
   226                      Metronic.stopPageLoading();
   227                      pageContentBody.html(res);
   228                      Layout.fixContentHeight(); // fix content height
   229                      Metronic.initAjax(); // initialize core stuff
   230                  },
   231                  error: function (xhr, ajaxOptions, thrownError) {
   232                      Metronic.stopPageLoading();
   233                      pageContentBody.html('<h4>Could not load the requested content.</h4>');
   234                  }
   235              });
   236          });
   237  
   238          // handle ajax link within main content
   239          $('.page-content').on('click', '.ajaxify', function (e) {
   240              e.preventDefault();
   241              Metronic.scrollTop();
   242  
   243              var url = $(this).attr("href");
   244              var pageContent = $('.page-content');
   245              var pageContentBody = $('.page-content .page-content-body');
   246  
   247              Metronic.startPageLoading();
   248  
   249              if (Metronic.getViewPort().width < resBreakpointMd && $('.page-sidebar').hasClass("in")) { // close the menu on mobile view while laoding a page 
   250                  $('.page-header .responsive-toggler').click();
   251              }
   252  
   253              $.ajax({
   254                  type: "GET",
   255                  cache: false,
   256                  url: url,
   257                  dataType: "html",
   258                  success: function (res) {
   259                      Metronic.stopPageLoading();
   260                      pageContentBody.html(res);
   261                      Layout.fixContentHeight(); // fix content height
   262                      Metronic.initAjax(); // initialize core stuff
   263                  },
   264                  error: function (xhr, ajaxOptions, thrownError) {
   265                      pageContentBody.html('<h4>Could not load the requested content.</h4>');
   266                      Metronic.stopPageLoading();
   267                  }
   268              });
   269          });
   270  
   271          // handle scrolling to top on responsive menu toggler click when header is fixed for mobile view
   272          $(document).on('click', '.page-header-fixed-mobile .page-header .responsive-toggler', function(){
   273              Metronic.scrollTop(); 
   274          });      
   275       
   276          // handle sidebar hover effect        
   277          handleFixedSidebarHoverEffect();
   278  
   279          // handle the search bar close
   280          $('.page-sidebar').on('click', '.sidebar-search .remove', function (e) {
   281              e.preventDefault();
   282              $('.sidebar-search').removeClass("open");
   283          });
   284  
   285          // handle the search query submit on enter press
   286          $('.page-sidebar .sidebar-search').on('keypress', 'input.form-control', function (e) {
   287              if (e.which == 13) {
   288                  $('.sidebar-search').submit();
   289                  return false; //<---- Add this line
   290              }
   291          });
   292  
   293          // handle the search submit(for sidebar search and responsive mode of the header search)
   294          $('.sidebar-search .submit').on('click', function (e) {
   295              e.preventDefault();
   296              if ($('body').hasClass("page-sidebar-closed")) {
   297                  if ($('.sidebar-search').hasClass('open') === false) {
   298                      if ($('.page-sidebar-fixed').size() === 1) {
   299                          $('.page-sidebar .sidebar-toggler').click(); //trigger sidebar toggle button
   300                      }
   301                      $('.sidebar-search').addClass("open");
   302                  } else {
   303                      $('.sidebar-search').submit();
   304                  }
   305              } else {
   306                  $('.sidebar-search').submit();
   307              }
   308          });
   309  
   310          // handle close on body click
   311          if ($('.sidebar-search').size() !== 0) {
   312              $('.sidebar-search .input-group').on('click', function(e){
   313                  e.stopPropagation();
   314              });
   315  
   316              $('body').on('click', function() {
   317                  if ($('.sidebar-search').hasClass('open')) {
   318                      $('.sidebar-search').removeClass("open");
   319                  }
   320              });
   321          }
   322      };
   323  
   324      // Helper function to calculate sidebar height for fixed sidebar layout.
   325      var _calculateFixedSidebarViewportHeight = function () {
   326          var sidebarHeight = Metronic.getViewPort().height - $('.page-header').outerHeight();
   327          if ($('body').hasClass("page-footer-fixed")) {
   328              sidebarHeight = sidebarHeight - $('.page-footer').outerHeight();
   329          }
   330  
   331          return sidebarHeight;
   332      };
   333  
   334      // Handles fixed sidebar
   335      var handleFixedSidebar = function () {
   336          var menu = $('.page-sidebar-menu');
   337  
   338          Metronic.destroySlimScroll(menu);
   339  
   340          if ($('.page-sidebar-fixed').size() === 0) {
   341              handleSidebarAndContentHeight();
   342              return;
   343          }
   344  
   345          if (Metronic.getViewPort().width >= resBreakpointMd) {
   346              menu.attr("data-height", _calculateFixedSidebarViewportHeight());
   347              Metronic.initSlimScroll(menu);
   348              handleSidebarAndContentHeight();
   349          }
   350      };
   351  
   352      // Handles sidebar toggler to close/hide the sidebar.
   353      var handleFixedSidebarHoverEffect = function () {
   354          var body = $('body');
   355          if (body.hasClass('page-sidebar-fixed')) {
   356              $('.page-sidebar').on('mouseenter', function () {
   357                  if (body.hasClass('page-sidebar-closed')) {
   358                      $(this).find('.page-sidebar-menu').removeClass('page-sidebar-menu-closed');
   359                  }
   360              }).on('mouseleave', function () {
   361                  if (body.hasClass('page-sidebar-closed')) {
   362                      $(this).find('.page-sidebar-menu').addClass('page-sidebar-menu-closed');
   363                  }
   364              });
   365          }
   366      };
   367  
   368      // Hanles sidebar toggler
   369      var handleSidebarToggler = function () {
   370          var body = $('body');
   371          if ($.cookie && $.cookie('sidebar_closed') === '1' && Metronic.getViewPort().width >= resBreakpointMd) {
   372              $('body').addClass('page-sidebar-closed');
   373              $('.page-sidebar-menu').addClass('page-sidebar-menu-closed');
   374          }
   375  
   376          // handle sidebar show/hide
   377          $('body').on('click', '.sidebar-toggler', function (e) {
   378              var sidebar = $('.page-sidebar');
   379              var sidebarMenu = $('.page-sidebar-menu');
   380              var pageSliderHeading = $('.page-slider-heading');
   381  
   382              $(".sidebar-search", sidebar).removeClass("open");
   383  
   384              if (body.hasClass("page-sidebar-closed")) {
   385                  body.removeClass("page-sidebar-closed");
   386                  sidebarMenu.removeClass("page-sidebar-menu-closed");
   387                  pageSliderHeading.removeClass("page-slider-heading-closed");
   388                  if ($.cookie) {
   389                      $.cookie('sidebar_closed', '0');
   390                  }
   391  
   392              } else {
   393                  body.addClass("page-sidebar-closed");
   394                  sidebarMenu.addClass("page-sidebar-menu-closed");
   395                  pageSliderHeading.addClass("page-slider-heading-closed");
   396                  if (body.hasClass("page-sidebar-fixed")) {
   397                      sidebarMenu.trigger("mouseleave");
   398                  }
   399                  if ($.cookie) {
   400                      $.cookie('sidebar_closed', '1');
   401                  }
   402              }
   403  
   404              $(window).trigger('resize');
   405          });
   406      };
   407  
   408      // Handles the horizontal menu
   409      var handleHorizontalMenu = function () {
   410          //handle tab click
   411          $('.page-header').on('click', '.hor-menu a[data-toggle="tab"]', function (e) {
   412              e.preventDefault();
   413              var nav = $(".hor-menu .nav");
   414              var active_link = nav.find('li.current');
   415              $('li.active', active_link).removeClass("active");
   416              $('.selected', active_link).remove();
   417              var new_link = $(this).parents('li').last();
   418              new_link.addClass("current");
   419              new_link.find("a:first").append('<span class="selected"></span>');
   420          });
   421  
   422          // handle search box expand/collapse        
   423          $('.page-header').on('click', '.search-form', function (e) {
   424              $(this).addClass("open");
   425              $(this).find('.form-control').focus();
   426  
   427              $('.page-header .search-form .form-control').on('blur', function (e) {
   428                  $(this).closest('.search-form').removeClass("open");
   429                  $(this).unbind("blur");
   430              });
   431          });
   432  
   433          // handle hor menu search form on enter press
   434          $('.page-header').on('keypress', '.hor-menu .search-form .form-control', function (e) {
   435              if (e.which == 13) {
   436                  $(this).closest('.search-form').submit();
   437                  return false;
   438              }
   439          });
   440  
   441          // handle header search button click
   442          $('.page-header').on('mousedown', '.search-form.open .submit', function (e) {
   443              e.preventDefault();
   444              e.stopPropagation();
   445              $(this).closest('.search-form').submit();
   446          });
   447  
   448          // handle hover dropdown menu for desktop devices only
   449          $('[data-hover="megamenu-dropdown"]').not('.hover-initialized').each(function() {   
   450              $(this).dropdownHover(); 
   451              $(this).addClass('hover-initialized'); 
   452          });
   453          
   454          $(document).on('click', '.mega-menu-dropdown .dropdown-menu', function (e) {
   455              e.stopPropagation();
   456          });
   457      };
   458  
   459      // Handles Bootstrap Tabs.
   460      var handleTabs = function () {
   461          // fix content height on tab click
   462          $('body').on('shown.bs.tab', 'a[data-toggle="tab"]', function () {
   463              handleSidebarAndContentHeight();
   464          });
   465      };
   466  
   467      // Handles the go to top button at the footer
   468      var handleGoTop = function () {
   469          var offset = 300;
   470          var duration = 500;
   471  
   472          if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {  // ios supported
   473              $(window).bind("touchend touchcancel touchleave", function(e){
   474                 if ($(this).scrollTop() > offset) {
   475                      $('.scroll-to-top').fadeIn(duration);
   476                  } else {
   477                      $('.scroll-to-top').fadeOut(duration);
   478                  }
   479              });
   480          } else {  // general 
   481              $(window).scroll(function() {
   482                  if ($(this).scrollTop() > offset) {
   483                      $('.scroll-to-top').fadeIn(duration);
   484                  } else {
   485                      $('.scroll-to-top').fadeOut(duration);
   486                  }
   487              });
   488          }
   489          
   490          $('.scroll-to-top').click(function(e) {
   491              e.preventDefault();
   492              $('html, body').animate({scrollTop: 0}, duration);
   493              return false;
   494          });
   495      };
   496  
   497      // Hanlde 100% height elements(block, portlet, etc)
   498      var handle100HeightContent = function () {
   499  
   500          var target = $('.full-height-content');
   501          var height;
   502  
   503          height = Metronic.getViewPort().height -
   504              $('.page-header').outerHeight(true) -
   505              $('.page-footer').outerHeight(true) -
   506              $('.page-title').outerHeight(true) -
   507              $('.page-bar').outerHeight(true);
   508  
   509          if (target.hasClass('portlet')) {
   510              var portletBody = target.find('.portlet-body');
   511              
   512              if (Metronic.getViewPort().width < resBreakpointMd) {
   513                  Metronic.destroySlimScroll(portletBody.find('.full-height-content-body')); // destroy slimscroll 
   514                  return;
   515              }
   516  
   517              height = height -
   518                  target.find('.portlet-title').outerHeight(true) -
   519                  parseInt(target.find('.portlet-body').css('padding-top')) -
   520                  parseInt(target.find('.portlet-body').css('padding-bottom')) - 2;
   521  
   522              if (target.hasClass("full-height-content-scrollable")) {
   523                  height = height - 35;
   524                  portletBody.find('.full-height-content-body').css('height', height);
   525                  Metronic.initSlimScroll(portletBody.find('.full-height-content-body'));
   526              } else {
   527                  portletBody.css('min-height', height);
   528              }
   529          } else {
   530              if (Metronic.getViewPort().width < resBreakpointMd) {
   531                  Metronic.destroySlimScroll(target.find('.full-height-content-body')); // destroy slimscroll 
   532                  return;
   533              }
   534  
   535              if (target.hasClass("full-height-content-scrollable")) {
   536                  height = height - 35;
   537                  target.find('.full-height-content-body').css('height', height);
   538                  Metronic.initSlimScroll(target.find('.full-height-content-body'));
   539              } else {
   540                  target.css('min-height', height);
   541              }
   542          }
   543      };
   544      //* END:CORE HANDLERS *//
   545  
   546      return {
   547          // Main init methods to initialize the layout
   548          //IMPORTANT!!!: Do not modify the core handlers call order.
   549  
   550          initHeader: function() {
   551              handleHorizontalMenu(); // handles horizontal menu    
   552          },
   553  
   554          setSidebarMenuActiveLink: function(mode, el) {
   555              handleSidebarMenuActiveLink(mode, el);
   556          },
   557  
   558          initSidebar: function() {
   559              //layout handlers
   560              handleFixedSidebar(); // handles fixed sidebar menu
   561              handleSidebarMenu(); // handles main menu
   562              handleSidebarToggler(); // handles sidebar hide/show
   563  
   564              if (Metronic.isAngularJsApp()) {      
   565                  handleSidebarMenuActiveLink('match'); // init sidebar active links 
   566              }
   567  
   568              Metronic.addResizeHandler(handleFixedSidebar); // reinitialize fixed sidebar on window resize
   569          },
   570  
   571          initContent: function() {
   572              handle100HeightContent(); // handles 100% height elements(block, portlet, etc)
   573              handleTabs(); // handle bootstrah tabs
   574  
   575              Metronic.addResizeHandler(handleSidebarAndContentHeight); // recalculate sidebar & content height on window resize
   576              Metronic.addResizeHandler(handle100HeightContent); // reinitialize content height on window resize 
   577          },
   578  
   579          initFooter: function() {
   580              handleGoTop(); //handles scroll to top functionality in the footer
   581          },
   582  
   583          init: function () {            
   584              this.initHeader();
   585              this.initSidebar();
   586              this.initContent();
   587              this.initFooter();
   588          },
   589  
   590          //public function to fix the sidebar and content height accordingly
   591          fixContentHeight: function () {
   592              handleSidebarAndContentHeight();
   593          },
   594  
   595          initFixedSidebarHoverEffect: function() {
   596              handleFixedSidebarHoverEffect();
   597          },
   598  
   599          initFixedSidebar: function() {
   600              handleFixedSidebar();
   601          },
   602  
   603          getLayoutImgPath: function () {
   604              return Metronic.getAssetsPath() + layoutImgPath;
   605          },
   606  
   607          getLayoutCssPath: function () {
   608              return Metronic.getAssetsPath() + layoutCssPath;
   609          }
   610      };
   611  
   612  }();