INQUIRY
Hello, I am currently working on building a straightforward navigation site and I have a question regarding how to modify or add a class to one of the li elements within the inline table of contents (toc) on the right side. I want to style it using CSS.
This is my current page:
Link to My Page
I aim to achieve a similar effect as demonstrated here: Desired Page Behavior
(If you scroll up and down the main page, you will notice changes in the styling of the toc element on the right)
You can also observe the same behavior in this example: Example Page (Notice how the toc on the right changes as you scroll)
I tried analyzing the JavaScript used in these pages, but found it quite complex and challenging to decipher. So, I'm reaching out for any suggestions or insights.
Thank you,
Sachin
NOTE - QUERY RESOLVED AND CODE updated via the provided link based on responses below
CODE IMPLEMENTED
The CSS styles I've worked on:
.doc-outline ul li a {
text-decoration: none;
}
.doc-outline ul li a:hover {
text-decoration: underline;
}
.doc-outline li.selected {
font-weight: 600;
border-color: #0065b3;
}
.doc-outline a:visited {
color: #0065b3;
}
Relevant sections of HTML code
<div class="primary-holder column is-two-thirds-tablet is-three-quarters-desktop">
<div class="columns has-large-gaps is-gapless-mobile">
<!-- MAIN CONTENT -->
<div id="main-column" class="column is-full is-four-fifths-desktop">
<main id="main" class ="content" lang="eng-us">
<h1 id="learn-conditional-logic-with-branch-and-loop-statements">Learn conditional logic with branch and loop statements</h1>.....etc.
</main>
</div>
<!-- TOC ON THE RIGHT SIDE -->
<div class="right-sidebar column is-one-quarter is-one-fifth-desktop is-hidden-mobile is-hidden-tablet-only">
<nav class="doc-outline is-fixed is-vertically-scrollable", id="affixed-right-sidebar">
<nav id="side-doc-outline">
<ul class="section-nav">
<li class="toc-entry toc-h2"><a href="#make-decisions-using-the-if-statement">Make decisions using the if statement</a></li>
<li class="toc-entry toc-h2"><a href="#make-if-and-else-work-together">Make if and else work together</a></li>
<li class="toc-entry toc-h2"><a href="#use-loops-to-repeat-operations">Use loops to repeat operations</a></li>
<li class="toc-entry toc-h2"><a href="#work-with-the-for-loop">Work with the for loop</a></li>
<li class="toc-entry toc-h2"><a href="#created-nested-loops">Created nested loops</a>
<ul>
<li class="toc-entry toc-h3"><a href="#test">Test</a></li>
</ul>
</li>
<li class="toc-entry toc-h2"><a href="#combine-branches-and-loops">Combine branches and loops</a></li>
</ul>
</nav>
</nav>
</div>
</div>
</div>
JavaScript Functionality
Modified JS code utilized through the provided link following feedback - Potential for simplifying some code blocks...
Highlighting Correct Menu Item in RHS TOC
(function rhsToc() {
// Initialize global variables outside functions
let observer = new IntersectionObserver(handler, { threshold: [0] });
let selection;
let headings = [...document.querySelectorAll("#main h2, #main h3")];
let rhsToc = [...document.querySelectorAll("ul.section-nav a")];
let a = null;
let lastScroll = 0;
let headingMenuMap = headings.reduce((acc, h) => {
let id = h.id;
acc[id] = rhsToc.find(a => a.getAttribute("href") === "#" + id);
return acc;
}, {})
headings.forEach(elem => observer.observe(elem));
// Detect Scroll Direction
scrollDetect();
let scrollDirection = [];
function scrollDetect(){
var lastScroll = 0;
window.onscroll = function() {
let currentScroll = document.documentElement.scrollTop || document.body.scrollTop; // Get Current Scroll Value
if (currentScroll > 0 && lastScroll <= currentScroll){
lastScroll = currentScroll;
scrollDirection = "down";
}else{
lastScroll = currentScroll;
scrollDirection = "up"
}
};
}
function handler(entries) {
// Update selection with current entries.
selection = (selection || entries).map( s => entries.find(e => e.target.id === s.target.id) || s);
// Keep only true values
filteredArr = selection.filter(x => x.isIntersecting == true );
// Find last visible/intersecting (use a copied array for that, since reverse is an in place method)
let firstVisibleId = [...selection].find(x => x.isIntersecting) ? [...selection].find(x => x.isIntersecting).target.id : null;
// Is a firstVisibleId returned? If not, then follow the below steps
if (firstVisibleId === null){
// Were you scrolling down? - Then do nothing
if (scrollDirection == "down"){
// Do nothing!
} else {
// Scrolling up - Remove 'selected' from current menu item and add it to the menu item above it
const current = document.querySelector(`#side-doc-outline > ul li.selected`);
if (current) {
current.classList.remove('selected');
}
// If there is no previous sibling with a class of 'toc-entry', you're at the top of the branch, so move up a level unless you reach section-nav
if(previousByClass(a.parentElement, "toc-entry") == null){
parent_by_selector(a.parentElement, "ul:not(.section-nav)") ? parent_by_selector(a.parentElement, "ul:not(.section-nav)").parentElement.classList.add("selected") : null;
} else {
previousByClass(a.parentElement, "toc-entry") ? previousByClass(a.parentElement, "toc-entry").classList.add("selected") : null;
}
}
return;
}
// Otherwise, remove 'selected' from the active item in the RHS toc
const current = document.querySelector(`#side-doc-outline > ul li.selected`);
if (current) {
current.classList.remove('selected');
}
// Add 'selected' to the target item in the RHS toc
for (s of selection) {
let targetId = s.target.id;
// Get the entry from the generated map.
a = headingMenuMap[targetId];
if (firstVisibleId === targetId) {
a.parentElement.classList.add("selected");
return;
}
};
}
})();
// Ensure Functions Initiate After Document Loads
document.addEventListener('DOMContentLoaded', tree);