You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
4.1 KiB
JavaScript
159 lines
4.1 KiB
JavaScript
const updatesContainer = document.getElementById("updates-container");
|
|
let updates = [];
|
|
let quotes = [];
|
|
|
|
let callback = (entries) => {
|
|
entries.forEach((entry) => {
|
|
entry.target.innerHTML = highlight(
|
|
quotes[entry.target.getAttribute("data-quote")],
|
|
entry.intersectionRatio
|
|
);
|
|
});
|
|
};
|
|
|
|
// Threshold Callback
|
|
|
|
let threshold = [];
|
|
for (let i = 0; i <= 1.0; i += 0.01) {
|
|
threshold.push(i);
|
|
}
|
|
|
|
let observer = new IntersectionObserver(callback, {
|
|
rootMargin: "100% 0% -50% 0%",
|
|
threshold: threshold,
|
|
});
|
|
|
|
// Karaoke highlight
|
|
|
|
function highlight(text, offset) {
|
|
let scrollCursor = text.length * offset;
|
|
return (
|
|
'<span class="highlight">' +
|
|
text.slice(0, scrollCursor) +
|
|
"</span>" +
|
|
text.slice(scrollCursor)
|
|
);
|
|
}
|
|
|
|
// Fetc the updates from the array in updates.json
|
|
// Each element of the array is structured like this:
|
|
//
|
|
// {
|
|
// "date": "October the 21st, 2021",
|
|
// "title": "2nd hand lifeboat script",
|
|
// "text": "Labore eiusmod labore pariatur elit nostrud ut magna cupidatat minim amet deserunt cillum id. Lorem consectetur incididunt anim sit do eu minim nisi id.",
|
|
// "quote": "Lorem elit magna esse reprehenderit fugiat labore est veniam ipsum labore est voluptate do."
|
|
// "media": {
|
|
// "type": "video",
|
|
// "src": "./assets/test-js.mp4",
|
|
// "alt": "An excerpt from 'When did software gone wrong?' highlighted progressively as in karaoke",
|
|
// "caption": "In every karaoke there are at least 2 voices: a text and a choir"
|
|
// }
|
|
// }
|
|
//
|
|
// Title, Text, Quote and Media are not mandatory.
|
|
// If some are not present, the createUpdate function will skip them
|
|
//
|
|
// Note that the Date is required, but its format is up to the user
|
|
//
|
|
// All the media elements require an alt description.
|
|
// This is for accessibility. It's a really good practice to provide quality alt text
|
|
// and we must pay attention to this.
|
|
|
|
fetch("./updates.json")
|
|
.then((response) => response.json())
|
|
.then((data) => {
|
|
updates = [...data.updates.reverse()];
|
|
populateContents();
|
|
});
|
|
|
|
function populateContents() {
|
|
updates.forEach((update) => createUpdate(update));
|
|
}
|
|
|
|
function createUpdate(update) {
|
|
let card = document.createElement("div");
|
|
card.classList.add("update");
|
|
|
|
// QUOTE
|
|
|
|
if (update.quote) {
|
|
let quote = document.createElement("blockquote");
|
|
quote.innerHTML = update.quote;
|
|
quote.setAttribute("data-quote", quotes.length);
|
|
quotes.push(update.quote);
|
|
card.appendChild(quote);
|
|
observer.observe(quote);
|
|
}
|
|
|
|
// LOG
|
|
let log = document.createElement("div");
|
|
log.classList.add("log");
|
|
|
|
// DATE
|
|
let date = document.createElement("div");
|
|
date.classList.add("date");
|
|
date.innerHTML = update.date;
|
|
log.appendChild(date);
|
|
|
|
// TITLE, if present
|
|
if (update.title) {
|
|
let title = document.createElement("h3");
|
|
title.classList.add("title");
|
|
title.innerHTML = update.title;
|
|
log.appendChild(title);
|
|
}
|
|
|
|
// MEDIA CONTENTS, if present
|
|
if (update.media) {
|
|
let media;
|
|
// IMAGE
|
|
if (update.media.type == "img") {
|
|
media = document.createElement("media");
|
|
media.classList.add("media");
|
|
|
|
let img = document.createElement("img");
|
|
img.src = update.media.src;
|
|
img.alt = update.media.alt;
|
|
media.appendChild(img);
|
|
|
|
if (update.media.caption) {
|
|
let caption = document.createElement("figcaption");
|
|
caption.innerHTML = update.media.caption;
|
|
media.appendChild(caption);
|
|
}
|
|
}
|
|
// VIDEO
|
|
if (update.media.type == "video") {
|
|
media = document.createElement("div");
|
|
media.classList.add("media");
|
|
|
|
let video = document.createElement("video");
|
|
video.src = update.media.src;
|
|
video.alt = update.media.alt;
|
|
video.setAttribute("autoplay", true);
|
|
video.setAttribute("loop", true);
|
|
media.appendChild(video);
|
|
|
|
if (update.media.caption) {
|
|
let caption = document.createElement("p");
|
|
caption.classList.add("caption");
|
|
caption.innerHTML = update.media.caption;
|
|
media.appendChild(caption);
|
|
}
|
|
}
|
|
log.appendChild(media);
|
|
}
|
|
|
|
// TEXT, if present
|
|
if (update.text) {
|
|
let text = document.createElement("p");
|
|
text.classList.add("text");
|
|
text.innerHTML = update.text;
|
|
log.appendChild(text);
|
|
}
|
|
|
|
card.appendChild(log);
|
|
updatesContainer.appendChild(card);
|
|
}
|