From 1031c61d0c191aeec0707d6dff755fca7ab291a2 Mon Sep 17 00:00:00 2001 From: Abijeet Date: Thu, 2 Nov 2017 01:14:06 +0530 Subject: [PATCH 1/4] Fixes #466. Adds support for header highlighting using intersection observer. --- resources/assets/js/pages/page-show.js | 53 ++++++++++++++++++++++++++ resources/assets/sass/_lists.scss | 3 ++ 2 files changed, 56 insertions(+) diff --git a/resources/assets/js/pages/page-show.js b/resources/assets/js/pages/page-show.js index 14437cd68..15acddf85 100644 --- a/resources/assets/js/pages/page-show.js +++ b/resources/assets/js/pages/page-show.js @@ -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 diff --git a/resources/assets/sass/_lists.scss b/resources/assets/sass/_lists.scss index d30d4d4a2..298ce32cb 100644 --- a/resources/assets/sass/_lists.scss +++ b/resources/assets/sass/_lists.scss @@ -82,6 +82,9 @@ .h6 { margin-left: $nav-indent*4; } + .current-heading { + font-weight: bold; + } } // Sidebar list From bdba25b6f2e9361229b43c646b40f4e9fbba0ed7 Mon Sep 17 00:00:00 2001 From: Abijeet Date: Sun, 5 Nov 2017 20:23:16 +0530 Subject: [PATCH 2/4] Refactored all functionality into one function. Changed margin-top. --- resources/assets/js/pages/page-show.js | 90 ++++++++++++++------------ 1 file changed, 47 insertions(+), 43 deletions(-) diff --git a/resources/assets/js/pages/page-show.js b/resources/assets/js/pages/page-show.js index 15acddf85..3693031fb 100644 --- a/resources/assets/js/pages/page-show.js +++ b/resources/assets/js/pages/page-show.js @@ -156,53 +156,57 @@ let setupPageShow = window.setupPageShow = function (pageId) { 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); - } - }); + addPageHighlighting(); } - 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); + function addPageHighlighting() { + let $pageNav = null; - // observe each heading - for (let i = 0; i !== headings.length; ++i) { - pageNavObserver.observe(headings[i]); - } + $(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); + } + }); + + function addNavObserver(headings) { + // Setup the intersection observer. + // margin top = -35px to trigger the threshold change before the heading + // has completely left the viewport on the top. + let intersectOpts = { + rootMargin: '-35px 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'); + } } - - 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 From 8378f068892a51bc456e1dcb65dda34a86d240a7 Mon Sep 17 00:00:00 2001 From: Abijeet Date: Tue, 14 Nov 2017 23:54:25 +0530 Subject: [PATCH 3/4] Highlights all headings currently visible. Also fixes extra scrollbar appearing in Firefox. --- resources/assets/js/pages/page-show.js | 24 +++++++++++++----------- resources/assets/sass/_grid.scss | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/resources/assets/js/pages/page-show.js b/resources/assets/js/pages/page-show.js index 3693031fb..02958017c 100644 --- a/resources/assets/js/pages/page-show.js +++ b/resources/assets/js/pages/page-show.js @@ -176,7 +176,7 @@ let setupPageShow = window.setupPageShow = function (pageId) { // margin top = -35px to trigger the threshold change before the heading // has completely left the viewport on the top. let intersectOpts = { - rootMargin: '-35px 0px 0px 0px', + rootMargin: '0px 0px 0px 0px', threshold: 1.0 } $pageNav = $('.sidebar-page-nav'); @@ -189,22 +189,24 @@ let setupPageShow = window.setupPageShow = function (pageId) { } function cbHeadingVisible(entries, observer) { - let element = null; for (let i = 0; i !== entries.length; ++i) { let currentEntry = entries[i]; + let element = currentEntry.target; // 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; + if (currentEntry.intersectionRatio === 1) { + highlightElement(element.id); } else { - break; + removeHighlight(element.id); } } - if (!element) { - return; - } - let elementId = element.id; - $pageNav.find('a').removeClass('current-heading'); - $pageNav.find('a[href="#' + elementId + '"]').addClass('current-heading'); + } + + function highlightElement(elementId) { + $pageNav.find('a[href="#' + elementId + '"]').addClass('current-heading'); + } + + function removeHighlight(elementId) { + $pageNav.find('a[href="#' + elementId + '"]').removeClass('current-heading'); } } }; diff --git a/resources/assets/sass/_grid.scss b/resources/assets/sass/_grid.scss index 0f755e9f0..4cef2cebd 100644 --- a/resources/assets/sass/_grid.scss +++ b/resources/assets/sass/_grid.scss @@ -135,7 +135,7 @@ body.flexbox { width: 30%; left: 0; height: 100%; - overflow-y: scroll; + overflow-y: auto; -ms-overflow-style: none; //background-color: $primary-faded; border-left: 1px solid #DDD; From 22613084152c4ec2cca2761710cf6acb436ead21 Mon Sep 17 00:00:00 2001 From: Abijeet Date: Wed, 15 Nov 2017 00:04:35 +0530 Subject: [PATCH 4/4] Removed invalid comments, and formatted the code. --- resources/assets/js/pages/page-show.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/resources/assets/js/pages/page-show.js b/resources/assets/js/pages/page-show.js index 02958017c..32c1b6f5b 100644 --- a/resources/assets/js/pages/page-show.js +++ b/resources/assets/js/pages/page-show.js @@ -173,8 +173,6 @@ let setupPageShow = window.setupPageShow = function (pageId) { function addNavObserver(headings) { // Setup the intersection observer. - // margin top = -35px to trigger the threshold change before the heading - // has completely left the viewport on the top. let intersectOpts = { rootMargin: '0px 0px 0px 0px', threshold: 1.0 @@ -192,7 +190,7 @@ let setupPageShow = window.setupPageShow = function (pageId) { for (let i = 0; i !== entries.length; ++i) { let currentEntry = entries[i]; let element = currentEntry.target; - // check if its currently visible and its distance from top of viewport is less than 100 + // check if its currently visible if (currentEntry.intersectionRatio === 1) { highlightElement(element.id); } else { @@ -202,7 +200,7 @@ let setupPageShow = window.setupPageShow = function (pageId) { } function highlightElement(elementId) { - $pageNav.find('a[href="#' + elementId + '"]').addClass('current-heading'); + $pageNav.find('a[href="#' + elementId + '"]').addClass('current-heading'); } function removeHighlight(elementId) {