Commit | Line | Data |
720accfe |
1 | // S5 v1.1 slides.js -- released under CC by-sa 2.0 license |
2 | // |
3 | // Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information |
4 | // about all the wonderful and talented contributors to this code! |
5 | |
6 | var undef; |
7 | var snum = 0; |
8 | var smax = 1; |
9 | var incpos = 0; |
10 | var number = undef; |
11 | var s5mode = true; |
12 | var slideCSS = document.getElementById('slideProj').href; |
13 | var defaultView = 'slideshow'; |
14 | var controlVis = 'visible'; |
15 | |
16 | var isIE = navigator.appName == 'Microsoft Internet Explorer' ? 1 : 0; |
17 | var isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0; |
18 | var isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0; |
19 | |
20 | function hasClass(object, className) { |
21 | if (!object.className) return false; |
22 | return (object.className.search('(^|\\s)' + className + '(\\s|$)') != -1); |
23 | } |
24 | |
25 | function hasValue(object, value) { |
26 | if (!object) return false; |
27 | return (object.search('(^|\\s)' + value + '(\\s|$)') != -1); |
28 | } |
29 | |
30 | function removeClass(object,className) { |
31 | if (!object) return; |
32 | object.className = object.className.replace(new RegExp('(^|\\s)'+className+'(\\s|$)'), RegExp.$1+RegExp.$2); |
33 | } |
34 | |
35 | function addClass(object,className) { |
36 | if (!object || hasClass(object, className)) return; |
37 | if (object.className) { |
38 | object.className += ' '+className; |
39 | } else { |
40 | object.className = className; |
41 | } |
42 | } |
43 | |
44 | function GetElementsWithClassName(elementName,className) { |
45 | var allElements = document.getElementsByTagName(elementName); |
46 | var elemColl = new Array(); |
47 | for (var i = 0; i< allElements.length; i++) { |
48 | if (hasClass(allElements[i], className)) { |
49 | elemColl[elemColl.length] = allElements[i]; |
50 | } |
51 | } |
52 | return elemColl; |
53 | } |
54 | |
55 | function isParentOrSelf(element, id) { |
56 | if (element == null || element.nodeName=='BODY') return false; |
57 | else if (element.id == id) return true; |
58 | else return isParentOrSelf(element.parentNode, id); |
59 | } |
60 | |
61 | function nodeValue(node) { |
62 | var result = ""; |
63 | if (node.nodeType == 1) { |
64 | var children = node.childNodes; |
65 | for (var i = 0; i < children.length; ++i) { |
66 | result += nodeValue(children[i]); |
67 | } |
68 | } |
69 | else if (node.nodeType == 3) { |
70 | result = node.nodeValue; |
71 | } |
72 | return(result); |
73 | } |
74 | |
75 | function slideLabel() { |
76 | var slideColl = GetElementsWithClassName('*','slide'); |
77 | var list = document.getElementById('jumplist'); |
78 | smax = slideColl.length; |
79 | for (var n = 0; n < smax; n++) { |
80 | var obj = slideColl[n]; |
81 | |
82 | var did = 'slide' + n.toString(); |
83 | obj.setAttribute('id',did); |
84 | if (isOp) continue; |
85 | |
86 | var otext = ''; |
87 | var menu = obj.firstChild; |
88 | if (!menu) continue; // to cope with empty slides |
89 | while (menu && menu.nodeType == 3) { |
90 | menu = menu.nextSibling; |
91 | } |
92 | if (!menu) continue; // to cope with slides with only text nodes |
93 | |
94 | var menunodes = menu.childNodes; |
95 | for (var o = 0; o < menunodes.length; o++) { |
96 | otext += nodeValue(menunodes[o]); |
97 | } |
98 | list.options[list.length] = new Option(n + ' : ' + otext, n); |
99 | } |
100 | } |
101 | |
102 | function currentSlide() { |
103 | var cs; |
104 | if (document.getElementById) { |
105 | cs = document.getElementById('currentSlide'); |
106 | } else { |
107 | cs = document.currentSlide; |
108 | } |
109 | cs.innerHTML = '<span id="csHere">' + snum + '<\/span> ' + |
110 | '<span id="csSep">\/<\/span> ' + |
111 | '<span id="csTotal">' + (smax-1) + '<\/span>'; |
112 | if (snum == 0) { |
113 | cs.style.visibility = 'hidden'; |
114 | } else { |
115 | cs.style.visibility = 'visible'; |
116 | } |
117 | } |
118 | |
119 | function go(step) { |
120 | if (document.getElementById('slideProj').disabled || step == 0) return; |
121 | var jl = document.getElementById('jumplist'); |
122 | var cid = 'slide' + snum; |
123 | var ce = document.getElementById(cid); |
124 | if (incrementals[snum].length > 0) { |
125 | for (var i = 0; i < incrementals[snum].length; i++) { |
126 | removeClass(incrementals[snum][i], 'current'); |
127 | removeClass(incrementals[snum][i], 'incremental'); |
128 | } |
129 | } |
130 | if (step != 'j') { |
131 | snum += step; |
132 | lmax = smax - 1; |
133 | if (snum > lmax) snum = lmax; |
134 | if (snum < 0) snum = 0; |
135 | } else |
136 | snum = parseInt(jl.value); |
137 | var nid = 'slide' + snum; |
138 | var ne = document.getElementById(nid); |
139 | if (!ne) { |
140 | ne = document.getElementById('slide0'); |
141 | snum = 0; |
142 | } |
143 | if (step < 0) {incpos = incrementals[snum].length} else {incpos = 0;} |
144 | if (incrementals[snum].length > 0 && incpos == 0) { |
145 | for (var i = 0; i < incrementals[snum].length; i++) { |
146 | if (hasClass(incrementals[snum][i], 'current')) |
147 | incpos = i + 1; |
148 | else |
149 | addClass(incrementals[snum][i], 'incremental'); |
150 | } |
151 | } |
152 | if (incrementals[snum].length > 0 && incpos > 0) |
153 | addClass(incrementals[snum][incpos - 1], 'current'); |
154 | ce.style.visibility = 'hidden'; |
155 | ne.style.visibility = 'visible'; |
156 | jl.selectedIndex = snum; |
157 | currentSlide(); |
158 | number = 0; |
159 | } |
160 | |
161 | function goTo(target) { |
162 | if (target >= smax || target == snum) return; |
163 | go(target - snum); |
164 | } |
165 | |
166 | function subgo(step) { |
167 | if (step > 0) { |
168 | removeClass(incrementals[snum][incpos - 1],'current'); |
169 | removeClass(incrementals[snum][incpos], 'incremental'); |
170 | addClass(incrementals[snum][incpos],'current'); |
171 | incpos++; |
172 | } else { |
173 | incpos--; |
174 | removeClass(incrementals[snum][incpos],'current'); |
175 | addClass(incrementals[snum][incpos], 'incremental'); |
176 | addClass(incrementals[snum][incpos - 1],'current'); |
177 | } |
178 | } |
179 | |
180 | function toggle() { |
181 | var slideColl = GetElementsWithClassName('div','slide'); |
182 | var slides = document.getElementById('slideProj'); |
183 | var outline = document.getElementById('outlineStyle'); |
184 | if (!slides.disabled) { |
185 | slides.disabled = true; |
186 | outline.disabled = false; |
187 | s5mode = false; |
188 | fontSize('1em'); |
189 | for (var n = 0; n < smax; n++) { |
190 | var slide = slideColl[n]; |
191 | slide.style.visibility = 'visible'; |
192 | } |
193 | } else { |
194 | slides.disabled = false; |
195 | outline.disabled = true; |
196 | s5mode = true; |
197 | fontScale(); |
198 | for (var n = 0; n < smax; n++) { |
199 | var slide = slideColl[n]; |
200 | slide.style.visibility = 'hidden'; |
201 | } |
202 | slideColl[snum].style.visibility = 'visible'; |
203 | } |
204 | } |
205 | |
206 | function showHide(action) { |
207 | var obj = GetElementsWithClassName('*','hideme')[0]; |
208 | switch (action) { |
209 | case 's': obj.style.visibility = 'visible'; break; |
210 | case 'h': obj.style.visibility = 'hidden'; break; |
211 | case 'k': |
212 | if (obj.style.visibility != 'visible') { |
213 | obj.style.visibility = 'visible'; |
214 | } else { |
215 | obj.style.visibility = 'hidden'; |
216 | } |
217 | break; |
218 | } |
219 | } |
220 | |
221 | // 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/) |
222 | function keys(key) { |
223 | if (!key) { |
224 | key = event; |
225 | key.which = key.keyCode; |
226 | } |
227 | if (key.which == 84) { |
228 | toggle(); |
229 | return; |
230 | } |
231 | if (s5mode) { |
232 | switch (key.which) { |
233 | case 10: // return |
234 | case 13: // enter |
235 | if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; |
236 | if (key.target && isParentOrSelf(key.target, 'controls')) return; |
237 | if(number != undef) { |
238 | goTo(number); |
239 | break; |
240 | } |
241 | case 32: // spacebar |
242 | case 34: // page down |
243 | case 39: // rightkey |
244 | case 40: // downkey |
245 | if(number != undef) { |
246 | go(number); |
247 | } else if (!incrementals[snum] || incpos >= incrementals[snum].length) { |
248 | go(1); |
249 | } else { |
250 | subgo(1); |
251 | } |
252 | break; |
253 | case 33: // page up |
254 | case 37: // leftkey |
255 | case 38: // upkey |
256 | if(number != undef) { |
257 | go(-1 * number); |
258 | } else if (!incrementals[snum] || incpos <= 0) { |
259 | go(-1); |
260 | } else { |
261 | subgo(-1); |
262 | } |
263 | break; |
264 | case 67: // c |
265 | showHide('k'); |
266 | break; |
267 | } |
268 | if (key.which < 48 || key.which > 57) { |
269 | number = undef; |
270 | } else { |
271 | if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; |
272 | if (key.target && isParentOrSelf(key.target, 'controls')) return; |
273 | number = (((number != undef) ? number : 0) * 10) + (key.which - 48); |
274 | } |
275 | } |
276 | } |
277 | |
278 | function clicker(e) { |
279 | number = undef; |
280 | var target; |
281 | if (window.event) { |
282 | target = window.event.srcElement; |
283 | e = window.event; |
284 | } else target = e.target; |
285 | if (target.getAttribute('href') != null || hasValue(target.rel, 'external') || isParentOrSelf(target, 'controls') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object')) return true; |
286 | if (!e.which || e.which == 1) { |
287 | if (!incrementals[snum] || incpos >= incrementals[snum].length) { |
288 | go(1); |
289 | } else { |
290 | subgo(1); |
291 | } |
292 | } |
293 | } |
294 | |
295 | function findSlide(hash) { |
296 | var target = null; |
297 | var slides = GetElementsWithClassName('*','slide'); |
298 | for (var i = 0; i < slides.length; i++) { |
299 | var targetSlide = slides[i]; |
300 | if ( (targetSlide.name && targetSlide.name == hash) |
301 | || (targetSlide.id && targetSlide.id == hash) ) { |
302 | target = targetSlide; |
303 | break; |
304 | } |
305 | } |
306 | while(target != null && target.nodeName != 'BODY') { |
307 | if (hasClass(target, 'slide')) { |
308 | return parseInt(target.id.slice(5)); |
309 | } |
310 | target = target.parentNode; |
311 | } |
312 | return null; |
313 | } |
314 | |
315 | function slideJump() { |
316 | if (window.location.hash == null) return; |
317 | var sregex = /^#slide(\d+)$/; |
318 | var matches = sregex.exec(window.location.hash); |
319 | var dest = null; |
320 | if (matches != null) { |
321 | dest = parseInt(matches[1]); |
322 | } else { |
323 | dest = findSlide(window.location.hash.slice(1)); |
324 | } |
325 | if (dest != null) |
326 | go(dest - snum); |
327 | } |
328 | |
329 | function fixLinks() { |
330 | var thisUri = window.location.href; |
331 | thisUri = thisUri.slice(0, thisUri.length - window.location.hash.length); |
332 | var aelements = document.getElementsByTagName('A'); |
333 | for (var i = 0; i < aelements.length; i++) { |
334 | var a = aelements[i].href; |
335 | var slideID = a.match('\#slide[0-9]{1,2}'); |
336 | if ((slideID) && (slideID[0].slice(0,1) == '#')) { |
337 | var dest = findSlide(slideID[0].slice(1)); |
338 | if (dest != null) { |
339 | if (aelements[i].addEventListener) { |
340 | aelements[i].addEventListener("click", new Function("e", |
341 | "if (document.getElementById('slideProj').disabled) return;" + |
342 | "go("+dest+" - snum); " + |
343 | "if (e.preventDefault) e.preventDefault();"), true); |
344 | } else if (aelements[i].attachEvent) { |
345 | aelements[i].attachEvent("onclick", new Function("", |
346 | "if (document.getElementById('slideProj').disabled) return;" + |
347 | "go("+dest+" - snum); " + |
348 | "event.returnValue = false;")); |
349 | } |
350 | } |
351 | } |
352 | } |
353 | } |
354 | |
355 | function externalLinks() { |
356 | if (!document.getElementsByTagName) return; |
357 | var anchors = document.getElementsByTagName('a'); |
358 | for (var i=0; i<anchors.length; i++) { |
359 | var anchor = anchors[i]; |
360 | if (anchor.getAttribute('href') && hasValue(anchor.rel, 'external')) { |
361 | anchor.target = '_blank'; |
362 | addClass(anchor,'external'); |
363 | } |
364 | } |
365 | } |
366 | |
367 | function createControls() { |
368 | var controlsDiv = document.getElementById("controls"); |
369 | if (!controlsDiv) return; |
370 | var hider = ' onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"'; |
371 | var hideDiv, hideList = ''; |
372 | if (controlVis == 'hidden') { |
373 | hideDiv = hider; |
374 | } else { |
375 | hideList = hider; |
376 | } |
377 | controlsDiv.innerHTML = '<form action="#" id="controlForm"' + hideDiv + '>' + |
378 | '<div id="navLinks">' + |
379 | '<a accesskey="t" id="toggle" href="javascript:toggle();">Ø<\/a>' + |
380 | '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' + |
381 | '<a accesskey="x" id="next" href="javascript:go(1);">»<\/a>' + |
382 | '<div id="navList"' + hideList + '><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>' + |
383 | '<\/div><\/form>'; |
384 | if (controlVis == 'hidden') { |
385 | var hidden = document.getElementById('navLinks'); |
386 | } else { |
387 | var hidden = document.getElementById('jumplist'); |
388 | } |
389 | addClass(hidden,'hideme'); |
390 | } |
391 | |
392 | function fontScale() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers |
393 | if (!s5mode) return false; |
394 | var vScale = 22; // both yield 32 (after rounding) at 1024x768 |
395 | var hScale = 32; // perhaps should auto-calculate based on theme's declared value? |
396 | if (window.innerHeight) { |
397 | var vSize = window.innerHeight; |
398 | var hSize = window.innerWidth; |
399 | } else if (document.documentElement.clientHeight) { |
400 | var vSize = document.documentElement.clientHeight; |
401 | var hSize = document.documentElement.clientWidth; |
402 | } else if (document.body.clientHeight) { |
403 | var vSize = document.body.clientHeight; |
404 | var hSize = document.body.clientWidth; |
405 | } else { |
406 | var vSize = 700; // assuming 1024x768, minus chrome and such |
407 | var hSize = 1024; // these do not account for kiosk mode or Opera Show |
408 | } |
409 | var newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale)); |
410 | fontSize(newSize + 'px'); |
411 | if (isGe) { // hack to counter incremental reflow bugs |
412 | var obj = document.getElementsByTagName('body')[0]; |
413 | obj.style.display = 'none'; |
414 | obj.style.display = 'block'; |
415 | } |
416 | } |
417 | |
418 | function fontSize(value) { |
419 | if (!(s5ss = document.getElementById('s5ss'))) { |
420 | if (!isIE) { |
421 | document.getElementsByTagName('head')[0].appendChild(s5ss = document.createElement('style')); |
422 | s5ss.setAttribute('media','screen, projection'); |
423 | s5ss.setAttribute('id','s5ss'); |
424 | } else { |
425 | document.createStyleSheet(); |
426 | document.s5ss = document.styleSheets[document.styleSheets.length - 1]; |
427 | } |
428 | } |
429 | if (!isIE) { |
430 | while (s5ss.lastChild) s5ss.removeChild(s5ss.lastChild); |
431 | s5ss.appendChild(document.createTextNode('body {font-size: ' + value + ' !important;}')); |
432 | } else { |
433 | document.s5ss.addRule('body','font-size: ' + value + ' !important;'); |
434 | } |
435 | } |
436 | |
437 | function notOperaFix() { |
438 | var slides = document.getElementById('slideProj'); |
439 | var outline = document.getElementById('outlineStyle'); |
440 | slides.setAttribute('media','screen'); |
441 | outline.disabled = true; |
442 | if (isGe) { |
443 | slides.setAttribute('href','null'); // Gecko fix |
444 | slides.setAttribute('href',slideCSS); // Gecko fix |
445 | } |
446 | } |
447 | |
448 | function getIncrementals(obj) { |
449 | var incrementals = new Array(); |
450 | if (!obj) |
451 | return incrementals; |
452 | var children = obj.childNodes; |
453 | for (var i = 0; i < children.length; i++) { |
454 | var child = children[i]; |
455 | if (hasClass(child, 'incremental')) { |
456 | if (child.nodeName == 'OL' || child.nodeName == 'UL') { |
457 | removeClass(child, 'incremental'); |
458 | for (var j = 0; j < child.childNodes.length; j++) { |
459 | if (child.childNodes[j].nodeType == 1) { |
460 | addClass(child.childNodes[j], 'incremental'); |
461 | } |
462 | } |
463 | } else { |
464 | incrementals[incrementals.length] = child; |
465 | removeClass(child,'incremental'); |
466 | } |
467 | } |
468 | if (hasClass(child, 'show-first')) { |
469 | if (child.nodeName == 'OL' || child.nodeName == 'UL') { |
470 | removeClass(child, 'show-first'); |
471 | if (child.childNodes[isGe].nodeType == 1) { |
472 | removeClass(child.childNodes[isGe], 'incremental'); |
473 | } |
474 | } else { |
475 | incrementals[incrementals.length] = child; |
476 | } |
477 | } |
478 | incrementals = incrementals.concat(getIncrementals(child)); |
479 | } |
480 | return incrementals; |
481 | } |
482 | |
483 | function createIncrementals() { |
484 | var incrementals = new Array(); |
485 | for (var i = 0; i < smax; i++) { |
486 | incrementals[i] = getIncrementals(document.getElementById('slide'+i)); |
487 | } |
488 | return incrementals; |
489 | } |
490 | |
491 | function defaultCheck() { |
492 | var allMetas = document.getElementsByTagName('meta'); |
493 | for (var i = 0; i< allMetas.length; i++) { |
494 | if (allMetas[i].name == 'defaultView') { |
495 | defaultView = allMetas[i].content; |
496 | } |
497 | if (allMetas[i].name == 'controlVis') { |
498 | controlVis = allMetas[i].content; |
499 | } |
500 | } |
501 | } |
502 | |
503 | // Key trap fix, new function body for trap() |
504 | function trap(e) { |
505 | if (!e) { |
506 | e = event; |
507 | e.which = e.keyCode; |
508 | } |
509 | try { |
510 | modifierKey = e.ctrlKey || e.altKey || e.metaKey; |
511 | } |
512 | catch(e) { |
513 | modifierKey = false; |
514 | } |
515 | return modifierKey || e.which == 0; |
516 | } |
517 | |
518 | function startup() { |
519 | defaultCheck(); |
520 | if (!isOp) createControls(); |
521 | slideLabel(); |
522 | fixLinks(); |
523 | externalLinks(); |
524 | fontScale(); |
525 | if (!isOp) { |
526 | notOperaFix(); |
527 | incrementals = createIncrementals(); |
528 | slideJump(); |
529 | if (defaultView == 'outline') { |
530 | toggle(); |
531 | } |
532 | document.onkeyup = keys; |
533 | document.onkeypress = trap; |
534 | document.onclick = clicker; |
535 | } |
536 | } |
537 | |
538 | |
539 | //IE/Win PNG transparency hack -- ONLY WORKS FOR FOREGROUND IMAGES! |
540 | /*@cc_on |
541 | @if (@_win16 != @_win16) |
542 | @set @_win16 = false |
543 | @end |
544 | @if (@_win32 != @_win32) |
545 | @set @_win32 = false |
546 | @end |
547 | @if (@_jscript_version >= 5.5 && (@_win32 || @_win16)) |
548 | window.attachEvent( |
549 | 'onload', function() { |
550 | for (var i = 0; i < document.images.length; i++) { |
551 | var img = document.images[i]; |
552 | var len = img.src.length; |
553 | if ('.PNG' == img.src.substring(len - 4, len).toUpperCase()) { |
554 | var span = { |
555 | id: img.id |
556 | ,className: img.className |
557 | ,title: (img.title) ? img.title : img.alt |
558 | ,style: 'display:inline-block;width:' |
559 | + img.width + 'px;height:' + img.height + 'px;' |
560 | + 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' |
561 | + img.src + '\',sizingMethod=\'scale\');' |
562 | ,toString: function() { |
563 | return '<span ' |
564 | + ((this.id) ? 'id="' + this.id + '" ' : '') |
565 | + ((this.className) ? 'class="' + this.className + '" ' : '') |
566 | + 'title="' + this.title + '" ' |
567 | + 'style="' + this.style + '"><\/span>'; |
568 | } |
569 | } |
570 | if ('left' == img.align) |
571 | span.style += 'float:left;'; |
572 | if ('right' == img.align) |
573 | span.style += 'float:right;'; |
574 | if (img.parentElement.href) |
575 | span.style += 'cursor:hand;'; |
576 | if (0 != img.style.cssText.length) |
577 | span.style = img.currentStyle + ';' + span.style; |
578 | img.outerHTML = span + ''; |
579 | i--; |
580 | } |
581 | } |
582 | } |
583 | ); |
584 | @end @*/ |
585 | |
586 | window.onload = startup; |
587 | window.onresize = function(){setTimeout('fontScale()', 50);} |