// QUOTES HIGHLIGHT let quotes = []; let cards = []; let callback = (entries) => { entries.forEach((entry) => { entry.target.innerHTML = highlight( quotes[entry.target.getAttribute("data-quote")], entry.intersectionRatio ); }); }; const filtersContainer = document.getElementById("filters"); let filters = new Set(["dev", "daily", "research"]); filtersContainer.addEventListener("click", (e) => { if (e.target.tagName === "LI") { let category = e.target.getAttribute("data-tag"); // if (filters.size == 1) { // filters = new Set(["dev", "daily", "research"]); // [...filtersContainer.getElementsByClassName('tag')].forEach(tag =>) // } else if (filters.has(category)) { e.target.classList.remove("active"); filters.delete(category); } else { e.target.classList.add("active"); filters.add(category); } } showSelectedUpdates(); }); function showSelectedUpdates() { cards.forEach((card) => { card.classList.remove("selected"); let categories = card .getAttribute("data-tag") .split(",") .map((tag) => tag.trim()); categories.forEach((category) => { if (filters.has(category)) card.classList.add("selected"); }); }); } // 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 ( '' + text.slice(0, scrollCursor) + "" + text.slice(scrollCursor) ); } // UPDATES // 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. const updatesContainer = document.getElementById("updates-container"); let updates = []; fetch("./updates.json") .then((response) => response.json()) .then((data) => { updates = [...data.updates.reverse()]; populateContents(); showSelectedUpdates(); }); function populateContents() { updates.forEach((update) => createUpdate(update)); } function createUpdate(update) { let card = document.createElement("div"); card.classList.add("update"); card.setAttribute("data-tag", update.tag); // 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("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); cards.push(card); }