1 /******************************
2 * JavaScript for talk slides *
6 ******************************/
12 var defaultIdx = 1; // set to slide index to show by default
13 var firstIdx = 2; // set no value if to use first available
14 var lastIdx; // set no value if to use last available
16 var pageTitle, headerText, subHeaderText;
17 var navPrev, navNext, navPrevNolink, navNextNolink;
19 // Slide timer - color variation of headerText
20 // Time per slide is total presentation length divided by number of slides
21 // except start and end slide.
22 var presLengthSeconds = 15 * 60;
23 var slideStart, timerMSec;
25 // Called when the document has been loaded.
26 function docLoaded() {
27 pageTitle = document.getElementsByTagName("title")[0];
28 headerText = document.getElementById("header-text");
29 subHeaderText = document.getElementById("subheader-text");
30 navPrev = document.getElementById("nav-prev");
31 navNext = document.getElementById("nav-next");
32 navPrevNolink = document.getElementById("nav-prev-nolink");
33 navNextNolink = document.getElementById("nav-next-nolink");
34 articleNodes = document.getElementsByTagName("article");
39 lastIdx = articleNodes.length - 1;
40 var slideSeconds = presLengthSeconds / (lastIdx - firstIdx);
41 timerMSec = 1000 * (slideSeconds / 3);
43 // Get a list of all slides (articles).
44 subHeaderText.textContent = articleNodes.length + " slides...";
45 for (var i = 0; i < articleNodes.length; ++i) {
46 subHeaderText.textContent = "Indexing slide " + i + " / " + articleNodes.length;
47 if (!articleNodes[i].id)
48 articleNodes[i].id = "slide_" + i;
50 slides[articleNodes[i].id] = {
52 "name": articleNodes[i].id,
53 "title": articleNodes[i].dataset.title ? articleNodes[i].dataset.title : articleNodes[i].id,
54 "obj": articleNodes[i],
55 "timeSeconds": articleNodes[i].dataset.seconds ? articleNodes[i].dataset.seconds : slideSeconds,
58 if (location.hash.length &&
59 (location.hash == "#" + articleNodes[i].id || location.hash == "#" + i)) {
60 articleNodes[i].setAttribute("aria-selected", "true");
61 currentSlide = slides[articleNodes[i].id];
67 currentIdx = defaultIdx;
68 currentSlide = slides[articleNodes[currentIdx].id];
69 currentSlide.obj.setAttribute("aria-selected", "true");
70 location.hash = "#" + currentSlide.name;
75 // Called when the hash part of the location changes.
76 function locationHashChanged() {
77 if (location.hash.length > 1) {
78 var hashtag = location.hash.substring(1);
79 // If not a number, treat as ID
80 if (isNaN(hashtag) && slides[hashtag]) {
81 currentSlide.obj.removeAttribute("aria-selected");
82 currentSlide = slides[hashtag];
83 currentIdx = currentSlide.idx;
84 currentSlide.obj.setAttribute("aria-selected", "true");
87 else if (articleNodes[hashtag]) {
88 currentSlide.obj.removeAttribute("aria-selected");
90 currentSlide = slides[articleNodes[currentIdx].id];
91 currentSlide.obj.setAttribute("aria-selected", "true");
96 window.onhashchange = locationHashChanged;
98 // Update the display after we updated what slide is shown.
99 function updateDisplay() {
100 if (currentIdx >= firstIdx && currentIdx <= lastIdx &&
101 currentSlide.name != "toc")
102 subHeaderText.textContent = (currentIdx - firstIdx + 1) + "/" +
103 (lastIdx - firstIdx + 1) + " - " +
106 subHeaderText.textContent = currentSlide.title;
107 pageTitle.textContent = headerText.textContent + ": " + currentSlide.title;
108 if (currentIdx > firstIdx && currentSlide.name != "toc") {
109 navPrev.hidden = false;
110 navPrev.href = "#" + articleNodes[currentIdx - 1].id;
111 navPrevNolink.hidden = true;
114 navPrev.hidden = true;
115 navPrevNolink.hidden = false;
117 if (currentIdx < lastIdx && currentSlide.name != "toc") {
118 navNext.hidden = false;
119 navNext.href = "#" + articleNodes[currentIdx + 1].id;
120 navNextNolink.hidden = true;
123 navNext.hidden = true;
124 navNextNolink.hidden = false;
126 headerText.className = "";
127 slideStart = new Date();
128 timerMSec = 1000 * (currentSlide.timeSeconds / 3);
129 if (currentSlide.name == "toc")
132 setTimeout(timerFired, timerMSec);
136 function createTOC() {
137 var list = document.getElementById("toc-list");
138 if (!list.getElementsByTagName("li").length) {
139 for (var slide in slides) {
140 if (slide != "toc") {
141 var item = document.createElement("li");
142 var link = document.createElement("a");
143 var slideHeaders = slides[slide].obj.getElementsByTagName("h1");
144 if (slideHeaders.length)
145 link.textContent = slideHeaders[0].textContent;
147 link.textContent = slides[slide].title;
148 link.href = "#" + slides[slide].name;
149 item.appendChild(link);
150 list.appendChild(item);
156 // Do timed color variation on slides.
157 function timerFired() {
158 var slideCurrent = new Date();
159 var secondsDiff = Math.round((slideCurrent.getTime() - slideStart.getTime()) / 1000);
160 if (secondsDiff >= currentSlide.timeSeconds) {
161 headerText.className = "overtime";
163 else if (secondsDiff >= Math.round(2 * currentSlide.timeSeconds / 3)) {
164 headerText.className = "ontime";
165 setTimeout(timerFired, timerMSec);
167 else if (secondsDiff >= Math.round(currentSlide.timeSeconds / 3)) {
168 headerText.className = "neartime";
169 setTimeout(timerFired, timerMSec);
172 // We should never come here, but if we do, go into a 100ms loop until we get over the upcoming step.
173 setTimeout(timerFired, 100);
177 // Keyboard/click nav functionality, mostly inherited from FOSDEM 2007.
180 where = where || "next";
181 var navElem = document.getElementById("nav-" + where);
183 window.location.href = navElem.href;
186 function handleClick(e) {
188 var target = (window.event) ? e.srcElement : e.target;
189 if (e.which == 1 && target.nodeName != "A" && target.nodeName != "VIDEO")
193 function handleKeyPress(e) {
196 // See https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode#Constants_for_keyCode_value
199 case "Left": // non-standard, old browsers
200 case "Down": // non-standard, old browsers
204 case "H": //8bitdo Zero "X"
205 case "h": //8bitdo Zero "X"
209 case "Right": // non-standard, old browsers
210 case "Up": // non-standard, old browsers
214 case "J": //8bitdo Zero "B"
215 case "j": //8bitdo Zero "B"
218 case "I": //8bitdo Zero "Y"
219 case "i": //8bitdo Zero "Y"
222 case "G": //8bitdo Zero "A"
223 case "g": //8bitdo Zero "A"
228 window.onclick = handleClick;
229 window.onkeydown = handleKeyPress;