Browse Source

enhanced ControlSidebar
- moved control sidebar related functions from Layout.js to ControlSidebar.js
- added own scrollbar options
- added ability to set control sidebar height while scrolling
- fixed overlapping with fixed footer/navbar

REJack 5 years ago
parent
commit
eeeee1fbbf

+ 144 - 8
build/js/ControlSidebar.js

@@ -19,23 +19,39 @@ const ControlSidebar = (($) => {
 
   const Event = {
     COLLAPSED: `collapsed${EVENT_KEY}`,
-    EXPANDED: `expanded${EVENT_KEY}`
+    EXPANDED: `expanded${EVENT_KEY}`,
   }
 
   const Selector = {
     CONTROL_SIDEBAR: '.control-sidebar',
-    DATA_TOGGLE    : '[data-widget="control-sidebar"]',
-    MAIN_HEADER    : '.main-header'
+    CONTROL_SIDEBAR_CONTENT: '.control-sidebar-content',
+    DATA_TOGGLE: '[data-widget="control-sidebar"]',
+    CONTENT: '.content-wrapper',
+    HEADER: '.main-header',
+    FOOTER: '.main-footer',
   }
 
   const ClassName = {
     CONTROL_SIDEBAR_ANIMATE: 'control-sidebar-animate',
     CONTROL_SIDEBAR_OPEN: 'control-sidebar-open',
-    CONTROL_SIDEBAR_SLIDE: 'control-sidebar-slide-open'
+    CONTROL_SIDEBAR_SLIDE: 'control-sidebar-slide-open',
+    LAYOUT_FIXED: 'layout-fixed',
+    NAVBAR_FIXED: 'layout-navbar-fixed',
+    NAVBAR_SM_FIXED: 'layout-sm-navbar-fixed',
+    NAVBAR_MD_FIXED: 'layout-md-navbar-fixed',
+    NAVBAR_LG_FIXED: 'layout-lg-navbar-fixed',
+    NAVBAR_XL_FIXED: 'layout-xl-navbar-fixed',
+    FOOTER_FIXED: 'layout-footer-fixed',
+    FOOTER_SM_FIXED: 'layout-sm-footer-fixed',
+    FOOTER_MD_FIXED: 'layout-md-footer-fixed',
+    FOOTER_LG_FIXED: 'layout-lg-footer-fixed',
+    FOOTER_XL_FIXED: 'layout-xl-footer-fixed',
   }
 
   const Default = {
-    controlsidebarSlide: true
+    controlsidebarSlide: true,
+    scrollbarTheme : 'os-theme-light',
+    scrollbarAutoHide: 'l',
   }
 
   /**
@@ -46,7 +62,9 @@ const ControlSidebar = (($) => {
   class ControlSidebar {
     constructor(element, config) {
       this._element = element
-      this._config  = this._getConfig(config)
+      this._config  = config
+
+      this._init()
     }
 
     // Public
@@ -101,10 +119,128 @@ const ControlSidebar = (($) => {
 
     // Private
 
-    _getConfig(config) {
-      return $.extend({}, Default, config)
+    _init() {
+      this._fixHeight()
+      this._fixScrollHeight()
+
+      $(window).resize(() => {
+        this._fixHeight()
+        this._fixScrollHeight()
+      })
+
+      $(window).scroll(() => {
+        if ($('body').hasClass(ClassName.CONTROL_SIDEBAR_OPEN) || $('body').hasClass(ClassName.CONTROL_SIDEBAR_SLIDE)) {
+            this._fixScrollHeight()
+        }
+      })
+    }
+
+    _fixScrollHeight() {
+      const heights = {
+        scroll: $(document).height(),
+        window: $(window).height(),
+        header: $(Selector.HEADER).outerHeight(),
+        footer: $(Selector.FOOTER).outerHeight(),
+      }
+      const positions = {
+        bottom: Math.abs((heights.window + $(window).scrollTop()) - heights.scroll),
+        top: $(window).scrollTop(),
+      }
+
+      let navbarFixed = false;
+      let footerFixed = false;
+
+      if ($('body').hasClass(ClassName.LAYOUT_FIXED)) {
+        if (
+          $('body').hasClass(ClassName.NAVBAR_FIXED)
+          || $('body').hasClass(ClassName.NAVBAR_SM_FIXED)
+          || $('body').hasClass(ClassName.NAVBAR_MD_FIXED)
+          || $('body').hasClass(ClassName.NAVBAR_LG_FIXED)
+          || $('body').hasClass(ClassName.NAVBAR_XL_FIXED)
+        ) {
+          if ($(Selector.HEADER).css("position") === "fixed") {
+            navbarFixed = true;
+          }
+        }
+        if (
+          $('body').hasClass(ClassName.FOOTER_FIXED)
+          || $('body').hasClass(ClassName.FOOTER_SM_FIXED)
+          || $('body').hasClass(ClassName.FOOTER_MD_FIXED)
+          || $('body').hasClass(ClassName.FOOTER_LG_FIXED)
+          || $('body').hasClass(ClassName.FOOTER_XL_FIXED)
+        ) {
+          if ($(Selector.FOOTER).css("position") === "fixed") {
+            footerFixed = true;
+          }
+        }
+
+        if (positions.top === 0 && positions.bottom === 0) {
+          $(Selector.CONTROL_SIDEBAR).css('bottom', heights.footer);
+          $(Selector.CONTROL_SIDEBAR).css('top', heights.header);
+          $(Selector.CONTROL_SIDEBAR + ', ' + Selector.CONTROL_SIDEBAR + ' ' + Selector.CONTROL_SIDEBAR_CONTENT).css('height', heights.window - (heights.header + heights.footer))
+        } else if (positions.bottom <= heights.footer) {
+          if (footerFixed === false) {  
+            $(Selector.CONTROL_SIDEBAR).css('bottom', heights.footer - positions.bottom);
+            $(Selector.CONTROL_SIDEBAR + ', ' + Selector.CONTROL_SIDEBAR + ' ' + Selector.CONTROL_SIDEBAR_CONTENT).css('height', heights.window - (heights.footer - positions.bottom))
+          } else {
+            $(Selector.CONTROL_SIDEBAR).css('bottom', heights.footer);
+          }
+        } else if (positions.top <= heights.header) {
+          if (navbarFixed === false) {
+            $(Selector.CONTROL_SIDEBAR).css('top', heights.header - positions.top);
+            $(Selector.CONTROL_SIDEBAR + ', ' + Selector.CONTROL_SIDEBAR + ' ' + Selector.CONTROL_SIDEBAR_CONTENT).css('height', heights.window - (heights.header - positions.top))
+          } else {
+            $(Selector.CONTROL_SIDEBAR).css('top', heights.header);
+          }
+        } else {
+          if (navbarFixed === false) {
+            $(Selector.CONTROL_SIDEBAR).css('top', 0);
+            $(Selector.CONTROL_SIDEBAR + ', ' + Selector.CONTROL_SIDEBAR + ' ' + Selector.CONTROL_SIDEBAR_CONTENT).css('height', heights.window)
+          } else {
+            $(Selector.CONTROL_SIDEBAR).css('top', heights.header);
+          }
+        }
+      }
+    }
+
+    _fixHeight() {
+      const heights = {
+        window: $(window).height(),
+        header: $(Selector.HEADER).outerHeight(),
+        footer: $(Selector.FOOTER).outerHeight(),
+      }
+
+      if ($('body').hasClass(ClassName.LAYOUT_FIXED)) {
+        let sidebarHeight = heights.window - heights.header;
+
+        if (
+          $('body').hasClass(ClassName.FOOTER_FIXED)
+          || $('body').hasClass(ClassName.FOOTER_SM_FIXED)
+          || $('body').hasClass(ClassName.FOOTER_MD_FIXED)
+          || $('body').hasClass(ClassName.FOOTER_LG_FIXED)
+          || $('body').hasClass(ClassName.FOOTER_XL_FIXED)
+        ) {
+          if ($(Selector.FOOTER).css("position") === "fixed") {
+            sidebarHeight = heights.window - heights.header - heights.footer;
+          }
+        }
+
+        $(Selector.CONTROL_SIDEBAR + ' ' + Selector.CONTROL_SIDEBAR_CONTENT).css('height', sidebarHeight)
+        
+        if (typeof $.fn.overlayScrollbars !== 'undefined') {
+          $(Selector.CONTROL_SIDEBAR + ' ' + Selector.CONTROL_SIDEBAR_CONTENT).overlayScrollbars({
+            className       : this._config.scrollbarTheme,
+            sizeAutoCapable : true,
+            scrollbars : {
+              autoHide: this._config.scrollbarAutoHide, 
+              clickScrolling : true
+            }
+          })
+        }
+      }
     }
 
+
     // Static
 
     static _jQueryInterface(operation) {

+ 0 - 9
build/js/Layout.js

@@ -77,7 +77,6 @@ const Layout = (($) => {
       if ($('body').hasClass(ClassName.LAYOUT_FIXED)) {
         $(Selector.CONTENT).css('min-height', max - heights.header - heights.footer)
         // $(Selector.SIDEBAR).css('min-height', max - heights.header)
-        $(Selector.CONTROL_SIDEBAR + ' .control-sidebar-content').css('height', max - heights.header)
         
         if (typeof $.fn.overlayScrollbars !== 'undefined') {
           $(Selector.SIDEBAR).overlayScrollbars({
@@ -88,14 +87,6 @@ const Layout = (($) => {
               clickScrolling : true
             }
           })
-          $(Selector.CONTROL_SIDEBAR + ' .control-sidebar-content').overlayScrollbars({
-            className       : this._config.scrollbarTheme,
-            sizeAutoCapable : true,
-            scrollbars : {
-              autoHide: this._config.scrollbarAutoHide, 
-              clickScrolling : true
-            }
-          })
         }
       } else {
         if (heights.window > heights.sidebar) {

+ 3 - 2
build/scss/_control-sidebar.scss

@@ -7,13 +7,14 @@ html.control-sidebar-animate {
 }
 
 .control-sidebar {
+  bottom: $main-footer-height;
   position: absolute;
   top: $main-header-height;
   z-index: $zindex-control-sidebar;
-
+  
   &,
   &::before {
-    bottom: 0;
+    bottom: $main-footer-height;
     display: none;
     right: -$control-sidebar-width;
     width: $control-sidebar-width;

+ 30 - 1
build/scss/_layout.scss

@@ -16,7 +16,7 @@ body,
   position: relative;
 
   & .content-wrapper {
-    min-height: calc(100vh - 112px);
+    min-height: calc(100vh - #{$main-header-height} - #{$main-footer-height});
   }
 
   .layout-boxed & {
@@ -34,6 +34,9 @@ body,
   }
 
   .layout-navbar-fixed.layout-fixed & {
+    .control-sidebar {
+      top: $main-header-height;
+    }
     .sidebar {
       margin-top: $main-header-height;
     }
@@ -117,6 +120,9 @@ body,
       $infix: breakpoint-infix($breakpoint, $grid-breakpoints);
 
       .layout#{$infix}-navbar-fixed.layout-fixed & {
+        .control-sidebar {
+          top: $main-header-height;
+        }
         .sidebar {
           margin-top: $main-header-height;
         }
@@ -199,6 +205,12 @@ body,
     }
   }
 
+  .layout-footer-fixed & {
+    .control-sidebar {
+      bottom: 0;
+    }
+  }
+
   .layout-footer-fixed & {
     .main-footer {
       bottom: 0;
@@ -222,6 +234,11 @@ body,
   @each $breakpoint in map-keys($grid-breakpoints) {
     @include media-breakpoint-up($breakpoint) {
       $infix: breakpoint-infix($breakpoint, $grid-breakpoints);
+      .layout#{$infix}-footer-fixed & {
+        .control-sidebar {
+          bottom: 0;
+        }
+      }
 
       .layout#{$infix}-footer-fixed & {
         .main-footer {
@@ -357,6 +374,18 @@ body,
     position: fixed;
     top: 0;
   }
+
+  .control-sidebar {
+    bottom: 0;
+    float: none;
+    height: 100vh;
+    position: fixed;
+    top: 0;
+
+    .control-sidebar-content {
+      height: calc(100vh - #{$main-header-height});
+    }
+  }
 }
 
 .main-footer {

+ 2 - 2
build/scss/_variables.scss

@@ -154,8 +154,8 @@ $attachment-border-radius: 3px !default;
 // --------------------------------------------------------
 $zindex-main-header: $zindex-fixed + 4 !default;
 $zindex-main-sidebar: $zindex-fixed + 8 !default;
-$zindex-main-footer: $zindex-fixed + 1 !default;
-$zindex-control-sidebar: $zindex-fixed + 2 !default;
+$zindex-main-footer: $zindex-fixed + 2 !default;
+$zindex-control-sidebar: $zindex-fixed + 1 !default;
 $zindex-sidebar-mini-links: 010 !default;
 
 // TRANSITIONS SETTINGS

+ 4 - 2
docs/javascript/control-sidebar.md

@@ -38,13 +38,15 @@ $("#my-toggle-button").ControlSidebar('toggle');
 |---
 | Name | Type | Default | Description
 |-|-|-|-
-|slide | Boolean | TRUE | Whether the sidebar should slide over the content or push the content to make space for itself.
+|controlsidebarSlide | Boolean | TRUE | Whether the sidebar should slide over the content or push the content to make space for itself.
+|scrollbarTheme | Boolean | `os-theme-light` | Scrollbar Theme used while SideBar Fixed
+|scrollbarAutoHide | Boolean | `l` | Scrollbar auto-hide trigger
 {: .table .table-bordered .bg-light}
 
 > ##### Tip!
 > You can use any option via the data-attributes like this to enable auto collapse sidebar on 768 pixels width.
 > ```html
-> <a href="#" data-widget="control-sidebar" data-slide="false">Toggle Control Sidebar</a>
+> <a href="#" data-widget="control-sidebar" data-controlsidebar-slide="false">Toggle Control Sidebar</a>
 > ```
 {: .quote-info}