Public
Edited
Dec 18, 2023
Comments locked
1 star
Insert cell
Insert cell
Insert cell
Insert cell
viewof skipButton = skipEpigraphButton()
// DH: be nice to right-align this with para, and hide for the ramble (I guess it is primarily for the web-view where it looks fine)
Insert cell
Insert cell
Insert cell
Insert cell
reader = async (ele, numWords = 999999) => {
let reading = true;
let readerix = 0;
let readerMillis = 2000;
let readerSpans = [];
// see the comment in the display cell above
// for notebook only, the following line would not be necessary
let spans = Array.from(ele.children);
for (let i = 0; i < numWords; i++) {
if (mutable skipEpigraph) break;
await Promises.delay(readerMillis).then(() => {
let iOfLast = mod(readerix - numberOfVisibleWords, spans.length);
let lastCl = spans[iOfLast].classList;
if (lastCl.contains("visible")) {
lastCl.remove("visible");
// used to create readerWindow for testing:
readerSpans.shift();
}
let cl = spans[readerix].classList;
cl.add("visible");
// used to create readerWindow for testing:
readerSpans.push(spans[readerix].innerHTML);
// readerWindow.innerHTML = readerSpans.join(" "); // TESTing
// overall reading speed can be changed by adding millisecond basetime arg to timeToRead(word,basetime)
readerMillis = timeToRead(spans[readerix].innerText);
readerix = ++readerix % spans.length;
return;
});
}
if (mutable skipEpigraph) {
mutable skipEpigraph = false;
return;
}
// cleanup
for (let i = numWords - numberOfVisibleWords; i < numWords; i++) {
await Promises.delay(readerMillis).then(() => {
spans[i].classList.remove("visible");
});
}
}
Insert cell
timeToRead = (word, basetime = 150) => {
const syltime = basetime / 2; // most significant accumulator: these milliseconds per syllable
if (RiTa.isPunct(word)) {
return word.match(/[\.\?!]/) ? basetime * 3 : basetime * 1.5;
}
let syls = RiTa.syllables(word); // array of syllables
let time = basetime + syls.split("/").length * syltime; // syls * basic unit
time += syls.split(/[\/-]/).length * (syltime / 12); // add 1/12 of a syltime for each phoneme
time += word.match(/[,;:—]/) ? basetime : 0; // add basetime to a punctuated word
time += word.match(/[\.\?!]/) ? basetime * 2 : 0; // or add more for the end of a period
return time;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// viewof controls = startStop() // for debugging: toggle word replacing
Insert cell
Insert cell
Insert cell
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
mutable skipEpigraph = false
Insert cell
Insert cell
Insert cell
css = html`<style>
.container {
width: 80vw;
}

.epigraph {
font-style: italic;
font-size: 3.5vw;
}

.none {
display: none;
}

.readerWindow {
width: 70vw;
text-align: center;
}

.text {
opacity: .3;
transition: opacity .5s ease-in-out;
}

.text.visible {
opacity: 1;
}
</style>`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
laob_notebook_css
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more