document.body.style.overflowY = "scroll"; if (location.hash && location.hash.length > 0) { var initialQuery = location.hash; if (initialQuery[0] == "#") { initialQuery = initialQuery.slice(1); } document.getElementById("query").value = decodeURIComponent(initialQuery); } var indexContainer = document.getElementById("cineraIndex"); var projectID = indexContainer.attributes.getNamedItem("data-project").value; var theme = indexContainer.classList.item(0); var baseURL = indexContainer.attributes.getNamedItem("data-baseURL").value; var playerLocation = indexContainer.attributes.getNamedItem("data-playerLocation").value; var indexSort = indexContainer.querySelector("#cineraIndexSort"); var indexEntries = indexContainer.querySelector("#cineraIndexEntries"); var indexSortChronological = true; indexSort.addEventListener("click", function(ev) { if(indexSortChronological) { this.firstChild.nodeValue = "Sort: New to Old ⏷" indexEntries.style.flexFlow = "column-reverse"; } else { this.firstChild.nodeValue = "Sort: Old to New ⏶" indexEntries.style.flexFlow = "column"; } indexSortChronological = !indexSortChronological; }); var lastQuery = null; var resultsToRender = []; var resultsIndex = 0; var resultsMarkerIndex = 0; var resultsContainer = document.getElementById("cineraResults"); var rendering = false; var dayContainerPrototype = document.createElement("DIV"); dayContainerPrototype.classList.add("dayContainer"); dayContainerPrototype.classList.add(theme); var dayNamePrototype = document.createElement("SPAN"); dayNamePrototype.classList.add("dayName"); dayContainerPrototype.appendChild(dayNamePrototype); var markerListPrototype = document.createElement("DIV"); markerListPrototype.classList.add("markerList"); markerListPrototype.classList.add(theme); dayContainerPrototype.appendChild(markerListPrototype); var markerPrototype = document.createElement("A"); markerPrototype.classList.add("marker"); markerPrototype.setAttribute("target", "_blank"); var highlightPrototype = document.createElement("B"); var episodes = []; function getEpisodeName(filename) { var day = filename; var dayParts = day.match(/([a-zA-Z_-]+)([0-9]+)?([a-zA-Z]+)?/); day = dayParts[1].slice(0, 1).toUpperCase() + dayParts[1].slice(1) + (dayParts[2] ? " " + dayParts[2] : "") + (dayParts[3] ? " " + dayParts[3].toUpperCase() : ""); return day; } function markerTime(totalTime) { var markTime = "("; var hours = Math.floor(totalTime / 60 / 60); var minutes = Math.floor(totalTime / 60) % 60; var seconds = totalTime % 60; if (hours > 0) { markTime += padTimeComponent(hours) + ":"; } markTime += padTimeComponent(minutes) + ":" + padTimeComponent(seconds) + ")"; return markTime; } function padTimeComponent(component) { return (component < 10 ? "0" + component : component); } function runSearch() { var queryStr = document.getElementById("query").value; if (lastQuery != queryStr) { var oldResultsContainer = resultsContainer; resultsContainer = oldResultsContainer.cloneNode(false); oldResultsContainer.parentNode.insertBefore(resultsContainer, oldResultsContainer); oldResultsContainer.remove(); resultsIndex = 0; resultsMarkerIndex = 0; } lastQuery = queryStr; resultsToRender = []; var numEpisodes = 0; var numMarkers = 0; var totalSeconds = 0; if (queryStr && queryStr.length > 0) { indexContainer.style.display = "none"; if (episodes.length > 0) { var query = new RegExp(queryStr.replace("(", "\\(").replace(")", "\\)").replace(/\|+/, "\|").replace(/\|$/, "").replace(/(^|[^\\])\\$/, "$1"), "gi"); for (var i = 0; i < episodes.length; ++i) { var episode = episodes[i]; var matches = []; for (var j = 0; j < episode.markers.length; ++j) { query.lastIndex = 0; var result = query.exec(episode.markers[j].text); if (result && result[0].length > 0) { numMarkers++; matches.push(episode.markers[j]); if (j < episode.markers.length-1) { totalSeconds += episode.markers[j+1].totalTime - episode.markers[j].totalTime; } } } if (matches.length > 0) { numEpisodes++; resultsToRender.push({ query: query, episode: episode, matches: matches }); } } if (!rendering) { renderResults(); } } else { document.querySelector(".spinner").classList.add("show"); } } else { indexContainer.style.display = "block"; } var totalTime = Math.floor(totalSeconds/60/60) + "h " + Math.floor(totalSeconds/60)%60 + "m " + totalSeconds%60 + "s "; document.getElementById("cineraResultsSummary").textContent = "Found: " + numEpisodes + " episodes, " + numMarkers + " markers, " + totalTime + "total."; } function renderMatches(renderStart) { var query = resultsToRender[resultsIndex].query; var episode = resultsToRender[resultsIndex].episode; var matches = resultsToRender[resultsIndex].matches; var markerList = null; if (resultsMarkerIndex == 0) { var dayContainer = dayContainerPrototype.cloneNode(true); var dayName = dayContainer.children[0]; markerList = dayContainer.children[1]; dayName.textContent = episode.day + ": " + episode.title; resultsContainer.appendChild(dayContainer); } else { markerList = document.querySelector("#cineraResults > .dayContainer:nth-child(" + (resultsIndex+1) + ") .markerList"); } do { var match = matches[resultsMarkerIndex]; var marker = markerPrototype.cloneNode(); var playerURLPrefix = (baseURL ? baseURL + "/" : "") + (playerLocation ? playerLocation + "/" : ""); marker.setAttribute("href", playerURLPrefix + episode.filename.replace(/"/g, "") + "/#" + match.totalTime); query.lastIndex = 0; var cursor = 0; var text = match.text; var result = null; marker.appendChild(document.createTextNode(match.prettyTime + " ")); while (result = query.exec(text)) { if (result.index > cursor) { marker.appendChild(document.createTextNode(text.slice(cursor, result.index))); } var highlightEl = highlightPrototype.cloneNode(); highlightEl.textContent = result[0]; marker.appendChild(highlightEl); cursor = result.index + result[0].length; } if (cursor < text.length) { marker.appendChild(document.createTextNode(text.slice(cursor, text.length))); } markerList.appendChild(marker); resultsMarkerIndex++; } while (resultsMarkerIndex < matches.length && performance.now() - renderStart < 1); return resultsMarkerIndex == matches.length; } function renderResults() { if (resultsIndex < resultsToRender.length) { rendering = true; var renderStart = performance.now(); while (resultsIndex < resultsToRender.length && performance.now() - renderStart < 1) { var done = renderMatches(renderStart); if (done) { resultsMarkerIndex = 0; resultsIndex++; } } requestAnimationFrame(renderResults); } else { rendering = false; } } var queryEl = document.getElementById("query") queryEl.addEventListener("input", function(ev) { history.replaceState(null, null, "#" + encodeURIComponent(queryEl.value)); runSearch(); }); var xhr = new XMLHttpRequest(); xhr.addEventListener("load", function() { var contents = xhr.response; var lines = contents.split("\n"); var mode = "none"; var episode = null; for (var i = 0; i < lines.length; ++i) { var line = lines[i]; if (line.trim().length == 0) { continue; } if (line == "---") { if (episode != null) { episode.filename = episode.name; episode.day = getEpisodeName(episode.filename + ".html.md"); episodes.push(episode); } episode = {}; mode = "none"; } else if (line.startsWith("name:")) { episode.name = line.slice(6); } else if (line.startsWith("title:")) { episode.title = line.slice(7).replace(/"/g, ""); } else if (line.startsWith("markers")) { mode = "markers"; episode.markers = []; } else if (mode == "markers") { var match = line.match(/"(\d+)": "(.+)"/); if (match == null) { console.log(name, line); } else { var totalTime = parseInt(line.slice(1)); var marker = { totalTime: totalTime, prettyTime: markerTime(totalTime), text: match[2].replace(/\\"/g, "\"") } episode.markers.push(marker); } } } document.querySelector(".spinner").classList.remove("show"); runSearch(); }); xhr.addEventListener("error", function() { console.error("Failed to load content"); }); var indexLocation = (baseURL ? baseURL + "/" : "") + projectID + ".index"; xhr.open("GET", indexLocation); xhr.setRequestHeader("Content-Type", "text/plain"); xhr.send(); runSearch();