Skip to content

Commit 22459db

Browse files
committed
Alternate approach to delaying showing problem content until after MathJax content has rendered.
In addition to setting the `.problem-content` div not visible, this injects an overlay div that is position absolutely over the `.problem-content` div with the same size. It also gets that `.problem-content` class so that it appears like an empty problem. It also pulsatess slowly using essentially bootstrap's `placeholder-glow` animation (although implemented with a JavaScript animation instead of css). In addition a height transition is set on the div so that it grows a bit slower than just the immediate jump in size. Perhaps this will allay the appearance of the content below jumping down in some cases since now there is something shown instead of just an empty space. This is an alternate approach to #3003 that maybe some will like better?
1 parent f2e3ea3 commit 22459db

1 file changed

Lines changed: 43 additions & 0 deletions

File tree

htdocs/js/MathJaxConfig/mathjax-config.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
if (!window.MathJax) {
2+
const problems = [];
3+
24
window.MathJax = {
35
tex: { packages: { '[+]': webworkConfig?.showMathJaxErrors ? [] : ['noerrors'] } },
46
loader: {
@@ -103,6 +105,16 @@ if (!window.MathJax) {
103105

104106
MathJax.startup.defaultReady();
105107
MathJax.startup.document.constructor.ProcessBits.allocate('findScripts');
108+
},
109+
pageReady() {
110+
return MathJax.startup.defaultPageReady().then(() => {
111+
for (const [problemContent, loaderOverlay, resizeObserver] of problems) {
112+
resizeObserver.disconnect();
113+
loaderOverlay.remove();
114+
problemContent.style.visibility = '';
115+
}
116+
problems.length = 0;
117+
});
106118
}
107119
},
108120
options: {
@@ -134,4 +146,35 @@ if (!window.MathJax) {
134146
ignoreHtmlClass: 'tex2jax_ignore'
135147
}
136148
};
149+
150+
for (const problemContent of document.querySelectorAll('.problem-content')) {
151+
problemContent.style.visibility = 'hidden';
152+
const loaderOverlay = document.createElement('div');
153+
loaderOverlay.classList.add('problem-content');
154+
const bodyRectangle = problemContent.getBoundingClientRect();
155+
loaderOverlay.style.position = 'absolute';
156+
loaderOverlay.style.top = `${bodyRectangle.y}px`;
157+
loaderOverlay.style.left = `${bodyRectangle.x}px`;
158+
loaderOverlay.style.width = `${bodyRectangle.width}px`;
159+
loaderOverlay.style.height = `${bodyRectangle.height}px`;
160+
loaderOverlay.style.overflow = 'clip';
161+
loaderOverlay.style.transition = 'height 0.3s ease';
162+
loaderOverlay.animate([{ opacity: 1 }, { opacity: 0.2 }, { opacity: 1 }], {
163+
duration: 2000,
164+
iterations: Infinity,
165+
easing: 'ease-in-out'
166+
});
167+
loaderOverlay.style.cursor = 'wait';
168+
169+
problemContent.after(loaderOverlay);
170+
const resizeObserver = new ResizeObserver(() => {
171+
const bodyRectangle = problemContent.getBoundingClientRect();
172+
loaderOverlay.style.top = `${bodyRectangle.top}px`;
173+
loaderOverlay.style.left = `${bodyRectangle.left}px`;
174+
loaderOverlay.style.width = `${bodyRectangle.width}px`;
175+
loaderOverlay.style.height = `${bodyRectangle.height}px`;
176+
});
177+
resizeObserver.observe(problemContent);
178+
problems.push([problemContent, loaderOverlay, resizeObserver]);
179+
}
137180
}

0 commit comments

Comments
 (0)