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