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 12 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 .index-box.sticky {
position: static;
}
.index .index-scroller {
max-height: 100%;
}
}

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

function indexHighlighter() {
//Only activate this if IntersectionObserver is supported
if('IntersectionObserver' in window){
tunetheweb marked this conversation as resolved.
Show resolved Hide resolved
var indexScroller = document.querySelector('.index-scroller');

// 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');
} else {
tunetheweb marked this conversation as resolved.
Show resolved Hide resolved

// 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 :-)
indexScroller && indexScroller.parentNode && indexScroller.parentNode.classList.add('sticky');
var indexScrollerStyles = getComputedStyle(indexScroller.parentNode);
if (indexScrollerStyles && indexScrollerStyles.position) {
//Handle vendor prefixes (still required for Safari 12)
if (indexScrollerStyles.position.endsWith('sticky')) {
tunetheweb marked this conversation as resolved.
Show resolved Hide resolved

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

var indexItems = {};
var currentItem;

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

var oldItem = currentItem;
tunetheweb marked this conversation as resolved.
Show resolved Hide resolved
var newItem = indexItems[link];
if (newItem){
newItem.classList.add('active');
if (oldItem && oldItem !== newItem) {
oldItem.classList.remove('active');
}
currentItem = newItem;

// If the index is too large to display in full then might need to change scroll
if (indexScroller.scrollHeight > indexScroller.clientHeight) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A simpler way to scroll to the active index item:

index.scrollIntoView({behavior: 'smooth', block: 'center'})

We can do without the smooth scrolling if needed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately can;'t use this as it scrolls the current element - which is fun when you have two scrolling elements like we do here! :-(

So works fine when clicking on the links in ToC, but not if focus is in main chapter text.

var currentPosition = currentItem.scrollTop;
var currentNode = currentItem;
// Walk the node back up to the index-scroller to get the total position of the element
while (currentNode && !currentNode.parentNode.classList.contains('index-scroller')) {
currentPosition = currentPosition + currentNode.offsetTop;
currentNode = currentNode.parentNode;
}

// Show the current image in the middle of the screen
indexScroller.scrollTop = currentPosition - (indexScroller.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) {
tunetheweb marked this conversation as resolved.
Show resolved Hide resolved
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);
};

// Let's create an index of all the index entries once, at page load
// This is done for performance reasons to save doing a DOM lookup each time
var all_index_entries = document.querySelectorAll('.index a');
for (index = 0; index < all_index_entries.length; ++index) {
var indexEntry = all_index_entries[index];
var href = indexEntry.getAttribute('href');
if (href && href.length > 1) {
href = href.substr(1);
indexItems[href] = indexEntry.parentNode;
}
}
}
}
}
}
}

indexHighlighter();
removeLazyLoadingOnPrint();
upgradeInteractiveFigures();
setDiscussionCount();
12 changes: 7 additions & 5 deletions src/templates/base/2019/base_chapter.html
Original file line number Diff line number Diff line change
Expand Up @@ -212,11 +212,13 @@
<main id="chapter" class="main">
<nav aria-label="{{ self.index_nav_title() }}" class="index">
<div class="index-box floating-card">
<h2 class="header">
<button class="index-btn" aria-expanded="false" aria-label="{{ self.open_the_index() }}">{{ self.index_title() }}</button>
<span class="no-button">{{ self.index_title() }}</span>
</h2>
{{ self.index() }}
<div class="index-scroller">
tunetheweb marked this conversation as resolved.
Show resolved Hide resolved
<h2 class="header">
<button class="index-btn" aria-expanded="false" aria-label="{{ self.open_the_index() }}">{{ self.index_title() }}</button>
<span class="no-button">{{ self.index_title() }}</span>
</h2>
{{ self.index() }}
</div>
</div>
</nav>

Expand Down
11 changes: 7 additions & 4 deletions src/templates/base/2019/methodology.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
<main id="methodology" class="main">
<nav class="index">
<div class="index-box floating-card">
<h2 class="header">
<button class="index-btn">{{ self.index_title() }}</button>
<span class="no-button">{{ self.index_title() }}</span>
</h2>
<div class="index-scroller">
<h2 class="header">
<button class="index-btn">{{ self.index_title() }}</button>
<span class="no-button">{{ self.index_title() }}</span>
</h2>
{{ self.index() }}
</div>
</div>
</nav>

Expand All @@ -31,4 +33,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 %}