Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved index sidebar #732

Merged
merged 16 commits into from
Apr 15, 2020
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/static/css/page.css
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@
.index .index-box {
margin: 20px 0;
padding: 8px 16px;
top: 0;
}

.index .index-box.sticky {
position: -webkit-sticky;
position: sticky;
}

.page-height {
max-height: 100vh;
overflow: auto;
}
.index .header {
color: #1A2B49;
Expand Down Expand Up @@ -417,7 +428,12 @@ figure .fig-desktop {
max-width: 100%;
height: auto;
}

.index .sticky {
position: static;
}
.index .index-box {
max-height: 100%;
}
}

/* Code highlighting */
Expand Down
92 changes: 92 additions & 0 deletions src/static/js/chapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,98 @@ function setDiscussionCount() {
}
}

function indexHighlighter() {
//Only activate this if IntersectionObserver is supported
if(!('IntersectionObserver' in window)) {
gtag('event', 'index-highlighter', { 'event_category': 'user', 'event_label': 'not-enabled', 'value': 0 });
return;
}

var chapterIndex = document.querySelector('.index-box');

// Check if user has set reduced motion and only continue if not
var hasOSReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (hasOSReducedMotion) {
console.log('User has set prefers-reduced-motion to ' + hasOSReducedMotion + ' so not highlighting the current section in chapter index');
gtag('event', 'prefers-reduced-motion', { 'event_category': 'user', 'event_label': 'reduce', 'value': 0 });
gtag('event', 'index-highlighter', { 'event_category': 'user', 'event_label': 'not-enabled', 'value': 0 });
return;
}

// Check if 'position:sticky' is supported (as this is not great UX when not so don't bother)
// Add the sticky class (which sets 'position:sticky') and then test if that stuck :-)
// Also use endsWith to support vendor prefixes (Safari v12 needs this)
chapterIndex && chapterIndex.classList.add('sticky');
var chapterIndexStyles = getComputedStyle(chapterIndex);
if (!chapterIndexStyles || !chapterIndexStyles.position || !chapterIndexStyles.position.endsWith('sticky')) {
gtag('event', 'index-highlighter', { 'event_category': 'user', 'event_label': 'not-enabled', 'value': 0 });
return;
}

// Restrict the page height of the index to the page-height, as we're going to scroll this.
chapterIndex.classList.add('page-height');

// Create a function to handle highlighting a new index item
// that will be called by the IntersectionObserver
function highlightIndexEntry(link) {

var indexLink = document.querySelector('.index-box a[href="#' + link + '"]');
var oldIndexLink = document.querySelector('.index-box .active');

if (!indexLink || indexLink.isEqualNode(oldIndexLink)) {
return;
}

if(oldIndexLink) {
oldIndexLink.classList.remove('active');
}
indexLink.parentNode.classList.add('active');

// If the index is displayed in full then we're done!
if (chapterIndex.scrollHeight <= chapterIndex.clientHeight) {
return;
}
// Otherwise if too large to display in full then scroll to this element
var currentPosition = indexLink.scrollTop;
var currentNode = indexLink;
// Walk the node back up to the index-scroller to get the total offset
// of this entry, relative to the full Index
while (currentNode && currentNode.parentNode != chapterIndex) {
currentPosition = currentPosition + currentNode.offsetTop;
currentNode = currentNode.parentNode;
}
// Show the current image in the middle of the screen
chapterIndex.scrollTop = currentPosition - (chapterIndex.clientHeight / 2);
}

// Set up a new Interstection Observer for when the title is 80% from the bottom of the page
var options = {
root: null,
rootMargin: "0px 0px -80% 0px",
threshold: null
};
var observer = new IntersectionObserver(function(entries) {
for (index = 0; index < entries.length; ++index) {
var entry = entries[index];

if (entry.isIntersecting && entry.target && entry.target.id) {
highlightIndexEntry(entry.target.id);
}
}
}, options);

// Add an intersection observer to each heading
var all_headings = document.querySelectorAll('article h1, article h2, article h3');
for (index = 0; index < all_headings.length; ++index) {
var heading = all_headings[index];
observer.observe(heading);
};

gtag('event', 'index-highlighter', { 'event_category': 'user', 'event_label': 'enabled', 'value': 0 });

}

indexHighlighter();
removeLazyLoadingOnPrint();
upgradeInteractiveFigures();
setDiscussionCount();
3 changes: 2 additions & 1 deletion src/templates/base/2019/methodology.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ <h2 class="header">
<button class="index-btn">{{ self.index_title() }}</button>
<span class="no-button">{{ self.index_title() }}</span>
</h2>
{{ self.index() }}
{{ self.index() }}
</div>
</nav>

Expand All @@ -31,4 +31,5 @@ <h1 class="title title-lg">{{ self.methodology_title() }}</h1>
{% block scripts %}
{{ super() }}
{{ self.index_menu_script() }}
<script src='/static/js/chapter.js?v=2' defer></script>
{% endblock %}