13
|
1 /* slidy.js
|
|
2
|
|
3 Copyright (c) 2005-2009 W3C (MIT, ERCIM, Keio), All Rights Reserved.
|
|
4 W3C liability, trademark, document use and software licensing
|
|
5 rules apply, see:
|
|
6
|
|
7 http://www.w3.org/Consortium/Legal/copyright-documents
|
|
8 http://www.w3.org/Consortium/Legal/copyright-software
|
|
9 */
|
|
10
|
|
11 var ns_pos = (typeof window.pageYOffset!='undefined');
|
|
12 var khtml = ((navigator.userAgent).indexOf("KHTML") >= 0 ? true : false);
|
|
13 var opera = ((navigator.userAgent).indexOf("Opera") >= 0 ? true : false);
|
|
14 var ie = (typeof document.all != "undefined" && !opera);
|
|
15 var ie7 = (!ns_pos && navigator.userAgent.indexOf("MSIE 7") != -1);
|
|
16 var ie8 = (!ns_pos && navigator.userAgent.indexOf("MSIE 8") != -1);
|
|
17 var slidy_started = false;
|
|
18
|
|
19 // added by kent.
|
|
20 var showspeak = false;
|
|
21
|
|
22 if (ie && !ie8)
|
|
23 document.write("<iframe id='historyFrame' src='javascript:\"<html"+"></"+"html>\"' height='1' width='1' style='position:absolute;left:-800px'></iframe>");
|
|
24
|
|
25 // IE only event handlers to ensure all slides are printed
|
|
26 // I don't yet know how to emulate these for other browsers
|
|
27 if (typeof beforePrint != 'undefined')
|
|
28 {
|
|
29 window.onbeforeprint = beforePrint;
|
|
30 window.onafterprint = afterPrint;
|
|
31 }
|
|
32
|
|
33 // to avoid a clash with other scripts or onload attribute on <body>
|
|
34 // we use something smarter than window.onload
|
|
35 //window.onload = startup;
|
|
36
|
|
37
|
|
38 if (ie)
|
|
39 setTimeout(ieSlidyInit, 100);
|
|
40 else if (document.addEventListener)
|
|
41 document.addEventListener("DOMContentLoaded", startup, false);
|
|
42
|
|
43 function ieSlidyInit()
|
|
44 {
|
|
45 if (//document.readyState == "interactive" ||
|
|
46 document.readyState == "complete" ||
|
|
47 document.readyState == "loaded")
|
|
48 {
|
|
49 startup();
|
|
50 }
|
|
51 else
|
|
52 {
|
|
53 setTimeout(ieSlidyInit, 100);
|
|
54 }
|
|
55 }
|
|
56
|
|
57 setTimeout(hideSlides, 50);
|
|
58
|
|
59 function hideSlides()
|
|
60 {
|
|
61 if (document.body)
|
|
62 document.body.style.visibility = "hidden";
|
|
63 else
|
|
64 setTimeout(hideSlides, 50);
|
|
65 }
|
|
66
|
|
67 var slidenum = 0; // integer slide count: 0, 1, 2, ...
|
|
68 var slides; // set to array of slide div's
|
|
69 var slideNumElement; // element containing slide number
|
|
70 var notes; // set to array of handout div's
|
|
71 var backgrounds; // set to array of background div's
|
|
72 var toolbar; // element containing toolbar
|
|
73 var title; // document title
|
|
74 var lastShown = null; // last incrementally shown item
|
|
75 var eos = null; // span element for end of slide indicator
|
|
76 var toc = null; // table of contents
|
|
77 var outline = null; // outline element with the focus
|
|
78 var selectedTextLen; // length of drag selection on document
|
|
79
|
|
80 var viewAll = 0; // 1 to view all slides + handouts
|
|
81 var wantToolbar = 1; // 0 if toolbar isn't wanted
|
|
82 var mouseClickEnabled = true; // enables left click for next slide
|
|
83 var scrollhack = 0; // IE work around for position: fixed
|
|
84
|
|
85 var helpAnchor; // used for keyboard focus hack in showToolbar()
|
|
86 var helpPage = "http://www.w3.org/Talks/Tools/Slidy/help.html";
|
|
87 var helpText = "Navigate with mouse click, space bar, Cursor Left/Right, " +
|
|
88 "or Pg Up and Pg Dn. Use S and B to change font size.";
|
|
89
|
|
90 var sizeIndex = 0;
|
|
91 var sizeAdjustment = 0;
|
|
92 var sizes = new Array("10pt", "12pt", "14pt", "16pt", "18pt", "20pt",
|
|
93 "22pt", "24pt", "26pt", "28pt", "30pt", "32pt");
|
|
94 var okayForIncremental = incrementalElementList();
|
|
95
|
|
96 // needed for efficient resizing
|
|
97 var lastWidth = 0;
|
|
98 var lastHeight = 0;
|
|
99
|
|
100 // Needed for cross browser support for relative width/height on
|
|
101 // object elements. The work around is to save width/height attributes
|
|
102 // and then to recompute absolute width/height dimensions on resizing
|
|
103 var objects;
|
|
104
|
|
105 // updated to language specified by html file
|
|
106 var lang = "en";
|
|
107
|
|
108 //var localize = {};
|
|
109
|
|
110 // for each language there is an associative array
|
|
111 var strings_es = {
|
|
112 "slide":"pág.",
|
|
113 "help?":"Ayuda",
|
|
114 "contents?":"Índice",
|
|
115 "table of contents":"tabla de contenidos",
|
|
116 "Table of Contents":"Tabla de Contenidos",
|
|
117 "restart presentation":"Reiniciar presentación",
|
|
118 "restart?":"Inicio"
|
|
119 };
|
|
120
|
|
121 strings_es[helpText] =
|
|
122 "Utilice el ratón, barra espaciadora, teclas Izda/Dcha, " +
|
|
123 "o Re pág y Av pág. Use S y B para cambiar el tamaño de fuente.";
|
|
124
|
|
125 var strings_ca = {
|
|
126 "slide":"pàg..",
|
|
127 "help?":"Ajuda",
|
|
128 "contents?":"Índex",
|
|
129 "table of contents":"taula de continguts",
|
|
130 "Table of Contents":"Taula de Continguts",
|
|
131 "restart presentation":"Reiniciar presentació",
|
|
132 "restart?":"Inici"
|
|
133 };
|
|
134
|
|
135 strings_ca[helpText] =
|
|
136 "Utilitzi el ratolí, barra espaiadora, tecles Esq./Dta. " +
|
|
137 "o Re pàg y Av pàg. Usi S i B per canviar grandària de font.";
|
|
138
|
|
139 var strings_nl = {
|
|
140 "slide":"pagina",
|
|
141 "help?":"Help?",
|
|
142 "contents?":"Inhoud?",
|
|
143 "table of contents":"inhoudsopgave",
|
|
144 "Table of Contents":"Inhoudsopgave",
|
|
145 "restart presentation":"herstart presentatie",
|
|
146 "restart?":"Herstart?"
|
|
147 };
|
|
148
|
|
149 strings_nl[helpText] =
|
|
150 "Navigeer d.m.v. het muis, spatiebar, Links/Rechts toetsen, " +
|
|
151 "of PgUp en PgDn. Gebruik S en B om de karaktergrootte te veranderen.";
|
|
152
|
|
153 var strings_de = {
|
|
154 "slide":"Seite",
|
|
155 "help?":"Hilfe",
|
|
156 "contents?":"Übersicht",
|
|
157 "table of contents":"Inhaltsverzeichnis",
|
|
158 "Table of Contents":"Inhaltsverzeichnis",
|
|
159 "restart presentation":"Präsentation neu starten",
|
|
160 "restart?":"Neustart"
|
|
161 };
|
|
162
|
|
163 strings_de[helpText] =
|
|
164 "Benutzen Sie die Maus, Leerschlag, die Cursortasten links/rechts oder " +
|
|
165 "Page up/Page Down zum Wechseln der Seiten und S und B für die Schriftgrösse.";
|
|
166
|
|
167 var strings_pl = {
|
|
168 "slide":"slajd",
|
|
169 "help?":"pomoc?",
|
|
170 "contents?":"spis treści?",
|
|
171 "table of contents":"spis treści",
|
|
172 "Table of Contents":"Spis Treści",
|
|
173 "restart presentation":"Restartuj prezentację",
|
|
174 "restart?":"restart?"
|
|
175 };
|
|
176
|
|
177 strings_pl[helpText] =
|
|
178 "Zmieniaj slajdy klikając myszą, naciskając spację, strzałki lewo/prawo" +
|
|
179 "lub PgUp / PgDn. Użyj klawiszy S i B, aby zmienić rozmiar czczionki.";
|
|
180
|
|
181 var strings_fr = {
|
|
182 "slide":"page",
|
|
183 "help?":"Aide",
|
|
184 "contents?":"Index",
|
|
185 "table of contents":"table des matières",
|
|
186 "Table of Contents":"Table des matières",
|
|
187 "restart presentation":"Recommencer l'exposé",
|
|
188 "restart?":"Début"
|
|
189 };
|
|
190
|
|
191 strings_fr[helpText] =
|
|
192 "Naviguez avec la souris, la barre d'espace, les flèches " +
|
|
193 "gauche/droite ou les touches Pg Up, Pg Dn. Utilisez " +
|
|
194 "les touches S et B pour modifier la taille de la police.";
|
|
195
|
|
196 var strings_hu = {
|
|
197 "slide":"oldal",
|
|
198 "help?":"segítség",
|
|
199 "contents?":"tartalom",
|
|
200 "table of contents":"tartalomjegyzék",
|
|
201 "Table of Contents":"Tartalomjegyzék",
|
|
202 "restart presentation":"bemutató újraindítása",
|
|
203 "restart?":"újraindítás"
|
|
204 };
|
|
205
|
|
206 strings_hu[helpText] =
|
|
207 "Az oldalak közti lépkedéshez kattintson az egérrel, vagy " +
|
|
208 "használja a szóköz, a bal, vagy a jobb nyíl, illetve a Page Down, " +
|
|
209 "Page Up billentyűket. Az S és a B billentyűkkel változtathatja " +
|
|
210 "a szöveg méretét.";
|
|
211
|
|
212 var strings_it = {
|
|
213 "slide":"pag.",
|
|
214 "help?":"Aiuto",
|
|
215 "contents?":"Indice",
|
|
216 "table of contents":"indice",
|
|
217 "Table of Contents":"Indice",
|
|
218 "restart presentation":"Ricominciare la presentazione",
|
|
219 "restart?":"Inizio"
|
|
220 };
|
|
221
|
|
222 strings_it[helpText] =
|
|
223 "Navigare con mouse, barra spazio, frecce sinistra/destra o " +
|
|
224 "PgUp e PgDn. Usare S e B per cambiare la dimensione dei caratteri.";
|
|
225
|
|
226 var strings_el = {
|
|
227 "slide":"σελίδα",
|
|
228 "help?":"βοήθεια;",
|
|
229 "contents?":"περιεχόμενα;",
|
|
230 "table of contents":"πίνακας περιεχομένων",
|
|
231 "Table of Contents":"Πίνακας Περιεχομένων",
|
|
232 "restart presentation":"επανεκκίνηση παρουσίασης",
|
|
233 "restart?":"επανεκκίνηση;"
|
|
234 };
|
|
235
|
|
236 strings_el[helpText] =
|
|
237 "Πλοηγηθείτε με το κλίκ του ποντικιού, το space, τα βέλη αριστερά/δεξιά, " +
|
|
238 "ή Page Up και Page Down. Χρησιμοποιήστε τα πλήκτρα S και B για να αλλάξετε " +
|
|
239 "το μέγεθος της γραμματοσειράς.";
|
|
240
|
|
241 var strings_ja = {
|
|
242 "slide":"スライド",
|
|
243 "help?":"ヘルプ",
|
|
244 "contents?":"目次",
|
|
245 "table of contents":"目次を表示",
|
|
246 "Table of Contents":"目次",
|
|
247 "restart presentation":"最初から再生",
|
|
248 "restart?":"最初から"
|
|
249 };
|
|
250
|
|
251 strings_ja[helpText] =
|
|
252 "マウス左クリック ・ スペース ・ 左右キー " +
|
|
253 "または Page Up ・ Page Downで操作, S ・ Bでフォントサイズ変更";
|
|
254
|
|
255 var strings_zh = {
|
|
256 "slide":"幻灯片",
|
|
257 "help?":"帮助?",
|
|
258 "contents?":"内容?",
|
|
259 "table of contents":"目录",
|
|
260 "Table of Contents":"目录",
|
|
261 "restart presentation":"重新启动展示",
|
|
262 "restart?":"重新启动?"
|
|
263 };
|
|
264
|
|
265 strings_zh[helpText] =
|
|
266 "用鼠标点击, 空格条, 左右箭头, Pg Up 和 Pg Dn 导航. " +
|
|
267 "用 S, B 改变字体大小.";
|
|
268
|
|
269 var strings_ru = {
|
|
270 "slide":"слайд",
|
|
271 "help?":"помощь?",
|
|
272 "contents?":"содержание?",
|
|
273 "table of contents":"оглавление",
|
|
274 "Table of Contents":"Оглавление",
|
|
275 "restart presentation":"перезапустить презентацию",
|
|
276 "restart?":"перезапуск?"
|
|
277 };
|
|
278
|
|
279 strings_ru[helpText] =
|
|
280 "Перемещайтесь кликая мышкой, используя клавишу пробел, стрелки" +
|
|
281 "влево/вправо или Pg Up и Pg Dn. Клавиши S и B меняют размер шрифта.";
|
|
282
|
|
283
|
|
284 // each such language array is declared in the localize array
|
|
285 // used indirectly as in help.innerHTML = "help".localize();
|
|
286 var localize = {
|
|
287 "es":strings_es,
|
|
288 "ca":strings_ca,
|
|
289 "nl":strings_nl,
|
|
290 "de":strings_de,
|
|
291 "pl":strings_pl,
|
|
292 "fr":strings_fr,
|
|
293 "hu":strings_hu,
|
|
294 "it":strings_it,
|
|
295 "el":strings_el,
|
|
296 "jp":strings_ja,
|
|
297 "zh":strings_zh,
|
|
298 "ru":strings_ru
|
|
299 };
|
|
300
|
|
301 /* general initialization */
|
|
302 function startup()
|
|
303 {
|
|
304 if (slidy_started)
|
|
305 {
|
|
306 alert("already started");
|
|
307 return;
|
|
308 }
|
|
309 slidy_started = true;
|
|
310
|
|
311 // find human language from html element
|
|
312 // for use in localizing strings
|
|
313 lang = document.body.parentNode.getAttribute("lang");
|
|
314
|
|
315 if (!lang)
|
|
316 lang = document.body.parentNode.getAttribute("xml:lang");
|
|
317
|
|
318 if (!lang)
|
|
319 lang = "en";
|
|
320
|
|
321 document.body.style.visibility = "visible";
|
|
322 title = document.title;
|
|
323 toolbar = addToolbar();
|
|
324 wrapImplicitSlides();
|
|
325 slides = collectSlides();
|
|
326 notes = collectNotes();
|
|
327 objects = document.body.getElementsByTagName("object");
|
|
328 backgrounds = collectBackgrounds();
|
|
329 patchAnchors();
|
|
330
|
|
331 slidenum = findSlideNumber(location.href);
|
|
332 window.offscreenbuffering = true;
|
|
333 sizeAdjustment = findSizeAdjust();
|
|
334 hideImageToolbar(); // suppress IE image toolbar popup
|
|
335 initOutliner(); // activate fold/unfold support
|
|
336
|
|
337 if (slides.length > 0)
|
|
338 {
|
|
339 var slide = slides[slidenum];
|
|
340 slide.style.position = "absolute";
|
|
341
|
|
342 if (slidenum > 0)
|
|
343 {
|
|
344 setVisibilityAllIncremental("visible");
|
|
345 lastShown = previousIncrementalItem(null);
|
|
346 setEosStatus(true);
|
|
347 }
|
|
348 else
|
|
349 {
|
|
350 lastShown = null;
|
|
351 setVisibilityAllIncremental("hidden");
|
|
352 setEosStatus(!nextIncrementalItem(lastShown));
|
|
353 }
|
|
354
|
|
355 setLocation();
|
|
356 }
|
|
357
|
|
358 toc = tableOfContents();
|
|
359 hideTableOfContents();
|
|
360
|
|
361 // bind event handlers
|
|
362 document.onclick = mouseButtonClick;
|
|
363 document.onmouseup = mouseButtonUp;
|
|
364 document.onkeydown = keyDown;
|
|
365 window.onresize = resized;
|
|
366 window.onscroll = scrolled;
|
|
367 window.onunload = unloaded;
|
|
368 singleSlideView();
|
|
369
|
|
370
|
|
371 setLocation();
|
|
372 resized();
|
|
373
|
|
374 if (ie7)
|
|
375 setTimeout("ieHack()", 100);
|
|
376
|
|
377 showToolbar();
|
|
378 setInterval("checkLocation()", 200); // for back button detection
|
|
379 }
|
|
380
|
|
381 // add localize method to all strings for use
|
|
382 // as in help.innerHTML = "help".localize();
|
|
383 String.prototype.localize = function()
|
|
384 {
|
|
385 if (this == "")
|
|
386 return this;
|
|
387
|
|
388 // try full language code, e.g. en-US
|
|
389 var s, lookup = localize[lang];
|
|
390
|
|
391 if (lookup)
|
|
392 {
|
|
393 s = lookup[this];
|
|
394
|
|
395 if (s)
|
|
396 return s;
|
|
397 }
|
|
398
|
|
399 // try en if undefined for en-US
|
|
400 var lg = lang.split("-");
|
|
401
|
|
402 if (lg.length > 1)
|
|
403 {
|
|
404 lookup = localize[lg[0]];
|
|
405
|
|
406 if (lookup)
|
|
407 {
|
|
408 s = lookup[this];
|
|
409
|
|
410 if (s)
|
|
411 return s;
|
|
412 }
|
|
413 }
|
|
414
|
|
415 // otherwise string as is
|
|
416 return this;
|
|
417 }
|
|
418
|
|
419 // suppress IE's image toolbar pop up
|
|
420 function hideImageToolbar()
|
|
421 {
|
|
422 if (!ns_pos)
|
|
423 {
|
|
424 var images = document.getElementsByTagName("IMG");
|
|
425
|
|
426 for (var i = 0; i < images.length; ++i)
|
|
427 images[i].setAttribute("galleryimg", "no");
|
|
428 }
|
|
429 }
|
|
430
|
|
431 // hack to persuade IE to compute correct document height
|
|
432 // as needed for simulating fixed positioning of toolbar
|
|
433 function ieHack()
|
|
434 {
|
|
435 window.resizeBy(0,-1);
|
|
436 window.resizeBy(0, 1);
|
|
437 }
|
|
438
|
|
439 function unloaded(e)
|
|
440 {
|
|
441 //alert("unloaded");
|
|
442 }
|
|
443
|
|
444 // Firefox reload SVG bug work around
|
|
445 function reload(e)
|
|
446 {
|
|
447 if (!e)
|
|
448 var e = window.event;
|
|
449
|
|
450 hideBackgrounds();
|
|
451 setTimeout("document.reload();", 100);
|
|
452
|
|
453 stopPropagation(e);
|
|
454 e.cancel = true;
|
|
455 e.returnValue = false;
|
|
456
|
|
457 return false;
|
|
458 }
|
|
459
|
|
460 // Safari and Konqueror don't yet support getComputedStyle()
|
|
461 // and they always reload page when location.href is updated
|
|
462 function isKHTML()
|
|
463 {
|
|
464 var agent = navigator.userAgent;
|
|
465 return (agent.indexOf("KHTML") >= 0 ? true : false);
|
|
466 }
|
|
467
|
|
468 function resized()
|
|
469 {
|
|
470 var width = 0;
|
|
471
|
|
472 if ( typeof( window.innerWidth ) == 'number' )
|
|
473 width = window.innerWidth; // Non IE browser
|
|
474 else if (document.documentElement && document.documentElement.clientWidth)
|
|
475 width = document.documentElement.clientWidth; // IE6
|
|
476 else if (document.body && document.body.clientWidth)
|
|
477 width = document.body.clientWidth; // IE4
|
|
478
|
|
479 var height = 0;
|
|
480
|
|
481 if ( typeof( window.innerHeight ) == 'number' )
|
|
482 height = window.innerHeight; // Non IE browser
|
|
483 else if (document.documentElement && document.documentElement.clientHeight)
|
|
484 height = document.documentElement.clientHeight; // IE6
|
|
485 else if (document.body && document.body.clientHeight)
|
|
486 height = document.body.clientHeight; // IE4
|
|
487
|
|
488 if (height && (width/height > 1.05*1024/768))
|
|
489 {
|
|
490 width = height * 1024.0/768;
|
|
491 }
|
|
492
|
|
493 // IE fires onresize even when only font size is changed!
|
|
494 // so we do a check to avoid blocking < and > actions
|
|
495 if (width != lastWidth || height != lastHeight)
|
|
496 {
|
|
497 if (width >= 1100)
|
|
498 sizeIndex = 5; // 4
|
|
499 else if (width >= 1000)
|
|
500 sizeIndex = 4; // 3
|
|
501 else if (width >= 800)
|
|
502 sizeIndex = 3; // 2
|
|
503 else if (width >= 600)
|
|
504 sizeIndex = 2; // 1
|
|
505 else if (width)
|
|
506 sizeIndex = 0;
|
|
507
|
|
508 // add in font size adjustment from meta element e.g.
|
|
509 // <meta name="font-size-adjustment" content="-2" />
|
|
510 // useful when slides have too much content ;-)
|
|
511
|
|
512 if (0 <= sizeIndex + sizeAdjustment &&
|
|
513 sizeIndex + sizeAdjustment < sizes.length)
|
|
514 sizeIndex = sizeIndex + sizeAdjustment;
|
|
515
|
|
516 // enables cross browser use of relative width/height
|
|
517 // on object elements for use with SVG and Flash media
|
|
518 adjustObjectDimensions(width, height);
|
|
519
|
|
520 document.body.style.fontSize = sizes[sizeIndex];
|
|
521
|
|
522 lastWidth = width;
|
|
523 lastHeight = height;
|
|
524
|
|
525 // force reflow to work around Mozilla bug
|
|
526 //if (ns_pos)
|
|
527 {
|
|
528 var slide = slides[slidenum];
|
|
529 hideSlide(slide);
|
|
530 showSlide(slide);
|
|
531 }
|
|
532
|
|
533 // force correct positioning of toolbar
|
|
534 refreshToolbar(200);
|
|
535 }
|
|
536 }
|
|
537
|
|
538 function scrolled()
|
|
539 {
|
|
540 if (toolbar && !ns_pos && !ie7)
|
|
541 {
|
|
542 hackoffset = scrollXOffset();
|
|
543 // hide toolbar
|
|
544 toolbar.style.display = "none";
|
|
545
|
|
546 // make it reappear later
|
|
547 if (scrollhack == 0 && !viewAll)
|
|
548 {
|
|
549 setTimeout(showToolbar, 1000);
|
|
550 scrollhack = 1;
|
|
551 }
|
|
552 }
|
|
553 }
|
|
554
|
|
555 // used to ensure IE refreshes toolbar in correct position
|
|
556 function refreshToolbar(interval)
|
|
557 {
|
|
558 if (!ns_pos && !ie7)
|
|
559 {
|
|
560 hideToolbar();
|
|
561 setTimeout(showToolbar, interval);
|
|
562 }
|
|
563 }
|
|
564
|
|
565 // restores toolbar after short delay
|
|
566 function showToolbar()
|
|
567 {
|
|
568 if (wantToolbar)
|
|
569 {
|
|
570 if (!ns_pos)
|
|
571 {
|
|
572 // adjust position to allow for scrolling
|
|
573 var xoffset = scrollXOffset();
|
|
574 toolbar.style.left = xoffset;
|
|
575 toolbar.style.right = xoffset;
|
|
576
|
|
577 // determine vertical scroll offset
|
|
578 //var yoffset = scrollYOffset();
|
|
579
|
|
580 // bottom is doc height - window height - scroll offset
|
|
581 //var bottom = documentHeight() - lastHeight - yoffset
|
|
582
|
|
583 //if (yoffset > 0 || documentHeight() > lastHeight)
|
|
584 // bottom += 16; // allow for height of scrollbar
|
|
585
|
|
586 toolbar.style.bottom = 0; //bottom;
|
|
587 }
|
|
588
|
|
589 toolbar.style.display = "block";
|
|
590 toolbar.style.visibility = "visible";
|
|
591 }
|
|
592
|
|
593 scrollhack = 0;
|
|
594
|
|
595
|
|
596 // set the keyboard focus to the help link on the
|
|
597 // toolbar to ensure that document has the focus
|
|
598 // IE doesn't always work with window.focus()
|
|
599 // and this hack has benefit of Enter for help
|
|
600
|
|
601 try
|
|
602 {
|
|
603 if (!opera)
|
|
604 helpAnchor.focus();
|
|
605 }
|
|
606 catch (e)
|
|
607 {
|
|
608 }
|
|
609 }
|
|
610
|
|
611 function hideToolbar()
|
|
612 {
|
|
613 toolbar.style.display = "none";
|
|
614 toolbar.style.visibility = "hidden";
|
|
615 window.focus();
|
|
616 }
|
|
617
|
|
618 // invoked via F key
|
|
619 function toggleToolbar()
|
|
620 {
|
|
621 if (!viewAll)
|
|
622 {
|
|
623 if (toolbar.style.display == "none")
|
|
624 {
|
|
625 toolbar.style.display = "block";
|
|
626 toolbar.style.visibility = "visible";
|
|
627 wantToolbar = 1;
|
|
628 }
|
|
629 else
|
|
630 {
|
|
631 toolbar.style.display = "none";
|
|
632 toolbar.style.visibility = "hidden";
|
|
633 wantToolbar = 0;
|
|
634 }
|
|
635 }
|
|
636 }
|
|
637
|
|
638 function scrollXOffset()
|
|
639 {
|
|
640 if (window.pageXOffset)
|
|
641 return self.pageXOffset;
|
|
642
|
|
643 if (document.documentElement &&
|
|
644 document.documentElement.scrollLeft)
|
|
645 return document.documentElement.scrollLeft;
|
|
646
|
|
647 if (document.body)
|
|
648 return document.body.scrollLeft;
|
|
649
|
|
650 return 0;
|
|
651 }
|
|
652
|
|
653
|
|
654 function scrollYOffset()
|
|
655 {
|
|
656 if (window.pageYOffset)
|
|
657 return self.pageYOffset;
|
|
658
|
|
659 if (document.documentElement &&
|
|
660 document.documentElement.scrollTop)
|
|
661 return document.documentElement.scrollTop;
|
|
662
|
|
663 if (document.body)
|
|
664 return document.body.scrollTop;
|
|
665
|
|
666 return 0;
|
|
667 }
|
|
668
|
|
669 // looking for a way to determine height of slide content
|
|
670 // the slide itself is set to the height of the window
|
|
671 function optimizeFontSize()
|
|
672 {
|
|
673 var slide = slides[slidenum];
|
|
674
|
|
675 //var dh = documentHeight(); //getDocHeight(document);
|
|
676 var dh = slide.scrollHeight;
|
|
677 var wh = getWindowHeight();
|
|
678 var u = 100 * dh / wh;
|
|
679
|
|
680 alert("window utilization = " + u + "% (doc "
|
|
681 + dh + " win " + wh + ")");
|
|
682 }
|
|
683
|
|
684 function getDocHeight(doc) // from document object
|
|
685 {
|
|
686 if (!doc)
|
|
687 doc = document;
|
|
688
|
|
689 if (doc && doc.body && doc.body.offsetHeight)
|
|
690 return doc.body.offsetHeight; // ns/gecko syntax
|
|
691
|
|
692 if (doc && doc.body && doc.body.scrollHeight)
|
|
693 return doc.body.scrollHeight;
|
|
694
|
|
695 alert("couldn't determine document height");
|
|
696 }
|
|
697
|
|
698 function getWindowHeight()
|
|
699 {
|
|
700 if ( typeof( window.innerHeight ) == 'number' )
|
|
701 return window.innerHeight; // Non IE browser
|
|
702
|
|
703 if (document.documentElement && document.documentElement.clientHeight)
|
|
704 return document.documentElement.clientHeight; // IE6
|
|
705
|
|
706 if (document.body && document.body.clientHeight)
|
|
707 return document.body.clientHeight; // IE4
|
|
708 }
|
|
709
|
|
710
|
|
711
|
|
712 function documentHeight()
|
|
713 {
|
|
714 var sh, oh;
|
|
715
|
|
716 sh = document.body.scrollHeight;
|
|
717 oh = document.body.offsetHeight;
|
|
718
|
|
719 if (sh && oh)
|
|
720 {
|
|
721 return (sh > oh ? sh : oh);
|
|
722 }
|
|
723
|
|
724 // no idea!
|
|
725 return 0;
|
|
726 }
|
|
727
|
|
728 function smaller()
|
|
729 {
|
|
730 if (sizeIndex > 0)
|
|
731 {
|
|
732 --sizeIndex;
|
|
733 }
|
|
734
|
|
735 toolbar.style.display = "none";
|
|
736 document.body.style.fontSize = sizes[sizeIndex];
|
|
737 var slide = slides[slidenum];
|
|
738 hideSlide(slide);
|
|
739 showSlide(slide);
|
|
740 setTimeout(showToolbar, 300);
|
|
741 }
|
|
742
|
|
743 function bigger()
|
|
744 {
|
|
745 if (sizeIndex < sizes.length - 1)
|
|
746 {
|
|
747 ++sizeIndex;
|
|
748 }
|
|
749
|
|
750 toolbar.style.display = "none";
|
|
751 document.body.style.fontSize = sizes[sizeIndex];
|
|
752 var slide = slides[slidenum];
|
|
753 hideSlide(slide);
|
|
754 showSlide(slide);
|
|
755 setTimeout(showToolbar, 300);
|
|
756 }
|
|
757
|
|
758 // enables cross browser use of relative width/height
|
|
759 // on object elements for use with SVG and Flash media
|
|
760 // with thanks to Ivan Herman for the suggestion
|
|
761 function adjustObjectDimensions(width, height)
|
|
762 {
|
|
763 for( var i = 0; i < objects.length; i++ )
|
|
764 {
|
|
765 var obj = objects[i];
|
|
766 var mimeType = obj.getAttribute("type");
|
|
767
|
|
768 if (mimeType == "image/svg+xml" || mimeType == "application/x-shockwave-flash")
|
|
769 {
|
|
770 if ( !obj.initialWidth )
|
|
771 obj.initialWidth = obj.getAttribute("width");
|
|
772
|
|
773 if ( !obj.initialHeight )
|
|
774 obj.initialHeight = obj.getAttribute("height");
|
|
775
|
|
776 if ( obj.initialWidth && obj.initialWidth.charAt(obj.initialWidth.length-1) == "%" )
|
|
777 {
|
|
778 var w = parseInt(obj.initialWidth.slice(0, obj.initialWidth.length-1));
|
|
779 var newW = width * (w/100.0);
|
|
780 obj.setAttribute("width",newW);
|
|
781 }
|
|
782
|
|
783 if ( obj.initialHeight && obj.initialHeight.charAt(obj.initialHeight.length-1) == "%" )
|
|
784 {
|
|
785 var h = parseInt(obj.initialHeight.slice(0, obj.initialHeight.length-1));
|
|
786 var newH = height * (h/100.0);
|
|
787 obj.setAttribute("height", newH);
|
|
788 }
|
|
789 }
|
|
790 }
|
|
791 }
|
|
792
|
|
793 function cancel(event)
|
|
794 {
|
|
795 if (event)
|
|
796 {
|
|
797 event.cancel = true;
|
|
798 event.returnValue = false;
|
|
799
|
|
800 if (event.preventDefault)
|
|
801 event.preventDefault();
|
|
802 }
|
|
803
|
|
804 return false;
|
|
805 }
|
|
806
|
|
807 // See e.g. http://www.quirksmode.org/js/events/keys.html for keycodes
|
|
808 function keyDown(event)
|
|
809 {
|
|
810 var key;
|
|
811
|
|
812 if (!event)
|
|
813 var event = window.event;
|
|
814
|
|
815 // kludge around NS/IE differences
|
|
816 if (window.event)
|
|
817 key = window.event.keyCode;
|
|
818 else if (event.which)
|
|
819 key = event.which;
|
|
820 else
|
|
821 return true; // Yikes! unknown browser
|
|
822
|
|
823 // ignore event if key value is zero
|
|
824 // as for alt on Opera and Konqueror
|
|
825 if (!key)
|
|
826 return true;
|
|
827
|
|
828 // check for concurrent control/command/alt key
|
|
829 // but are these only present on mouse events?
|
|
830
|
|
831 if (event.ctrlKey || event.altKey || event.metaKey)
|
|
832 return true;
|
|
833
|
|
834 // dismiss table of contents if visible
|
|
835 if (isShownToc() && key != 9 && key != 16 && key != 38 && key != 40)
|
|
836 {
|
|
837 hideTableOfContents();
|
|
838
|
|
839 if (key == 27 || key == 84 || key == 67)
|
|
840 return cancel(event);
|
|
841 }
|
|
842
|
|
843 if (key == 34) // Page Down
|
|
844 {
|
|
845 if (viewAll)
|
|
846 return true;
|
|
847
|
|
848 nextSlide(false);
|
|
849 return cancel(event);
|
|
850 }
|
|
851 else if (key == 33) // Page Up
|
|
852 {
|
|
853 if (viewAll)
|
|
854 return true;
|
|
855
|
|
856 previousSlide(false);
|
|
857 return cancel(event);
|
|
858 }
|
|
859 else if (key == 32) // space bar
|
|
860 {
|
|
861 nextSlide(true);
|
|
862 return cancel(event);
|
|
863 }
|
|
864 else if (key == 37) // Left arrow
|
|
865 {
|
|
866 previousSlide(!event.shiftKey);
|
|
867 return cancel(event);
|
|
868 }
|
|
869 else if (key == 36) // Home
|
|
870 {
|
|
871 firstSlide();
|
|
872 return cancel(event);
|
|
873 }
|
|
874 else if (key == 35) // End
|
|
875 {
|
|
876 lastSlide();
|
|
877 return cancel(event);
|
|
878 }
|
|
879 else if (key == 39) // Right arrow
|
|
880 {
|
|
881 nextSlide(!event.shiftKey);
|
|
882 return cancel(event);
|
|
883 }
|
|
884 else if (key == 13) // Enter
|
|
885 {
|
|
886 if (outline)
|
|
887 {
|
|
888 if (outline.visible)
|
|
889 fold(outline);
|
|
890 else
|
|
891 unfold(outline);
|
|
892
|
|
893 return cancel(event);
|
|
894 }
|
|
895 }
|
|
896 else if (key == 188) // < for smaller fonts
|
|
897 {
|
|
898 smaller();
|
|
899 return cancel(event);
|
|
900 }
|
|
901 else if (key == 190) // > for larger fonts
|
|
902 {
|
|
903 bigger();
|
|
904 return cancel(event);
|
|
905 }
|
|
906 else if (key == 189 || key == 109) // - for smaller fonts
|
|
907 {
|
|
908 smaller();
|
|
909 return cancel(event);
|
|
910 }
|
|
911 else if (key == 187 || key == 191 || key == 107) // = + for larger fonts
|
|
912 {
|
|
913 bigger();
|
|
914 return cancel(event);
|
|
915 }
|
|
916 else if (key == 83) // S for smaller fonts
|
|
917 {
|
|
918 smaller();
|
|
919 return cancel(event);
|
|
920 }
|
|
921 else if (key == 66) // B for larger fonts
|
|
922 {
|
|
923 bigger();
|
|
924 return cancel(event);
|
|
925 }
|
|
926 else if (key == 90) // Z for last slide
|
|
927 {
|
|
928 lastSlide();
|
|
929 return cancel(event);
|
|
930 }
|
|
931 else if (key == 70) // F for toggle toolbar
|
|
932 {
|
|
933 toggleToolbar();
|
|
934 return cancel(event);
|
|
935 }
|
|
936 else if (key == 65) // A for toggle view single/all slides
|
|
937 {
|
|
938 toggleView();
|
|
939 return cancel(event);
|
|
940 }
|
|
941 else if (key == 75) // toggle action of left click for next page
|
|
942 {
|
|
943 // commented out by kent 20100210.
|
|
944 /*
|
|
945 mouseClickEnabled = !mouseClickEnabled;
|
|
946 alert((mouseClickEnabled ? "enabled" : "disabled") + " mouse click advance");
|
|
947 return cancel(event);
|
|
948 */
|
|
949 }
|
|
950 else if (key == 84 || key == 67) // T or C for table of contents
|
|
951 {
|
|
952 if (toc)
|
|
953 showTableOfContents();
|
|
954
|
|
955 return cancel(event);
|
|
956 }
|
|
957 else if (key == 72) // H for help
|
|
958 {
|
|
959 window.location = helpPage;
|
|
960 return cancel(event);
|
|
961 }
|
|
962
|
|
963 // added by kent 20100210
|
|
964 else if (key == 77) {
|
|
965 showspeak = !showspeak;
|
|
966 var value = (showspeak? "visible":"hidden");
|
|
967 var elems = document.getElementsByClassName("speak");
|
|
968
|
|
969 for (var i=0; i<elems.length; i++) {
|
|
970 elems[i].style.visibility = value;
|
|
971 }
|
|
972 return cancel(event);
|
|
973 }
|
|
974
|
|
975 //else if (key == 93) // Windows menu key
|
|
976 //alert("lastShown is " + lastShown);
|
|
977 //else alert("key code is "+ key);
|
|
978
|
|
979
|
|
980 return true;
|
|
981 }
|
|
982
|
|
983 // make note of length of selected text
|
|
984 // as this evaluates to zero in click event
|
|
985 function mouseButtonUp(e)
|
|
986 {
|
|
987 selectedTextLen = getSelectedText().length;
|
|
988 }
|
|
989
|
|
990 // right mouse button click is reserved for context menus
|
|
991 // it is more reliable to detect rightclick than leftclick
|
|
992 function mouseButtonClick(e)
|
|
993 {
|
|
994 var rightclick = false;
|
|
995 var leftclick = false;
|
|
996 var middleclick = false;
|
|
997 var target;
|
|
998
|
|
999 if (!e)
|
|
1000 var e = window.event;
|
|
1001
|
|
1002 if (e.target)
|
|
1003 target = e.target;
|
|
1004 else if (e.srcElement)
|
|
1005 target = e.srcElement;
|
|
1006
|
|
1007 // work around Safari bug
|
|
1008 if (target.nodeType == 3)
|
|
1009 target = target.parentNode;
|
|
1010
|
|
1011 if (e.which) // all browsers except IE
|
|
1012 {
|
|
1013 leftclick = (e.which == 1);
|
|
1014 middleclick = (e.which == 2);
|
|
1015 rightclick = (e.which == 3);
|
|
1016 }
|
|
1017 else if (e.button)
|
|
1018 {
|
|
1019 // Konqueror gives 1 for left, 4 for middle
|
|
1020 // IE6 gives 0 for left and not 1 as I expected
|
|
1021
|
|
1022 if (e.button == 4)
|
|
1023 middleclick = true;
|
|
1024
|
|
1025 // all browsers agree on 2 for right button
|
|
1026 rightclick = (e.button == 2);
|
|
1027 }
|
|
1028 else leftclick = true;
|
|
1029
|
|
1030 //alert("selected text length = "+selectedTextLen);
|
|
1031
|
|
1032 if (selectedTextLen > 0)
|
|
1033 {
|
|
1034 stopPropagation(e);
|
|
1035 e.cancel = true;
|
|
1036 e.returnValue = false;
|
|
1037 return false;
|
|
1038 }
|
|
1039
|
|
1040 // dismiss table of contents
|
|
1041 hideTableOfContents();
|
|
1042
|
|
1043 // check if target is something that probably want's clicks
|
|
1044 // e.g. embed, object, input, textarea, select, option
|
|
1045
|
|
1046 if (mouseClickEnabled && leftclick &&
|
|
1047 target.nodeName != "EMBED" &&
|
|
1048 target.nodeName != "OBJECT" &&
|
|
1049 target.nodeName != "VIDEO" &&
|
|
1050 target.nodeName != "INPUT" &&
|
|
1051 target.nodeName != "TEXTAREA" &&
|
|
1052 target.nodeName != "SELECT" &&
|
|
1053 target.nodeName != "OPTION")
|
|
1054 {
|
|
1055 nextSlide(true);
|
|
1056 stopPropagation(e);
|
|
1057 e.cancel = true;
|
|
1058 e.returnValue = false;
|
|
1059 }
|
|
1060 }
|
|
1061
|
|
1062 function previousSlide(incremental)
|
|
1063 {
|
|
1064 if (!viewAll)
|
|
1065 {
|
|
1066 var slide;
|
|
1067
|
|
1068 if ((incremental || slidenum == 0) && lastShown != null)
|
|
1069 {
|
|
1070 lastShown = hidePreviousItem(lastShown);
|
|
1071 setEosStatus(false);
|
|
1072 }
|
|
1073 else if (slidenum > 0)
|
|
1074 {
|
|
1075 slide = slides[slidenum];
|
|
1076 hideSlide(slide);
|
|
1077
|
|
1078 slidenum = slidenum - 1;
|
|
1079 slide = slides[slidenum];
|
|
1080 setVisibilityAllIncremental("visible");
|
|
1081 lastShown = previousIncrementalItem(null);
|
|
1082 setEosStatus(true);
|
|
1083 showSlide(slide);
|
|
1084 }
|
|
1085
|
|
1086 setLocation();
|
|
1087
|
|
1088 if (!ns_pos)
|
|
1089 refreshToolbar(200);
|
|
1090 }
|
|
1091 }
|
|
1092
|
|
1093 function nextSlide(incremental)
|
|
1094 {
|
|
1095 if (!viewAll)
|
|
1096 {
|
|
1097 var slide, last = lastShown;
|
|
1098
|
|
1099 if (incremental || slidenum == slides.length - 1)
|
|
1100 lastShown = revealNextItem(lastShown);
|
|
1101
|
|
1102 if ((!incremental || lastShown == null) && slidenum < slides.length - 1)
|
|
1103 {
|
|
1104 slide = slides[slidenum];
|
|
1105 hideSlide(slide);
|
|
1106
|
|
1107 slidenum = slidenum + 1;
|
|
1108 slide = slides[slidenum];
|
|
1109 lastShown = null;
|
|
1110 setVisibilityAllIncremental("hidden");
|
|
1111 showSlide(slide);
|
|
1112 }
|
|
1113 else if (!lastShown)
|
|
1114 {
|
|
1115 if (last && incremental)
|
|
1116 lastShown = last;
|
|
1117 }
|
|
1118
|
|
1119 setLocation();
|
|
1120
|
|
1121 setEosStatus(!nextIncrementalItem(lastShown));
|
|
1122
|
|
1123 if (!ns_pos)
|
|
1124 refreshToolbar(200);
|
|
1125 }
|
|
1126 }
|
|
1127
|
|
1128 // to first slide with nothing revealed
|
|
1129 // i.e. state at start of presentation
|
|
1130 function firstSlide()
|
|
1131 {
|
|
1132 if (!viewAll)
|
|
1133 {
|
|
1134 var slide;
|
|
1135
|
|
1136 if (slidenum != 0)
|
|
1137 {
|
|
1138 slide = slides[slidenum];
|
|
1139 hideSlide(slide);
|
|
1140
|
|
1141 slidenum = 0;
|
|
1142 slide = slides[slidenum];
|
|
1143 lastShown = null;
|
|
1144 setVisibilityAllIncremental("hidden");
|
|
1145 showSlide(slide);
|
|
1146 }
|
|
1147
|
|
1148 setEosStatus(!nextIncrementalItem(lastShown));
|
|
1149 setLocation();
|
|
1150 }
|
|
1151 }
|
|
1152
|
|
1153
|
|
1154 // to last slide with everything revealed
|
|
1155 // i.e. state at end of presentation
|
|
1156 function lastSlide()
|
|
1157 {
|
|
1158 if (!viewAll)
|
|
1159 {
|
|
1160 var slide;
|
|
1161
|
|
1162 lastShown = null; //revealNextItem(lastShown);
|
|
1163
|
|
1164 if (lastShown == null && slidenum < slides.length - 1)
|
|
1165 {
|
|
1166 slide = slides[slidenum];
|
|
1167 hideSlide(slide);
|
|
1168 slidenum = slides.length - 1;
|
|
1169 slide = slides[slidenum];
|
|
1170 setVisibilityAllIncremental("visible");
|
|
1171 lastShown = previousIncrementalItem(null);
|
|
1172
|
|
1173 showSlide(slide);
|
|
1174 }
|
|
1175 else
|
|
1176 {
|
|
1177 setVisibilityAllIncremental("visible");
|
|
1178 lastShown = previousIncrementalItem(null);
|
|
1179 }
|
|
1180
|
|
1181 setEosStatus(true);
|
|
1182 setLocation();
|
|
1183 }
|
|
1184 }
|
|
1185
|
|
1186 // first slide is 0
|
|
1187 function gotoSlide(num)
|
|
1188 {
|
|
1189 //alert("going to slide " + (num+1));
|
|
1190 var slide = slides[slidenum];
|
|
1191 hideSlide(slide);
|
|
1192 slidenum = num;
|
|
1193 slide = slides[slidenum];
|
|
1194 lastShown = null;
|
|
1195 setVisibilityAllIncremental("hidden");
|
|
1196 setEosStatus(!nextIncrementalItem(lastShown));
|
|
1197 document.title = title + " (" + (slidenum+1) + ")";
|
|
1198 showSlide(slide);
|
|
1199 showSlideNumber();
|
|
1200 }
|
|
1201
|
|
1202 function setEosStatus(state)
|
|
1203 {
|
|
1204 if (eos)
|
|
1205 eos.style.color = (state ? "rgb(240,240,240)" : "red");
|
|
1206 }
|
|
1207
|
|
1208 function showSlide(slide)
|
|
1209 {
|
|
1210 syncBackground(slide);
|
|
1211 window.scrollTo(0,0);
|
|
1212 slide.style.visibility = "visible";
|
|
1213 slide.style.display = "block";
|
|
1214 }
|
|
1215
|
|
1216 function hideSlide(slide)
|
|
1217 {
|
|
1218 slide.style.visibility = "hidden";
|
|
1219 slide.style.display = "none";
|
|
1220 }
|
|
1221
|
|
1222 function beforePrint()
|
|
1223 {
|
|
1224 showAllSlides();
|
|
1225 hideToolbar();
|
|
1226 }
|
|
1227
|
|
1228 function afterPrint()
|
|
1229 {
|
|
1230 if (!viewAll)
|
|
1231 {
|
|
1232 singleSlideView();
|
|
1233 showToolbar();
|
|
1234 }
|
|
1235 }
|
|
1236
|
|
1237 function printSlides()
|
|
1238 {
|
|
1239 beforePrint();
|
|
1240 window.print();
|
|
1241 afterPrint();
|
|
1242 }
|
|
1243
|
|
1244 function toggleView()
|
|
1245 {
|
|
1246 if (viewAll)
|
|
1247 {
|
|
1248 singleSlideView();
|
|
1249 showToolbar();
|
|
1250 viewAll = 0;
|
|
1251 }
|
|
1252 else
|
|
1253 {
|
|
1254 showAllSlides();
|
|
1255 hideToolbar();
|
|
1256 viewAll = 1;
|
|
1257 }
|
|
1258 }
|
|
1259
|
|
1260 // prepare for printing
|
|
1261 function showAllSlides()
|
|
1262 {
|
|
1263 var slide;
|
|
1264
|
|
1265 for (var i = 0; i < slides.length; ++i)
|
|
1266 {
|
|
1267 slide = slides[i];
|
|
1268
|
|
1269 slide.style.position = "relative";
|
|
1270 slide.style.borderTopStyle = "solid";
|
|
1271 slide.style.borderTopWidth = "thin";
|
|
1272 slide.style.borderTopColor = "black";
|
|
1273
|
|
1274 try {
|
|
1275 if (i == 0)
|
|
1276 slide.style.pageBreakBefore = "avoid";
|
|
1277 else
|
|
1278 slide.style.pageBreakBefore = "always";
|
|
1279 }
|
|
1280 catch (e)
|
|
1281 {
|
|
1282 //do nothing
|
|
1283 }
|
|
1284
|
|
1285 setVisibilityAllIncremental("visible");
|
|
1286 showSlide(slide);
|
|
1287 }
|
|
1288
|
|
1289 var note;
|
|
1290
|
|
1291 for (var i = 0; i < notes.length; ++i)
|
|
1292 {
|
|
1293 showSlide(notes[i]);
|
|
1294 }
|
|
1295
|
|
1296 // no easy way to render background under each slide
|
|
1297 // without duplicating the background divs for each slide
|
|
1298 // therefore hide backgrounds to avoid messing up slides
|
|
1299 hideBackgrounds();
|
|
1300 }
|
|
1301
|
|
1302 // restore after printing
|
|
1303 function singleSlideView()
|
|
1304 {
|
|
1305 var slide;
|
|
1306
|
|
1307 for (var i = 0; i < slides.length; ++i)
|
|
1308 {
|
|
1309 slide = slides[i];
|
|
1310
|
|
1311 slide.style.position = "absolute";
|
|
1312
|
|
1313 if (i == slidenum)
|
|
1314 {
|
|
1315 slide.style.borderStyle = "none";
|
|
1316 showSlide(slide);
|
|
1317 }
|
|
1318 else
|
|
1319 {
|
|
1320 slide.style.borderStyle = "none";
|
|
1321 hideSlide(slide);
|
|
1322 }
|
|
1323 }
|
|
1324
|
|
1325 setVisibilityAllIncremental("visible");
|
|
1326 lastShown = previousIncrementalItem(null);
|
|
1327
|
|
1328 var note;
|
|
1329
|
|
1330 for (var i = 0; i < notes.length; ++i)
|
|
1331 {
|
|
1332 hideSlide(notes[i]);
|
|
1333 }
|
|
1334 }
|
|
1335
|
|
1336 // the string str is a whitespace separated list of tokens
|
|
1337 // test if str contains a particular token, e.g. "slide"
|
|
1338 function hasToken(str, token)
|
|
1339 {
|
|
1340 if (str)
|
|
1341 {
|
|
1342 // define pattern as regular expression
|
|
1343 var pattern = /\w+/g;
|
|
1344
|
|
1345 // check for matches
|
|
1346 // place result in array
|
|
1347 var result = str.match(pattern);
|
|
1348
|
|
1349 // now check if desired token is present
|
|
1350 for (var i = 0; i < result.length; i++)
|
|
1351 {
|
|
1352 if (result[i] == token)
|
|
1353 return true;
|
|
1354 }
|
|
1355 }
|
|
1356
|
|
1357 return false;
|
|
1358 }
|
|
1359
|
|
1360 function getClassList(element)
|
|
1361 {
|
|
1362 if (typeof element.className != 'undefined')
|
|
1363 return element.className;
|
|
1364
|
|
1365 var clsname = (ns_pos||ie8) ? "class" : "className";
|
|
1366 return element.getAttribute(clsname);
|
|
1367 }
|
|
1368
|
|
1369 function hasClass(element, name)
|
|
1370 {
|
|
1371 var regexp = new RegExp("(^| )" + name + "\W*");
|
|
1372
|
|
1373 if (typeof element.className != 'undefined')
|
|
1374 return regexp.test(element.className);
|
|
1375
|
|
1376 var clsname = (ns_pos||ie8) ? "class" : "className";
|
|
1377 return regexp.test(element.getAttribute(clsname));
|
|
1378 }
|
|
1379
|
|
1380 function removeClass(element, name)
|
|
1381 {
|
|
1382 var regexp = new RegExp("(^| )" + name + "\W*");
|
|
1383 var clsval = "";
|
|
1384
|
|
1385 if (typeof element.className != 'undefined')
|
|
1386 {
|
|
1387 clsval = element.className;
|
|
1388
|
|
1389 if (clsval)
|
|
1390 {
|
|
1391 clsval = clsval.replace(regexp, "");
|
|
1392 element.className = clsval;
|
|
1393 }
|
|
1394 }
|
|
1395 else
|
|
1396 {
|
|
1397 var clsname = (ns_pos||ie8) ? "class" : "className";
|
|
1398 clsval = element.getAttribute(clsname);
|
|
1399
|
|
1400 if (clsval)
|
|
1401 {
|
|
1402 clsval = clsval.replace(regexp, "");
|
|
1403 element.setAttribute(clsname, clsval);
|
|
1404 }
|
|
1405 }
|
|
1406 }
|
|
1407
|
|
1408 function addClass(element, name)
|
|
1409 {
|
|
1410 if (!hasClass(element, name))
|
|
1411 {
|
|
1412 if (typeof element.className != 'undefined')
|
|
1413 element.className += " " + name;
|
|
1414 else
|
|
1415 {
|
|
1416 var clsname = (ns_pos||ie8) ? "class" : "className";
|
|
1417 var clsval = element.getAttribute(clsname);
|
|
1418 clsval = clsval ? clsval + " " + name : name;
|
|
1419 element.setAttribute(clsname, clsval);
|
|
1420 }
|
|
1421 }
|
|
1422 }
|
|
1423
|
|
1424 // wysiwyg editors make it hard to use div elements
|
|
1425 // e.g. amaya loses the div when you copy and paste
|
|
1426 // this function wraps div elements around implicit
|
|
1427 // slides which start with an h1 element and continue
|
|
1428 // up to the next heading or div element
|
|
1429 function wrapImplicitSlides()
|
|
1430 {
|
|
1431 var i, heading, node, next, div;
|
|
1432 var headings = document.getElementsByTagName("h1");
|
|
1433
|
|
1434 if (!headings)
|
|
1435 return;
|
|
1436
|
|
1437 for (i = 0; i < headings.length; ++i)
|
|
1438 {
|
|
1439 heading = headings[i];
|
|
1440
|
|
1441 if (heading.parentNode != document.body)
|
|
1442 continue;
|
|
1443
|
|
1444 node = heading.nextSibling;
|
|
1445
|
|
1446 div = document.createElement("div");
|
|
1447 addClass(div, "slide");
|
|
1448 document.body.replaceChild(div, heading);
|
|
1449 div.appendChild(heading);
|
|
1450
|
|
1451 while (node)
|
|
1452 {
|
|
1453 if (node.nodeType == 1 && // an element
|
|
1454 (node.nodeName == "H1" ||
|
|
1455 node.nodeName == "h1" ||
|
|
1456 node.nodeName == "DIV" ||
|
|
1457 node.nodeName == "div"))
|
|
1458 break;
|
|
1459
|
|
1460 next = node.nextSibling;
|
|
1461 node = document.body.removeChild(node);
|
|
1462 div.appendChild(node);
|
|
1463 node = next;
|
|
1464 }
|
|
1465 }
|
|
1466 }
|
|
1467
|
|
1468 // return new array of all slides
|
|
1469 function collectSlides()
|
|
1470 {
|
|
1471 var slides = new Array();
|
|
1472 var divs = document.body.getElementsByTagName("div");
|
|
1473
|
|
1474 for (var i = 0; i < divs.length; ++i)
|
|
1475 {
|
|
1476 div = divs.item(i);
|
|
1477
|
|
1478 if (hasClass(div, "slide"))
|
|
1479 {
|
|
1480 // add slide to collection
|
|
1481 slides[slides.length] = div;
|
|
1482
|
|
1483 // hide each slide as it is found
|
|
1484 div.style.display = "none";
|
|
1485 div.style.visibility = "hidden";
|
|
1486
|
|
1487 // add dummy <br/> at end for scrolling hack
|
|
1488 var node1 = document.createElement("br");
|
|
1489 div.appendChild(node1);
|
|
1490 var node2 = document.createElement("br");
|
|
1491 div.appendChild(node2);
|
|
1492 }
|
|
1493 else if (hasClass(div, "background"))
|
|
1494 { // work around for Firefox SVG reload bug
|
|
1495 // which otherwise replaces 1st SVG graphic with 2nd
|
|
1496 div.style.display = "block";
|
|
1497 }
|
|
1498 }
|
|
1499
|
|
1500 return slides;
|
|
1501 }
|
|
1502
|
|
1503 // return new array of all <div class="handout">
|
|
1504 function collectNotes()
|
|
1505 {
|
|
1506 var notes = new Array();
|
|
1507 var divs = document.body.getElementsByTagName("div");
|
|
1508
|
|
1509 for (var i = 0; i < divs.length; ++i)
|
|
1510 {
|
|
1511 div = divs.item(i);
|
|
1512
|
|
1513 if (hasClass(div, "handout"))
|
|
1514 {
|
|
1515 // add slide to collection
|
|
1516 notes[notes.length] = div;
|
|
1517
|
|
1518 // hide handout notes as they are found
|
|
1519 div.style.display = "none";
|
|
1520 div.style.visibility = "hidden";
|
|
1521 }
|
|
1522 }
|
|
1523
|
|
1524 return notes;
|
|
1525 }
|
|
1526
|
|
1527 // return new array of all <div class="background">
|
|
1528 // including named backgrounds e.g. class="background titlepage"
|
|
1529 function collectBackgrounds()
|
|
1530 {
|
|
1531 var backgrounds = new Array();
|
|
1532 var divs = document.body.getElementsByTagName("div");
|
|
1533
|
|
1534 for (var i = 0; i < divs.length; ++i)
|
|
1535 {
|
|
1536 div = divs.item(i);
|
|
1537
|
|
1538 if (hasClass(div, "background"))
|
|
1539 {
|
|
1540 // add slide to collection
|
|
1541 backgrounds[backgrounds.length] = div;
|
|
1542
|
|
1543 // hide named backgrounds as they are found
|
|
1544 // e.g. class="background epilog"
|
|
1545 if (getClassList(div) != "background")
|
|
1546 {
|
|
1547 div.style.display = "none";
|
|
1548 div.style.visibility = "hidden";
|
|
1549 }
|
|
1550 }
|
|
1551 }
|
|
1552
|
|
1553 return backgrounds;
|
|
1554 }
|
|
1555
|
|
1556 // show just the backgrounds pertinent to this slide
|
|
1557 function syncBackground(slide)
|
|
1558 {
|
|
1559 var background;
|
|
1560 var bgColor;
|
|
1561
|
|
1562 if (slide.currentStyle)
|
|
1563 bgColor = slide.currentStyle["backgroundColor"];
|
|
1564 else if (document.defaultView)
|
|
1565 {
|
|
1566 var styles = document.defaultView.getComputedStyle(slide,null);
|
|
1567
|
|
1568 if (styles)
|
|
1569 bgColor = styles.getPropertyValue("background-color");
|
|
1570 else // broken implementation probably due Safari or Konqueror
|
|
1571 {
|
|
1572 //alert("defective implementation of getComputedStyle()");
|
|
1573 bgColor = "transparent";
|
|
1574 }
|
|
1575 }
|
|
1576 else
|
|
1577 bgColor == "transparent";
|
|
1578
|
|
1579 if (bgColor == "transparent")
|
|
1580 {
|
|
1581 var slideClass = getClassList(slide);
|
|
1582
|
|
1583 for (var i = 0; i < backgrounds.length; i++)
|
|
1584 {
|
|
1585 background = backgrounds[i];
|
|
1586
|
|
1587 var bgClass = getClassList(background);
|
|
1588
|
|
1589 if (matchingBackground(slideClass, bgClass))
|
|
1590 {
|
|
1591 background.style.display = "block";
|
|
1592 background.style.visibility = "visible";
|
|
1593 }
|
|
1594 else
|
|
1595 {
|
|
1596 background.style.display = "none";
|
|
1597 background.style.visibility = "hidden";
|
|
1598 }
|
|
1599 }
|
|
1600 }
|
|
1601 else // forcibly hide all backgrounds
|
|
1602 hideBackgrounds();
|
|
1603 }
|
|
1604
|
|
1605 function hideBackgrounds()
|
|
1606 {
|
|
1607 for (var i = 0; i < backgrounds.length; i++)
|
|
1608 {
|
|
1609 background = backgrounds[i];
|
|
1610 background.style.display = "none";
|
|
1611 background.style.visibility = "hidden";
|
|
1612 }
|
|
1613 }
|
|
1614
|
|
1615 // compare classes for slide and background
|
|
1616 function matchingBackground(slideClass, bgClass)
|
|
1617 {
|
|
1618 if (bgClass == "background")
|
|
1619 return true;
|
|
1620
|
|
1621 // define pattern as regular expression
|
|
1622 var pattern = /\w+/g;
|
|
1623
|
|
1624 // check for matches and place result in array
|
|
1625 var result = slideClass.match(pattern);
|
|
1626
|
|
1627 // now check if desired name is present for background
|
|
1628 for (var i = 0; i < result.length; i++)
|
|
1629 {
|
|
1630 if (hasToken(bgClass, result[i]))
|
|
1631 return true;
|
|
1632 }
|
|
1633
|
|
1634 return false;
|
|
1635 }
|
|
1636
|
|
1637 // left to right traversal of root's content
|
|
1638 function nextNode(root, node)
|
|
1639 {
|
|
1640 if (node == null)
|
|
1641 return root.firstChild;
|
|
1642
|
|
1643 if (node.firstChild)
|
|
1644 return node.firstChild;
|
|
1645
|
|
1646 if (node.nextSibling)
|
|
1647 return node.nextSibling;
|
|
1648
|
|
1649 for (;;)
|
|
1650 {
|
|
1651 node = node.parentNode;
|
|
1652
|
|
1653 if (!node || node == root)
|
|
1654 break;
|
|
1655
|
|
1656 if (node && node.nextSibling)
|
|
1657 return node.nextSibling;
|
|
1658 }
|
|
1659
|
|
1660 return null;
|
|
1661 }
|
|
1662
|
|
1663 // right to left traversal of root's content
|
|
1664 function previousNode(root, node)
|
|
1665 {
|
|
1666 if (node == null)
|
|
1667 {
|
|
1668 node = root.lastChild;
|
|
1669
|
|
1670 if (node)
|
|
1671 {
|
|
1672 while (node.lastChild)
|
|
1673 node = node.lastChild;
|
|
1674 }
|
|
1675
|
|
1676 return node;
|
|
1677 }
|
|
1678
|
|
1679 if (node.previousSibling)
|
|
1680 {
|
|
1681 node = node.previousSibling;
|
|
1682
|
|
1683 while (node.lastChild)
|
|
1684 node = node.lastChild;
|
|
1685
|
|
1686 return node;
|
|
1687 }
|
|
1688
|
|
1689 if (node.parentNode != root)
|
|
1690 return node.parentNode;
|
|
1691
|
|
1692 return null;
|
|
1693 }
|
|
1694
|
|
1695 // HTML elements that can be used with class="incremental"
|
|
1696 // note that you can also put the class on containers like
|
|
1697 // up, ol, dl, and div to make their contents appear
|
|
1698 // incrementally. Upper case is used since this is what
|
|
1699 // browsers report for HTML node names (text/html).
|
|
1700 function incrementalElementList()
|
|
1701 {
|
|
1702 var inclist = new Array();
|
|
1703 inclist["P"] = true;
|
|
1704 inclist["PRE"] = true;
|
|
1705 inclist["LI"] = true;
|
|
1706 inclist["BLOCKQUOTE"] = true;
|
|
1707 inclist["DT"] = true;
|
|
1708 inclist["DD"] = true;
|
|
1709 inclist["H2"] = true;
|
|
1710 inclist["H3"] = true;
|
|
1711 inclist["H4"] = true;
|
|
1712 inclist["H5"] = true;
|
|
1713 inclist["H6"] = true;
|
|
1714 inclist["SPAN"] = true;
|
|
1715 inclist["ADDRESS"] = true;
|
|
1716 inclist["TABLE"] = true;
|
|
1717 inclist["TR"] = true;
|
|
1718 inclist["TH"] = true;
|
|
1719 inclist["TD"] = true;
|
|
1720 inclist["IMG"] = true;
|
|
1721 inclist["OBJECT"] = true;
|
|
1722 return inclist;
|
|
1723 }
|
|
1724
|
|
1725 function nextIncrementalItem(node)
|
|
1726 {
|
|
1727 var slide = slides[slidenum];
|
|
1728
|
|
1729 for (;;)
|
|
1730 {
|
|
1731 node = nextNode(slide, node);
|
|
1732
|
|
1733 if (node == null || node.parentNode == null)
|
|
1734 break;
|
|
1735
|
|
1736 if (node.nodeType == 1) // ELEMENT
|
|
1737 {
|
|
1738 if (node.nodeName == "BR")
|
|
1739 continue;
|
|
1740
|
|
1741 if (hasClass(node, "incremental")
|
|
1742 && okayForIncremental[node.nodeName])
|
|
1743 return node;
|
|
1744
|
|
1745 if (hasClass(node.parentNode, "incremental")
|
|
1746 && !hasClass(node, "non-incremental"))
|
|
1747 return node;
|
|
1748 }
|
|
1749 }
|
|
1750
|
|
1751 return node;
|
|
1752 }
|
|
1753
|
|
1754 function previousIncrementalItem(node)
|
|
1755 {
|
|
1756 var slide = slides[slidenum];
|
|
1757
|
|
1758 for (;;)
|
|
1759 {
|
|
1760 node = previousNode(slide, node);
|
|
1761
|
|
1762 if (node == null || node.parentNode == null)
|
|
1763 break;
|
|
1764
|
|
1765 if (node.nodeType == 1)
|
|
1766 {
|
|
1767 if (node.nodeName == "BR")
|
|
1768 continue;
|
|
1769
|
|
1770 if (hasClass(node, "incremental")
|
|
1771 && okayForIncremental[node.nodeName])
|
|
1772 return node;
|
|
1773
|
|
1774 if (hasClass(node.parentNode, "incremental")
|
|
1775 && !hasClass(node, "non-incremental"))
|
|
1776 return node;
|
|
1777 }
|
|
1778 }
|
|
1779
|
|
1780 return node;
|
|
1781 }
|
|
1782
|
|
1783 // set visibility for all elements on current slide with
|
|
1784 // a parent element with attribute class="incremental"
|
|
1785 function setVisibilityAllIncremental(value)
|
|
1786 {
|
|
1787 var node = nextIncrementalItem(null);
|
|
1788
|
|
1789 while (node)
|
|
1790 {
|
|
1791 node.style.visibility = value;
|
|
1792 node = nextIncrementalItem(node);
|
|
1793 }
|
|
1794 }
|
|
1795
|
|
1796 // reveal the next hidden item on the slide
|
|
1797 // node is null or the node that was last revealed
|
|
1798 function revealNextItem(node)
|
|
1799 {
|
|
1800 node = nextIncrementalItem(node);
|
|
1801
|
|
1802 if (node && node.nodeType == 1) // an element
|
|
1803 node.style.visibility = "visible";
|
|
1804
|
|
1805 return node;
|
|
1806 }
|
|
1807
|
|
1808
|
|
1809 // exact inverse of revealNextItem(node)
|
|
1810 function hidePreviousItem(node)
|
|
1811 {
|
|
1812 if (node && node.nodeType == 1) // an element
|
|
1813 node.style.visibility = "hidden";
|
|
1814
|
|
1815 return previousIncrementalItem(node);
|
|
1816 }
|
|
1817
|
|
1818
|
|
1819 /* set click handlers on all anchors */
|
|
1820 function patchAnchors()
|
|
1821 {
|
|
1822 var anchors = document.body.getElementsByTagName("a");
|
|
1823
|
|
1824 for (var i = 0; i < anchors.length; ++i)
|
|
1825 {
|
|
1826 anchors[i].onclick = clickedAnchor;
|
|
1827 }
|
|
1828 }
|
|
1829
|
|
1830 function clickedAnchor(e)
|
|
1831 {
|
|
1832 if (!e)
|
|
1833 var e = window.event;
|
|
1834
|
|
1835 // compare this.href with location.href
|
|
1836 // for link to another slide in this doc
|
|
1837
|
|
1838 if (pageAddress(this.href) == pageAddress(location.href))
|
|
1839 {
|
|
1840 // yes, so find new slide number
|
|
1841 var newslidenum = findSlideNumber(this.href);
|
|
1842
|
|
1843 if (newslidenum != slidenum)
|
|
1844 {
|
|
1845 slide = slides[slidenum];
|
|
1846 hideSlide(slide);
|
|
1847 slidenum = newslidenum;
|
|
1848 slide = slides[slidenum];
|
|
1849 showSlide(slide);
|
|
1850 setLocation();
|
|
1851 }
|
|
1852 }
|
|
1853 else if (this.target == null)
|
|
1854 location.href = this.href;
|
|
1855
|
|
1856 this.blur();
|
|
1857 stopPropagation(e);
|
|
1858 }
|
|
1859
|
|
1860 function pageAddress(uri)
|
|
1861 {
|
|
1862 var i = uri.indexOf("#");
|
|
1863
|
|
1864 if (i < 0)
|
|
1865 i = uri.indexOf("%23");
|
|
1866
|
|
1867 // check if anchor is entire page
|
|
1868
|
|
1869 if (i < 0)
|
|
1870 return uri; // yes
|
|
1871
|
|
1872 return uri.substr(0, i);
|
|
1873 }
|
|
1874
|
|
1875 function showSlideNumber()
|
|
1876 {
|
|
1877 slideNumElement.innerHTML = "slide".localize() + " " +
|
|
1878 (slidenum + 1) + "/" + slides.length;
|
|
1879 }
|
|
1880
|
|
1881 // every 200mS check if the location has been changed as a
|
|
1882 // result of the user activating the Back button/menu item
|
|
1883 // doesn't work for Opera < 9.5
|
|
1884 function checkLocation()
|
|
1885 {
|
|
1886 var hash = location.hash;
|
|
1887
|
|
1888 if (slidenum > 0 && (hash == "" || hash == "#"))
|
|
1889 gotoSlide(0);
|
|
1890 else if (hash.length > 2 && hash != "#("+(slidenum+1)+")")
|
|
1891 {
|
|
1892 var num = parseInt(location.hash.substr(2));
|
|
1893
|
|
1894 if (!isNaN(num))
|
|
1895 gotoSlide(num-1);
|
|
1896 }
|
|
1897 }
|
|
1898
|
|
1899 // this doesn't push location onto history stack for IE
|
|
1900 // for which a hidden iframe hack is needed: load page into
|
|
1901 // the iframe with script that set's parent's location.hash
|
|
1902 // but that won't work for standalone use unless we can
|
|
1903 // create the page dynamically via a javascript: URL
|
|
1904 function setLocation()
|
|
1905 {
|
|
1906 var uri = pageAddress(location.href);
|
|
1907 var hash = "#(" + (slidenum+1) + ")";
|
|
1908
|
|
1909 if (slidenum >= 0)
|
|
1910 uri = uri + hash;
|
|
1911
|
|
1912 if (ie && !ie8)
|
|
1913 pushHash(hash);
|
|
1914
|
|
1915 if (uri != location.href /*&& !khtml */)
|
|
1916 location.href = uri;
|
|
1917
|
|
1918 if (khtml)
|
|
1919 hash = "(" + (slidenum+1) + ")";
|
|
1920
|
|
1921 if (!ie && location.hash != hash && location.hash != "")
|
|
1922 location.hash = hash;
|
|
1923
|
|
1924 document.title = title + " (" + (slidenum+1) + ")";
|
|
1925 showSlideNumber();
|
|
1926 }
|
|
1927
|
|
1928 // only used for IE6 and IE7
|
|
1929 function onFrameLoaded(hash)
|
|
1930 {
|
|
1931 location.hash = hash;
|
|
1932 var uri = pageAddress(location.href);
|
|
1933 location.href = uri + hash;
|
|
1934 }
|
|
1935
|
|
1936 // history hack with thanks to Bertrand Le Roy
|
|
1937 function pushHash(hash)
|
|
1938 {
|
|
1939 if (hash == "") hash = "#(1)";
|
|
1940 window.location.hash = hash;
|
|
1941 var doc = document.getElementById("historyFrame").contentWindow.document;
|
|
1942 doc.open("javascript:'<html></html>'");
|
|
1943 doc.write("<html><head><script type=\"text/javascript\">parent.onFrameLoaded('"+
|
|
1944 (hash) + "');</script></head><body>hello mum</body></html>");
|
|
1945 doc.close();
|
|
1946 }
|
|
1947
|
|
1948 // find current slide based upon location
|
|
1949 // first find target anchor and then look
|
|
1950 // for associated div element enclosing it
|
|
1951 // finally map that to slide number
|
|
1952 function findSlideNumber(uri)
|
|
1953 {
|
|
1954 // first get anchor from page location
|
|
1955
|
|
1956 var i = uri.indexOf("#");
|
|
1957
|
|
1958 // check if anchor is entire page
|
|
1959
|
|
1960 if (i < 0)
|
|
1961 return 0; // yes
|
|
1962
|
|
1963 var anchor = unescape(uri.substr(i+1));
|
|
1964
|
|
1965 // now use anchor as XML ID to find target
|
|
1966 var target = document.getElementById(anchor);
|
|
1967
|
|
1968 if (!target)
|
|
1969 {
|
|
1970 // does anchor look like "(2)" for slide 2 ??
|
|
1971 // where first slide is (1)
|
|
1972 var re = /\((\d)+\)/;
|
|
1973
|
|
1974 if (anchor.match(re))
|
|
1975 {
|
|
1976 var num = parseInt(anchor.substring(1, anchor.length-1));
|
|
1977
|
|
1978 if (num > slides.length)
|
|
1979 num = 1;
|
|
1980
|
|
1981 if (--num < 0)
|
|
1982 num = 0;
|
|
1983
|
|
1984 return num;
|
|
1985 }
|
|
1986
|
|
1987 // accept [2] for backwards compatibility
|
|
1988 re = /\[(\d)+\]/;
|
|
1989
|
|
1990 if (anchor.match(re))
|
|
1991 {
|
|
1992 var num = parseInt(anchor.substring(1, anchor.length-1));
|
|
1993
|
|
1994 if (num > slides.length)
|
|
1995 num = 1;
|
|
1996
|
|
1997 if (--num < 0)
|
|
1998 num = 0;
|
|
1999
|
|
2000 return num;
|
|
2001 }
|
|
2002
|
|
2003 // oh dear unknown anchor
|
|
2004 return 0;
|
|
2005 }
|
|
2006
|
|
2007 // search for enclosing slide
|
|
2008
|
|
2009 while (true)
|
|
2010 {
|
|
2011 // browser coerces html elements to uppercase!
|
|
2012 if (target.nodeName.toLowerCase() == "div" &&
|
|
2013 hasClass(target, "slide"))
|
|
2014 {
|
|
2015 // found the slide element
|
|
2016 break;
|
|
2017 }
|
|
2018
|
|
2019 // otherwise try parent element if any
|
|
2020
|
|
2021 target = target.parentNode;
|
|
2022
|
|
2023 if (!target)
|
|
2024 {
|
|
2025 return 0; // no luck!
|
|
2026 }
|
|
2027 };
|
|
2028
|
|
2029 for (i = 0; i < slides.length; ++i)
|
|
2030 {
|
|
2031 if (slides[i] == target)
|
|
2032 return i; // success
|
|
2033 }
|
|
2034
|
|
2035 // oh dear still no luck
|
|
2036 return 0;
|
|
2037 }
|
|
2038
|
|
2039 // find slide name from first h1 element
|
|
2040 // default to document title + slide number
|
|
2041 function slideName(index)
|
|
2042 {
|
|
2043 var name = null;
|
|
2044 var slide = slides[index];
|
|
2045
|
|
2046 var heading = findHeading(slide);
|
|
2047
|
|
2048 if (heading)
|
|
2049 name = extractText(heading);
|
|
2050
|
|
2051 if (!name)
|
|
2052 name = title + "(" + (index + 1) + ")";
|
|
2053
|
|
2054 name.replace(/\&/g, "&");
|
|
2055 name.replace(/\</g, "<");
|
|
2056 name.replace(/\>/g, ">");
|
|
2057
|
|
2058 return name;
|
|
2059 }
|
|
2060
|
|
2061 // find first h1 element in DOM tree
|
|
2062 function findHeading(node)
|
|
2063 { if (!node || node.nodeType != 1)
|
|
2064 return null;
|
|
2065
|
|
2066 if (node.nodeName == "H1" || node.nodeName == "h1")
|
|
2067 return node;
|
|
2068
|
|
2069 var child = node.firstChild;
|
|
2070
|
|
2071 while (child)
|
|
2072 {
|
|
2073 node = findHeading(child);
|
|
2074
|
|
2075 if (node)
|
|
2076 return node;
|
|
2077
|
|
2078 child = child.nextSibling;
|
|
2079 }
|
|
2080
|
|
2081 return null;
|
|
2082 }
|
|
2083
|
|
2084 // recursively extract text from DOM tree
|
|
2085 function extractText(node)
|
|
2086 {
|
|
2087 if (!node)
|
|
2088 return "";
|
|
2089
|
|
2090 // text nodes
|
|
2091 if (node.nodeType == 3)
|
|
2092 return node.nodeValue;
|
|
2093
|
|
2094 // elements
|
|
2095 if (node.nodeType == 1)
|
|
2096 {
|
|
2097 node = node.firstChild;
|
|
2098 var text = "";
|
|
2099
|
|
2100 while (node)
|
|
2101 {
|
|
2102 text = text + extractText(node);
|
|
2103 node = node.nextSibling;
|
|
2104 }
|
|
2105
|
|
2106 return text;
|
|
2107 }
|
|
2108
|
|
2109 return "";
|
|
2110 }
|
|
2111
|
|
2112
|
|
2113 // find copyright text from meta element
|
|
2114 function findCopyright()
|
|
2115 {
|
|
2116 var name, content;
|
|
2117 var meta = document.getElementsByTagName("meta");
|
|
2118
|
|
2119 for (var i = 0; i < meta.length; ++i)
|
|
2120 {
|
|
2121 name = meta[i].getAttribute("name");
|
|
2122 content = meta[i].getAttribute("content");
|
|
2123
|
|
2124 if (name == "copyright")
|
|
2125 return content;
|
|
2126 }
|
|
2127
|
|
2128 return null;
|
|
2129 }
|
|
2130
|
|
2131 function findSizeAdjust()
|
|
2132 {
|
|
2133 var name, content, offset;
|
|
2134 var meta = document.getElementsByTagName("meta");
|
|
2135
|
|
2136 for (var i = 0; i < meta.length; ++i)
|
|
2137 {
|
|
2138 name = meta[i].getAttribute("name");
|
|
2139 content = meta[i].getAttribute("content");
|
|
2140
|
|
2141 if (name == "font-size-adjustment")
|
|
2142 return 1 * content;
|
|
2143 }
|
|
2144
|
|
2145 return 1;
|
|
2146 }
|
|
2147
|
|
2148 function addToolbar()
|
|
2149 {
|
|
2150 var slideCounter, page;
|
|
2151
|
|
2152 var toolbar = createElement("div");
|
|
2153 toolbar.setAttribute("class", "toolbar");
|
|
2154
|
|
2155 if (ns_pos) // a reasonably behaved browser
|
|
2156 {
|
|
2157 var right = document.createElement("div");
|
|
2158 right.setAttribute("style", "float: right; text-align: right");
|
|
2159
|
|
2160 slideCounter = document.createElement("div")
|
|
2161 slideCounter.innerHTML = "slide".localize() + " n/m";
|
|
2162 right.appendChild(slideCounter);
|
|
2163 toolbar.appendChild(right);
|
|
2164
|
|
2165 var left = document.createElement("div");
|
|
2166 left.setAttribute("style", "text-align: left");
|
|
2167
|
|
2168 // global end of slide indicator
|
|
2169 eos = document.createElement("span");
|
|
2170 eos.innerHTML = "* ";
|
|
2171 left.appendChild(eos);
|
|
2172
|
|
2173 var help = document.createElement("a");
|
|
2174 help.setAttribute("href", helpPage);
|
|
2175 help.setAttribute("title", helpText.localize());
|
|
2176 help.innerHTML = "help?".localize();
|
|
2177 left.appendChild(help);
|
|
2178 helpAnchor = help; // save for focus hack
|
|
2179
|
|
2180 var gap1 = document.createTextNode(" ");
|
|
2181 left.appendChild(gap1);
|
|
2182
|
|
2183 var contents = document.createElement("a");
|
|
2184 contents.setAttribute("href", "javascript:toggleTableOfContents()");
|
|
2185 contents.setAttribute("title", "table of contents".localize());
|
|
2186 contents.innerHTML = "contents?".localize();
|
|
2187 left.appendChild(contents);
|
|
2188
|
|
2189 var gap2 = document.createTextNode(" ");
|
|
2190 left.appendChild(gap2);
|
|
2191
|
|
2192 var start = document.createElement("a");
|
|
2193 start.setAttribute("href", "javascript:firstSlide()");
|
|
2194 start.setAttribute("title", "restart presentation".localize());
|
|
2195 start.innerHTML = "restart?".localize();
|
|
2196 // start.setAttribute("href", "javascript:printSlides()");
|
|
2197 // start.setAttribute("title", "print all slides".localize());
|
|
2198 // start.innerHTML = "print!".localize();
|
|
2199 left.appendChild(start);
|
|
2200
|
|
2201 var copyright = findCopyright();
|
|
2202
|
|
2203 if (copyright)
|
|
2204 {
|
|
2205 var span = document.createElement("span");
|
|
2206 span.innerHTML = copyright;
|
|
2207 span.style.color = "black";
|
|
2208 span.style.marginLeft = "4em";
|
|
2209 left.appendChild(span);
|
|
2210 }
|
|
2211
|
|
2212 toolbar.appendChild(left);
|
|
2213 }
|
|
2214 else // IE so need to work around its poor CSS support
|
|
2215 {
|
|
2216 toolbar.style.position = (ie7 ? "fixed" : "absolute");
|
|
2217 toolbar.style.zIndex = "200";
|
|
2218 toolbar.style.width = "99.9%";
|
|
2219 toolbar.style.height = "1.2em";
|
|
2220 toolbar.style.top = "auto";
|
|
2221 toolbar.style.bottom = "0";
|
|
2222 toolbar.style.left = "0";
|
|
2223 toolbar.style.right = "0";
|
|
2224 toolbar.style.textAlign = "left";
|
|
2225 toolbar.style.fontSize = "60%";
|
|
2226 toolbar.style.color = "red";
|
|
2227 toolbar.borderWidth = 0;
|
|
2228 toolbar.style.background = "rgb(240,240,240)";
|
|
2229
|
|
2230 // would like to have help text left aligned
|
|
2231 // and page counter right aligned, floating
|
|
2232 // div's don't work, so instead use nested
|
|
2233 // absolutely positioned div's.
|
|
2234
|
|
2235 var sp = document.createElement("span");
|
|
2236 sp.innerHTML = " * ";
|
|
2237 toolbar.appendChild(sp);
|
|
2238 eos = sp; // end of slide indicator
|
|
2239
|
|
2240 var help = document.createElement("a");
|
|
2241 help.setAttribute("href", helpPage);
|
|
2242 help.setAttribute("title", helpText.localize());
|
|
2243 help.innerHTML = "help?".localize();
|
|
2244 toolbar.appendChild(help);
|
|
2245 helpAnchor = help; // save for focus hack
|
|
2246
|
|
2247 var gap1 = document.createTextNode(" ");
|
|
2248 toolbar.appendChild(gap1);
|
|
2249
|
|
2250 var contents = document.createElement("a");
|
|
2251 contents.setAttribute("href", "javascript:toggleTableOfContents()");
|
|
2252 contents.setAttribute("title", "table of contents".localize());
|
|
2253 contents.innerHTML = "contents?".localize();
|
|
2254 toolbar.appendChild(contents);
|
|
2255
|
|
2256 var gap2 = document.createTextNode(" ");
|
|
2257 toolbar.appendChild(gap2);
|
|
2258
|
|
2259 var start = document.createElement("a");
|
|
2260 start.setAttribute("href", "javascript:firstSlide()");
|
|
2261 start.setAttribute("title", "restart presentation".localize());
|
|
2262 start.innerHTML = "restart?".localize();
|
|
2263 // start.setAttribute("href", "javascript:printSlides()");
|
|
2264 // start.setAttribute("title", "print all slides".localize());
|
|
2265 // start.innerHTML = "print!".localize();
|
|
2266 toolbar.appendChild(start);
|
|
2267
|
|
2268 var copyright = findCopyright();
|
|
2269
|
|
2270 if (copyright)
|
|
2271 {
|
|
2272 var span = document.createElement("span");
|
|
2273 span.innerHTML = copyright;
|
|
2274 span.style.color = "black";
|
|
2275 span.style.marginLeft = "2em";
|
|
2276 toolbar.appendChild(span);
|
|
2277 }
|
|
2278
|
|
2279 slideCounter = document.createElement("div")
|
|
2280 slideCounter.style.position = "absolute";
|
|
2281 slideCounter.style.width = "auto"; //"20%";
|
|
2282 slideCounter.style.height = "1.2em";
|
|
2283 slideCounter.style.top = "auto";
|
|
2284 slideCounter.style.bottom = 0;
|
|
2285 slideCounter.style.right = "0";
|
|
2286 slideCounter.style.textAlign = "right";
|
|
2287 slideCounter.style.color = "red";
|
|
2288 slideCounter.style.background = "rgb(240,240,240)";
|
|
2289
|
|
2290 slideCounter.innerHTML = "slide".localize() + " n/m";
|
|
2291 toolbar.appendChild(slideCounter);
|
|
2292 }
|
|
2293
|
|
2294 // ensure that click isn't passed through to the page
|
|
2295 toolbar.onclick = stopPropagation;
|
|
2296 document.body.appendChild(toolbar);
|
|
2297 slideNumElement = slideCounter;
|
|
2298 setEosStatus(false);
|
|
2299
|
|
2300 return toolbar;
|
|
2301 }
|
|
2302
|
|
2303 function isShownToc()
|
|
2304 {
|
|
2305 if (toc && toc.style.visible == "visible")
|
|
2306 return true;
|
|
2307
|
|
2308 return false;
|
|
2309 }
|
|
2310
|
|
2311 function showTableOfContents()
|
|
2312 {
|
|
2313 if (toc)
|
|
2314 {
|
|
2315 if (toc.style.visibility != "visible")
|
|
2316 {
|
|
2317 toc.style.visibility = "visible";
|
|
2318 toc.style.display = "block";
|
|
2319 toc.focus();
|
|
2320
|
|
2321 if (ie7 && slidenum == 0)
|
|
2322 setTimeout("ieHack()", 100);
|
|
2323 }
|
|
2324 else
|
|
2325 hideTableOfContents();
|
|
2326 }
|
|
2327 }
|
|
2328
|
|
2329 function hideTableOfContents()
|
|
2330 {
|
|
2331 if (toc && toc.style.visibility != "hidden")
|
|
2332 {
|
|
2333 toc.style.visibility = "hidden";
|
|
2334 toc.style.display = "none";
|
|
2335
|
|
2336 try
|
|
2337 {
|
|
2338 if (!opera)
|
|
2339 helpAnchor.focus();
|
|
2340 }
|
|
2341 catch (e)
|
|
2342 {
|
|
2343 }
|
|
2344 }
|
|
2345 }
|
|
2346
|
|
2347 function toggleTableOfContents()
|
|
2348 {
|
|
2349 if (toc)
|
|
2350 {
|
|
2351 if (toc.style.visible != "visible")
|
|
2352 showTableOfContents();
|
|
2353 else
|
|
2354 hideTableOfContents();
|
|
2355 }
|
|
2356 }
|
|
2357
|
|
2358 // called on clicking toc entry
|
|
2359 function gotoEntry(e)
|
|
2360 {
|
|
2361 var target;
|
|
2362
|
|
2363 if (!e)
|
|
2364 var e = window.event;
|
|
2365
|
|
2366 if (e.target)
|
|
2367 target = e.target;
|
|
2368 else if (e.srcElement)
|
|
2369 target = e.srcElement;
|
|
2370
|
|
2371 // work around Safari bug
|
|
2372 if (target.nodeType == 3)
|
|
2373 target = target.parentNode;
|
|
2374
|
|
2375 if (target && target.nodeType == 1)
|
|
2376 {
|
|
2377 var uri = target.getAttribute("href");
|
|
2378
|
|
2379 if (uri)
|
|
2380 {
|
|
2381 //alert("going to " + uri);
|
|
2382 var slide = slides[slidenum];
|
|
2383 hideSlide(slide);
|
|
2384 slidenum = findSlideNumber(uri);
|
|
2385 slide = slides[slidenum];
|
|
2386 lastShown = null;
|
|
2387 setLocation();
|
|
2388 setVisibilityAllIncremental("hidden");
|
|
2389 setEosStatus(!nextIncrementalItem(lastShown));
|
|
2390 showSlide(slide);
|
|
2391 //target.focus();
|
|
2392
|
|
2393 try
|
|
2394 {
|
|
2395 if (!opera)
|
|
2396 helpAnchor.focus();
|
|
2397 }
|
|
2398 catch (e)
|
|
2399 {
|
|
2400 }
|
|
2401 }
|
|
2402 }
|
|
2403
|
|
2404 hideTableOfContents(e);
|
|
2405 if (ie7) ieHack();
|
|
2406 stopPropagation(e);
|
|
2407 return cancel(e);
|
|
2408 }
|
|
2409
|
|
2410 // called onkeydown for toc entry
|
|
2411 function gotoTocEntry(event)
|
|
2412 {
|
|
2413 var key;
|
|
2414
|
|
2415 if (!event)
|
|
2416 var event = window.event;
|
|
2417
|
|
2418 // kludge around NS/IE differences
|
|
2419 if (window.event)
|
|
2420 key = window.event.keyCode;
|
|
2421 else if (event.which)
|
|
2422 key = event.which;
|
|
2423 else
|
|
2424 return true; // Yikes! unknown browser
|
|
2425
|
|
2426 // ignore event if key value is zero
|
|
2427 // as for alt on Opera and Konqueror
|
|
2428 if (!key)
|
|
2429 return true;
|
|
2430
|
|
2431 // check for concurrent control/command/alt key
|
|
2432 // but are these only present on mouse events?
|
|
2433
|
|
2434 if (event.ctrlKey || event.altKey)
|
|
2435 return true;
|
|
2436
|
|
2437 if (key == 13)
|
|
2438 {
|
|
2439 var uri = this.getAttribute("href");
|
|
2440
|
|
2441 if (uri)
|
|
2442 {
|
|
2443 //alert("going to " + uri);
|
|
2444 var slide = slides[slidenum];
|
|
2445 hideSlide(slide);
|
|
2446 slidenum = findSlideNumber(uri);
|
|
2447 slide = slides[slidenum];
|
|
2448 lastShown = null;
|
|
2449 setLocation();
|
|
2450 setVisibilityAllIncremental("hidden");
|
|
2451 setEosStatus(!nextIncrementalItem(lastShown));
|
|
2452 showSlide(slide);
|
|
2453 //target.focus();
|
|
2454
|
|
2455 try
|
|
2456 {
|
|
2457 if (!opera)
|
|
2458 helpAnchor.focus();
|
|
2459 }
|
|
2460 catch (e)
|
|
2461 {
|
|
2462 }
|
|
2463 }
|
|
2464
|
|
2465 hideTableOfContents();
|
|
2466 if (ie7) ieHack();
|
|
2467 return cancel(event);
|
|
2468 }
|
|
2469
|
|
2470 if (key == 40 && this.next)
|
|
2471 {
|
|
2472 this.next.focus();
|
|
2473 return cancel(event);
|
|
2474 }
|
|
2475
|
|
2476 if (key == 38 && this.previous)
|
|
2477 {
|
|
2478 this.previous.focus();
|
|
2479 return cancel(event);
|
|
2480 }
|
|
2481
|
|
2482 return true;
|
|
2483 }
|
|
2484
|
|
2485 function isTitleSlide(slide)
|
|
2486 {
|
|
2487 return hasClass(slide, "title");
|
|
2488 }
|
|
2489
|
|
2490 // create div element with links to each slide
|
|
2491 function tableOfContents()
|
|
2492 {
|
|
2493 var toc = document.createElement("div");
|
|
2494 addClass(toc, "toc");
|
|
2495 //toc.setAttribute("tabindex", "0");
|
|
2496
|
|
2497 var heading = document.createElement("div");
|
|
2498 addClass(heading, "toc-heading");
|
|
2499 heading.innerHTML = "Table of Contents".localize();
|
|
2500
|
|
2501 heading.style.textAlign = "center";
|
|
2502 heading.style.width = "100%";
|
|
2503 heading.style.margin = "0";
|
|
2504 heading.style.marginBottom = "1em";
|
|
2505 heading.style.borderBottomStyle = "solid";
|
|
2506 heading.style.borderBottomColor = "rgb(180,180,180)";
|
|
2507 heading.style.borderBottomWidth = "1px";
|
|
2508
|
|
2509 toc.appendChild(heading);
|
|
2510 var previous = null;
|
|
2511
|
|
2512 for (var i = 0; i < slides.length; ++i)
|
|
2513 {
|
|
2514 var title = hasClass(slides[i], "title");
|
|
2515 var num = document.createTextNode((i + 1) + ". ");
|
|
2516
|
|
2517 toc.appendChild(num);
|
|
2518
|
|
2519 var a = document.createElement("a");
|
|
2520 a.setAttribute("href", "#(" + (i+1) + ")");
|
|
2521
|
|
2522 if (title)
|
|
2523 addClass(a, "titleslide");
|
|
2524
|
|
2525 var name = document.createTextNode(slideName(i));
|
|
2526 a.appendChild(name);
|
|
2527 a.onclick = gotoEntry;
|
|
2528 a.onkeydown = gotoTocEntry;
|
|
2529 a.previous = previous;
|
|
2530
|
|
2531 if (previous)
|
|
2532 previous.next = a;
|
|
2533
|
|
2534 toc.appendChild(a);
|
|
2535
|
|
2536 if (i == 0)
|
|
2537 toc.first = a;
|
|
2538
|
|
2539 if (i < slides.length - 1)
|
|
2540 {
|
|
2541 var br = document.createElement("br");
|
|
2542 toc.appendChild(br);
|
|
2543 }
|
|
2544
|
|
2545 previous = a;
|
|
2546 }
|
|
2547
|
|
2548 toc.focus = function () {
|
|
2549 if (this.first)
|
|
2550 this.first.focus();
|
|
2551 }
|
|
2552
|
|
2553 toc.onmouseup = mouseButtonUp;
|
|
2554
|
|
2555 toc.onclick = function (e) {
|
|
2556 e||(e=window.event);
|
|
2557
|
|
2558 if (selectedTextLen <= 0)
|
|
2559 hideTableOfContents();
|
|
2560
|
|
2561 stopPropagation(e);
|
|
2562
|
|
2563 if (e.cancel != undefined)
|
|
2564 e.cancel = true;
|
|
2565
|
|
2566 if (e.returnValue != undefined)
|
|
2567 e.returnValue = false;
|
|
2568
|
|
2569 return false;
|
|
2570 };
|
|
2571
|
|
2572 toc.style.position = "absolute";
|
|
2573 toc.style.zIndex = "300";
|
|
2574 toc.style.width = "60%";
|
|
2575 toc.style.maxWidth = "30em";
|
|
2576 toc.style.height = "30em";
|
|
2577 toc.style.overflow = "auto";
|
|
2578 toc.style.top = "auto";
|
|
2579 toc.style.right = "auto";
|
|
2580 toc.style.left = "4em";
|
|
2581 toc.style.bottom = "4em";
|
|
2582 toc.style.padding = "1em";
|
|
2583 toc.style.background = "rgb(240,240,240)";
|
|
2584 toc.style.borderStyle = "solid";
|
|
2585 toc.style.borderWidth = "2px";
|
|
2586 toc.style.fontSize = "60%";
|
|
2587
|
|
2588 document.body.insertBefore(toc, document.body.firstChild);
|
|
2589 return toc;
|
|
2590 }
|
|
2591
|
|
2592 function replaceByNonBreakingSpace(str)
|
|
2593 {
|
|
2594 for (var i = 0; i < str.length; ++i)
|
|
2595 str[i] = 160;
|
|
2596 }
|
|
2597
|
|
2598
|
|
2599 function initOutliner()
|
|
2600 {
|
|
2601 var items = document.getElementsByTagName("LI");
|
|
2602
|
|
2603 for (var i = 0; i < items.length; ++i)
|
|
2604 {
|
|
2605 var target = items[i];
|
|
2606
|
|
2607 if (!hasClass(target.parentNode, "outline"))
|
|
2608 continue;
|
|
2609
|
|
2610 target.onclick = outlineClick;
|
|
2611
|
|
2612 if (!ns_pos)
|
|
2613 {
|
|
2614 target.onmouseover = hoverOutline;
|
|
2615 target.onmouseout = unhoverOutline;
|
|
2616 }
|
|
2617
|
|
2618 if (foldable(target))
|
|
2619 {
|
|
2620 target.foldable = true;
|
|
2621 target.onfocus = function () {outline = this;};
|
|
2622 target.onblur = function () {outline = null;};
|
|
2623
|
|
2624 if (!target.getAttribute("tabindex"))
|
|
2625 target.setAttribute("tabindex", "0");
|
|
2626
|
|
2627 if (hasClass(target, "expand"))
|
|
2628 unfold(target);
|
|
2629 else
|
|
2630 fold(target);
|
|
2631 }
|
|
2632 else
|
|
2633 {
|
|
2634 addClass(target, "nofold");
|
|
2635 target.visible = true;
|
|
2636 target.foldable = false;
|
|
2637 }
|
|
2638 }
|
|
2639 }
|
|
2640
|
|
2641 function foldable(item)
|
|
2642 {
|
|
2643 if (!item || item.nodeType != 1)
|
|
2644 return false;
|
|
2645
|
|
2646 var node = item.firstChild;
|
|
2647
|
|
2648 while (node)
|
|
2649 {
|
|
2650 if (node.nodeType == 1 && isBlock(node))
|
|
2651 return true;
|
|
2652
|
|
2653 node = node.nextSibling;
|
|
2654 }
|
|
2655
|
|
2656 return false;
|
|
2657 }
|
|
2658
|
|
2659 function fold(item)
|
|
2660 {
|
|
2661 if (item)
|
|
2662 {
|
|
2663 removeClass(item, "unfolded");
|
|
2664 addClass(item, "folded");
|
|
2665 }
|
|
2666
|
|
2667 var node = item ? item.firstChild : null;
|
|
2668
|
|
2669 while (node)
|
|
2670 {
|
|
2671 if (node.nodeType == 1 && isBlock(node)) // element
|
|
2672 {
|
|
2673 // note that getElementStyle won't work for Safari 1.3
|
|
2674 node.display = getElementStyle(node, "display", "display");
|
|
2675 node.style.display = "none";
|
|
2676 node.style.visibility = "hidden";
|
|
2677 }
|
|
2678
|
|
2679 node = node.nextSibling;
|
|
2680 }
|
|
2681
|
|
2682 item.visible = false;
|
|
2683 }
|
|
2684
|
|
2685 function unfold(item)
|
|
2686 {
|
|
2687 if (item)
|
|
2688 {
|
|
2689 addClass(item, "unfolded");
|
|
2690 removeClass(item, "folded");
|
|
2691 }
|
|
2692
|
|
2693 var node = item ? item.firstChild : null;
|
|
2694
|
|
2695 while (node)
|
|
2696 {
|
|
2697 if (node.nodeType == 1 && isBlock(node)) // element
|
|
2698 {
|
|
2699 // with fallback for Safari, see above
|
|
2700 node.style.display = (node.display ? node.display : "block");
|
|
2701 node.style.visibility = "visible";
|
|
2702 }
|
|
2703
|
|
2704 node = node.nextSibling;
|
|
2705 }
|
|
2706
|
|
2707 item.visible = true;
|
|
2708 }
|
|
2709
|
|
2710 function outlineClick(e)
|
|
2711 {
|
|
2712 var rightclick = false;
|
|
2713 var target;
|
|
2714
|
|
2715 if (!e)
|
|
2716 var e = window.event;
|
|
2717
|
|
2718 if (e.target)
|
|
2719 target = e.target;
|
|
2720 else if (e.srcElement)
|
|
2721 target = e.srcElement;
|
|
2722
|
|
2723 // work around Safari bug
|
|
2724 if (target.nodeType == 3)
|
|
2725 target = target.parentNode;
|
|
2726
|
|
2727 while (target && target.visible == undefined)
|
|
2728 target = target.parentNode;
|
|
2729
|
|
2730 if (!target)
|
|
2731 return true;
|
|
2732
|
|
2733 if (e.which)
|
|
2734 rightclick = (e.which == 3);
|
|
2735 else if (e.button)
|
|
2736 rightclick = (e.button == 2);
|
|
2737
|
|
2738 if (!rightclick && target.visible != undefined)
|
|
2739 {
|
|
2740 if (target.foldable)
|
|
2741 {
|
|
2742 if (target.visible)
|
|
2743 fold(target);
|
|
2744 else
|
|
2745 unfold(target);
|
|
2746 }
|
|
2747
|
|
2748 stopPropagation(e);
|
|
2749 e.cancel = true;
|
|
2750 e.returnValue = false;
|
|
2751 }
|
|
2752
|
|
2753 return false;
|
|
2754 }
|
|
2755
|
|
2756 function hoverOutline(e)
|
|
2757 {
|
|
2758 var target;
|
|
2759
|
|
2760 if (!e)
|
|
2761 var e = window.event;
|
|
2762
|
|
2763 if (e.target)
|
|
2764 target = e.target;
|
|
2765 else if (e.srcElement)
|
|
2766 target = e.srcElement;
|
|
2767
|
|
2768 // work around Safari bug
|
|
2769 if (target.nodeType == 3)
|
|
2770 target = target.parentNode;
|
|
2771
|
|
2772 while (target && target.visible == undefined)
|
|
2773 target = target.parentNode;
|
|
2774
|
|
2775 if (target && target.foldable)
|
|
2776 target.style.cursor = "pointer";
|
|
2777
|
|
2778 return true;
|
|
2779 }
|
|
2780
|
|
2781 function unhoverOutline(e)
|
|
2782 {
|
|
2783 var target;
|
|
2784
|
|
2785 if (!e)
|
|
2786 var e = window.event;
|
|
2787
|
|
2788 if (e.target)
|
|
2789 target = e.target;
|
|
2790 else if (e.srcElement)
|
|
2791 target = e.srcElement;
|
|
2792
|
|
2793 // work around Safari bug
|
|
2794 if (target.nodeType == 3)
|
|
2795 target = target.parentNode;
|
|
2796
|
|
2797 while (target && target.visible == undefined)
|
|
2798 target = target.parentNode;
|
|
2799
|
|
2800 if (target)
|
|
2801 target.style.cursor = "default";
|
|
2802
|
|
2803 return true;
|
|
2804 }
|
|
2805
|
|
2806
|
|
2807 function stopPropagation(e)
|
|
2808 {
|
|
2809 if (window.event)
|
|
2810 {
|
|
2811 window.event.cancelBubble = true;
|
|
2812 //window.event.returnValue = false;
|
|
2813 }
|
|
2814 else if (e)
|
|
2815 {
|
|
2816 e.cancelBubble = true;
|
|
2817 e.stopPropagation();
|
|
2818 //e.preventDefault();
|
|
2819 }
|
|
2820 }
|
|
2821
|
|
2822 /* can't rely on display since we set that to none to hide things */
|
|
2823 function isBlock(elem)
|
|
2824 {
|
|
2825 var tag = elem.nodeName;
|
|
2826
|
|
2827 return tag == "OL" || tag == "UL" || tag == "P" ||
|
|
2828 tag == "LI" || tag == "TABLE" || tag == "PRE" ||
|
|
2829 tag == "H1" || tag == "H2" || tag == "H3" ||
|
|
2830 tag == "H4" || tag == "H5" || tag == "H6" ||
|
|
2831 tag == "BLOCKQUOTE" || tag == "ADDRESS";
|
|
2832 }
|
|
2833
|
|
2834 function getElementStyle(elem, IEStyleProp, CSSStyleProp)
|
|
2835 {
|
|
2836 if (elem.currentStyle)
|
|
2837 {
|
|
2838 return elem.currentStyle[IEStyleProp];
|
|
2839 }
|
|
2840 else if (window.getComputedStyle)
|
|
2841 {
|
|
2842 var compStyle = window.getComputedStyle(elem, "");
|
|
2843 return compStyle.getPropertyValue(CSSStyleProp);
|
|
2844 }
|
|
2845 return "";
|
|
2846 }
|
|
2847
|
|
2848 // works with text/html and text/xhtml+xml with thanks to Simon Willison
|
|
2849 function createElement(element)
|
|
2850 {
|
|
2851 if (typeof document.createElementNS != 'undefined')
|
|
2852 {
|
|
2853 return document.createElementNS('http://www.w3.org/1999/xhtml', element);
|
|
2854 }
|
|
2855
|
|
2856 if (typeof document.createElement != 'undefined')
|
|
2857 {
|
|
2858 return document.createElement(element);
|
|
2859 }
|
|
2860
|
|
2861 return false;
|
|
2862 }
|
|
2863
|
|
2864 // designed to work with both text/html and text/xhtml+xml
|
|
2865 function getElementsByTagName(name)
|
|
2866 {
|
|
2867 if (typeof document.getElementsByTagNameNS != 'undefined')
|
|
2868 {
|
|
2869 return document.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', name);
|
|
2870 }
|
|
2871
|
|
2872 if (typeof document.getElementsByTagName != 'undefined')
|
|
2873 {
|
|
2874 return document.getElementsByTagName(name);
|
|
2875 }
|
|
2876
|
|
2877 return null;
|
|
2878 }
|
|
2879
|
|
2880 /*
|
|
2881 // clean alternative to innerHTML method, but on IE6
|
|
2882 // it doesn't work with named entities like
|
|
2883 // which need to be replaced by numeric entities
|
|
2884 function insertText(element, text)
|
|
2885 {
|
|
2886 try
|
|
2887 {
|
|
2888 element.textContent = text; // DOM3 only
|
|
2889 }
|
|
2890 catch (e)
|
|
2891 {
|
|
2892 if (element.firstChild)
|
|
2893 {
|
|
2894 // remove current children
|
|
2895 while (element.firstChild)
|
|
2896 element.removeChild(element.firstChild);
|
|
2897 }
|
|
2898
|
|
2899 element.appendChild(document.createTextNode(text));
|
|
2900 }
|
|
2901 }
|
|
2902
|
|
2903 // as above, but as method of all element nodes
|
|
2904 // doesn't work in IE6 which doesn't allow you to
|
|
2905 // add methods to the HTMLElement prototype
|
|
2906 if (HTMLElement != undefined)
|
|
2907 {
|
|
2908 HTMLElement.prototype.insertText = function(text) {
|
|
2909 var element = this;
|
|
2910
|
|
2911 try
|
|
2912 {
|
|
2913 element.textContent = text; // DOM3 only
|
|
2914 }
|
|
2915 catch (e)
|
|
2916 {
|
|
2917 if (element.firstChild)
|
|
2918 {
|
|
2919 // remove current children
|
|
2920 while (element.firstChild)
|
|
2921 element.removeChild(element.firstChild);
|
|
2922 }
|
|
2923
|
|
2924 element.appendChild(document.createTextNode(text));
|
|
2925 }
|
|
2926 };
|
|
2927 }
|
|
2928 */
|
|
2929
|
|
2930 function getSelectedText()
|
|
2931 {
|
|
2932 try
|
|
2933 {
|
|
2934 if (window.getSelection)
|
|
2935 return window.getSelection().toString();
|
|
2936
|
|
2937 if (document.getSelection)
|
|
2938 return document.getSelection().toString();
|
|
2939
|
|
2940 if (document.selection)
|
|
2941 return document.selection.createRange().text;
|
|
2942 }
|
|
2943 catch (e)
|
|
2944 {
|
|
2945 return "";
|
|
2946 }
|
|
2947 return "";
|
|
2948 }
|
|
2949
|