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