ulmul 0.1.0

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