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