]> BookStack Code Mirror - bookstack/commitdiff
Fixes #466. Adds support for header highlighting using intersection observer.
authorAbijeet <redacted>
Wed, 1 Nov 2017 19:44:06 +0000 (01:14 +0530)
committerAbijeet <redacted>
Wed, 1 Nov 2017 19:44:06 +0000 (01:14 +0530)
resources/assets/js/pages/page-show.js
resources/assets/sass/_lists.scss

index 14437cd68a326466b1179cf4639154e329386999..15acddf85956238356456725ea00858fa103ff80 100644 (file)
@@ -150,6 +150,59 @@ let setupPageShow = window.setupPageShow = function (pageId) {
             unstickTree();
         }
     });
+
+
+    // Check if support is present for IntersectionObserver
+    if ('IntersectionObserver' in window &&
+        'IntersectionObserverEntry' in window &&
+        'intersectionRatio' in window.IntersectionObserverEntry.prototype) {
+        $(document).ready(function () {
+            // fetch all the headings.
+            let headings = document.querySelector('.page-content').querySelectorAll('h1, h2, h3, h4, h5, h6');
+            // if headings are present, add observers.
+            if (headings.length > 0) {
+                addNavObserver(headings);
+            }
+        });
+    }
+
+    let $pageNav = null;
+    function addNavObserver(headings) {
+        // Setup the intersection observer.
+        // margin top = -25px to trigger the threshold change before the heading
+        // has completely left the viewport on the top.
+        let intersectOpts = {
+            rootMargin: '-25px 0px 0px 0px',
+            threshold: 1.0
+        }
+        $pageNav = $('.sidebar-page-nav');
+        let pageNavObserver = new IntersectionObserver(cbHeadingVisible, intersectOpts);
+
+        // observe each heading
+        for (let i = 0; i !== headings.length; ++i) {
+            pageNavObserver.observe(headings[i]);
+        }
+    }
+
+    function cbHeadingVisible(entries, observer) {
+        let element = null;
+        for (let i = 0; i !== entries.length; ++i) {
+            let currentEntry = entries[i];
+            // check if its currently visible and its distance from top of viewport is less than 100
+            if (currentEntry.intersectionRatio <= 1 && currentEntry.boundingClientRect.y < 100) {
+                element = currentEntry.target;
+            } else {
+                break;
+            }
+        }
+        if (!element) {
+            return;
+        }
+        let elementId = element.id;
+        $pageNav.find('a').removeClass('current-heading');
+        $pageNav.find('a[href="#' + elementId + '"]').addClass('current-heading');
+    }
+
 };
 
 module.exports = setupPageShow;
\ No newline at end of file
index d30d4d4a22ab98745b5f7b1076db90297dc2fde0..298ce32cb7de06bec2626b906bf6c5a8bb557aa2 100644 (file)
@@ -82,6 +82,9 @@
   .h6 {
     margin-left: $nav-indent*4;
   }
+  .current-heading {
+    font-weight: bold;
+  }
 }
 
 // Sidebar list