Skip to content

Commit f9851bf

Browse files
Copilotmmcky
andcommitted
Add local JavaScript fix for collapse scroll positioning issue
Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com>
1 parent c0f08bf commit f9851bf

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-0
lines changed

lectures/_config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ sphinx:
7575
html_favicon: _static/lectures-favicon.ico
7676
html_theme: quantecon_book_theme
7777
html_static_path: ['_static']
78+
html_js_files: ['collapse-fix.js']
7879
html_theme_options:
7980
authors:
8081
- name: Thomas J. Sargent

lectures/_static/collapse-fix.js

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Fix for collapse scroll positioning issue
3+
* This script improves the scroll behavior when collapsing code blocks
4+
* for better reading continuity.
5+
*
6+
* The issue: when clicking collapse, the code block gets positioned too high
7+
* in the viewport, interrupting the reading flow.
8+
*
9+
* The solution: position the collapsed code block so its bottom is roughly
10+
* 1/3 from the top of the viewport, leaving visible content below for
11+
* continuous reading.
12+
*/
13+
14+
document.addEventListener("DOMContentLoaded", function () {
15+
// Wait for the theme's JavaScript to load and set up collapse functionality
16+
setTimeout(() => {
17+
console.log('Applying collapse scroll behavior fix...');
18+
19+
const collapsableCodeToggles = document.querySelectorAll(
20+
"div.cell[class*='tag_collapse'] .collapse-toggle-bar",
21+
);
22+
23+
console.log(`Found ${collapsableCodeToggles.length} collapse toggles to fix`);
24+
25+
// Remove existing event listeners by cloning and replacing elements
26+
for (let i = 0; i < collapsableCodeToggles.length; i++) {
27+
const oldToggle = collapsableCodeToggles[i];
28+
const newToggle = oldToggle.cloneNode(true);
29+
oldToggle.parentNode.replaceChild(newToggle, oldToggle);
30+
31+
// Add improved event listener
32+
newToggle.addEventListener("click", function (e) {
33+
console.log('Collapse toggle clicked with improved behavior');
34+
e.preventDefault();
35+
var codeBlock = this.closest("div.cell[class*='tag_collapse']");
36+
var codeBlockH = codeBlock.querySelector(".highlight");
37+
var indicator = this.querySelector(".collapse-indicator");
38+
39+
if (codeBlock.classList.contains("expanded")) {
40+
console.log('Collapsing code block...');
41+
codeBlock.classList.remove("expanded");
42+
indicator.textContent = "Expand";
43+
44+
// Apply height based on collapse class
45+
const collapseAccToHeight = (classList, elH) => {
46+
for (let className of classList) {
47+
if (className.startsWith("tag_collapse-")) {
48+
const index = className.indexOf("-");
49+
const height = className.substring(index + 1);
50+
if (height && !isNaN(height)) {
51+
elH.style.height = parseInt(height) + 0.5 + "em";
52+
return true;
53+
}
54+
}
55+
}
56+
return false;
57+
};
58+
59+
collapseAccToHeight(codeBlock.classList, codeBlockH);
60+
61+
// Improved scroll behavior for better reading continuity
62+
setTimeout(() => {
63+
console.log('Applying improved scroll positioning...');
64+
const rect = codeBlock.getBoundingClientRect();
65+
const viewportHeight = window.innerHeight;
66+
67+
// Position the collapsed code block so the reader can continue reading
68+
// Position the bottom of the collapsed block about 30% from the top of viewport
69+
// This leaves about 70% of the viewport showing content below the collapsed block
70+
const targetPositionFromTop = viewportHeight * 0.3;
71+
const currentScrollTop = window.pageYOffset || document.documentElement.scrollTop;
72+
const elementTop = rect.top + currentScrollTop;
73+
const elementHeight = rect.height;
74+
75+
// Calculate scroll position to put the bottom of collapsed block at target position
76+
const newScrollTop = elementTop + elementHeight - targetPositionFromTop;
77+
78+
// Ensure we don't scroll past page boundaries
79+
const maxScrollTop = Math.max(0, document.documentElement.scrollHeight - viewportHeight);
80+
const finalScrollTop = Math.max(0, Math.min(newScrollTop, maxScrollTop));
81+
82+
console.log(`Scrolling to position ${finalScrollTop} for optimal reading flow`);
83+
84+
window.scrollTo({
85+
top: finalScrollTop,
86+
behavior: 'smooth'
87+
});
88+
}, 150); // Slightly longer delay for height change to complete
89+
} else {
90+
console.log('Expanding code block...');
91+
codeBlock.classList.add("expanded");
92+
indicator.textContent = "Collapse";
93+
codeBlockH.style.height = "auto";
94+
}
95+
});
96+
}
97+
}, 1500); // Wait for theme JS to fully load
98+
});

0 commit comments

Comments
 (0)