add crash lef cycle brown bag
[slides.git] / fosdem2012 / slides.js
1 /******************************
2  * JavaScript for talk slides *
3  *      by Robert Kaiser      *
4  *      <kairo@kairo.at>      *
5  *     (for FOSDEM 2011)      *
6  ******************************/
7
8 var slides = {};
9 var articleNodes;
10 var currentSlide;
11 var currentIdx;
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 first available
15
16 var pageTitle, headerText, subHeaderText;
17 var navPrev, navNext, navPrevNolink, navNextNolink;
18
19 // Slide timer - color variation of headerText
20 var slideSeconds = 3 * 60;
21
22 // Called when the document has been loaded.
23 function docLoaded() {
24   pageTitle = document.getElementsByTagName("title")[0];
25   headerText = document.getElementById("header-text");
26   subHeaderText = document.getElementById("subheader-text");
27   navPrev = document.getElementById("nav-prev");
28   navNext = document.getElementById("nav-next");
29   navPrevNolink = document.getElementById("nav-prev-nolink");
30   navNextNolink = document.getElementById("nav-next-nolink");
31   articleNodes = document.getElementsByTagName("article");
32
33   if (!firstIdx)
34     firstIdx = 0;
35   if (!lastIdx)
36     lastIdx = articleNodes.length - 1;
37
38   // Get a list of all slides (articles).
39   subHeaderText.textContent = articleNodes.length + " slides...";
40   for (var i = 0; i < articleNodes.length; ++i) {
41     subHeaderText.textContent = "Indexing slide " + i + " / " + articleNodes.length;
42     if (!articleNodes[i].id)
43       articleNodes[i].id = "slide_" + i;
44
45     slides[articleNodes[i].id] =
46        {"idx": i,
47         "name": articleNodes[i].id,
48         "title": articleNodes[i].title ? articleNodes[i].title : articleNodes[i].id,
49         "obj": articleNodes[i]};
50
51     if (location.hash.length &&
52         (location.hash == "#" + articleNodes[i].id || location.hash == "#" + i)) {
53       articleNodes[i].setAttribute("aria-selected", "true");
54       currentSlide = slides[articleNodes[i].id];
55       currentIdx = i;
56     }
57   }
58
59   if (!currentSlide) {
60     currentIdx = defaultIdx;
61     currentSlide = slides[articleNodes[currentIdx].id];
62     currentSlide.obj.setAttribute("aria-selected", "true");
63     location.hash = "#" + currentSlide.name;
64   }
65   updateDisplay();
66 }
67
68 // Called when the hash part of the location changes.
69 function locationHashChanged() {
70   if (location.hash.length > 1) {
71     var hashtag = location.hash.substring(1);
72     // If not a number, treat as ID
73     if (isNaN(hashtag) && slides[hashtag]) {
74       currentSlide.obj.removeAttribute("aria-selected");
75       currentSlide = slides[hashtag];
76       currentIdx = currentSlide.idx;
77       currentSlide.obj.setAttribute("aria-selected", "true");
78       updateDisplay();
79     }
80     else if (articleNodes[hashtag]) {
81       currentSlide.obj.removeAttribute("aria-selected");
82       currentIdx = hashtag;
83       currentSlide = slides[articleNodes[currentIdx].id];
84       currentSlide.obj.setAttribute("aria-selected", "true");
85       updateDisplay();
86     }
87   }
88 }
89 window.onhashchange = locationHashChanged;
90
91 // Update the display after we updated what slide is shown.
92 function updateDisplay() {
93   if (currentIdx >= firstIdx && currentIdx <= lastIdx &&
94       currentSlide.name != "toc")
95     subHeaderText.textContent = (currentIdx - firstIdx + 1) + "/" +
96                                 (lastIdx - firstIdx + 1) + " - " +
97                                 currentSlide.title;
98   else
99     subHeaderText.textContent = currentSlide.title;
100   pageTitle.textContent = headerText.textContent + ": " + currentSlide.title;
101   if (currentIdx > firstIdx && currentSlide.name != "toc") {
102     navPrev.hidden = false;
103     navPrev.href = "#" + articleNodes[currentIdx - 1].id;
104     navPrevNolink.hidden = true;
105   }
106   else {
107     navPrev.hidden = true;
108     navPrevNolink.hidden = false;
109   }
110   if (currentIdx < lastIdx && currentSlide.name != "toc") {
111     navNext.hidden = false;
112     navNext.href = "#" + articleNodes[currentIdx + 1].id;
113     navNextNolink.hidden = true;
114   }
115   else {
116     navNext.hidden = true;
117     navNextNolink.hidden = false;
118   }
119   headerText.className = "";
120   slideStart = new Date();
121   if (currentSlide.name == "toc")
122     createTOC();
123   else
124     setTimeout("timerFired()", timerMSec);
125 }
126
127 // Create TOC list.
128 function createTOC() {
129  var list = document.getElementById("toc-list");
130  if (!list.getElementsByTagName("li").length) {
131    for (var slide in slides) {
132      if (slide != "toc") {
133        var item = document.createElement("li");
134        var link = document.createElement("a");
135        var slideHeaders = slides[slide].obj.getElementsByTagName("h1");
136        if (slideHeaders.length)
137          link.textContent = slideHeaders[0].textContent;
138        else
139          link.textContent = slides[slide].title;
140        link.href = "#" + slides[slide].name;
141        item.appendChild(link);
142        list.appendChild(item);
143      }
144    }
145  }
146 }
147
148 // Do timed color variation on slides.
149 function timerFired() {
150   var slideCurrent = new Date();
151   var secondsDiff = Math.round((slideCurrent.getTime() - slideStart.getTime()) / 1000);
152   if (secondsDiff >= slideSeconds) {
153     headerText.className = "overtime";
154   }
155   else if (secondsDiff >= Math.round(2 * slideSeconds / 3)) {
156     headerText.className = "ontime";
157     setTimeout("timerFired()", timerMSec);
158   }
159   else if (secondsDiff >= Math.round(slideSeconds / 3)) {
160     headerText.className = "neartime";
161     setTimeout("timerFired()", timerMSec);
162   }
163   else {
164     // We should never come here, but if we do, go into a 100ms loop until we get over the upcoming step.
165     setTimeout("timerFired()", 100);
166   }
167 }
168 var slideStart = new Date();
169 var timerMSec = 1000 * (slideSeconds / 3);
170 setTimeout("timerFired()", timerMSec);
171
172 // Keyboard/click nav functionality, mostly inherited from FOSDEM 2007.
173 (function() {
174   function go(where) {
175     where = where || "next";
176     var navElem = document.getElementById("nav-" + where);
177     if (!navElem.hidden)
178       window.location.href = navElem.href;
179   }
180
181   function handleClick(e) {
182     e = e || event;
183     var target = (window.event) ? e.srcElement : e.target;
184     if (e.which == 1 && target.nodeName != "A" && target.nodeName != "VIDEO")
185       go("next");
186   }
187
188   function handleKeyPress(e) {
189     e = e || event;
190     switch (e.keyCode) {
191       case e.DOM_VK_LEFT:
192         go("prev"); break;
193       case e.DOM_VK_RIGHT:
194         go("next"); break;
195     }
196   }
197
198   window.onclick = handleClick;
199   window.onkeypress = handleKeyPress;
200 })();