| /* http://www.w3.org/Talks/Tools/Slidy/slidy.js |
| |
| Copyright (c) 2005 W3C (MIT, ERCIM, Keio), All Rights Reserved. |
| W3C liability, trademark, document use and software licensing |
| rules apply, see: |
| |
| http://www.w3.org/Consortium/Legal/copyright-documents |
| http://www.w3.org/Consortium/Legal/copyright-software |
| */ |
| |
| var ns_pos = (typeof window.pageYOffset!='undefined'); |
| var khtml = ((navigator.userAgent).indexOf("KHTML") >= 0 ? true : false); |
| var opera = ((navigator.userAgent).indexOf("Opera") >= 0 ? true : false); |
| var ie7 = (!ns_pos && navigator.userAgent.indexOf("MSIE 7") != -1); |
| |
| window.onload = startup; // equivalent to onload on body element |
| |
| // IE only event handlers to ensure all slides are printed |
| // I don't yet know how to emulate these for other browsers |
| window.onbeforeprint = beforePrint; |
| window.onafterprint = afterPrint; |
| |
| // hack to hide slides while loading |
| setTimeout(hideAll, 50); |
| |
| function hideAll() |
| { |
| if (document.body) |
| document.body.style.visibility = "hidden"; |
| else |
| setTimeout(hideAll, 50); |
| } |
| |
| var slidenum = 0; // integer slide count: 0, 1, 2, ... |
| var slides; // set to array of slide div's |
| var slideNumElement; // element containing slide number |
| var notes; // set to array of handout div's |
| var backgrounds; // set to array of background div's |
| var toolbar; // element containing toolbar |
| var title; // document title |
| var lastShown = null; // last incrementally shown item |
| var eos = null; // span element for end of slide indicator |
| var toc = null; // table of contents |
| var outline = null; // outline element with the focus |
| var selectedTextLen; // length of drag selection on document |
| |
| var viewAll = 0; // 1 to view all slides + handouts |
| var wantToolbar = 1; // 0 if toolbar isn't wanted |
| var mouseClickEnabled = true; // enables left click for next slide |
| var scrollhack = 0; // IE work around for position: fixed |
| |
| var helpAnchor; // used for keyboard focus hack in showToolbar() |
| var helpPage = "http://www.w3.org/Talks/Tools/Slidy/help.html"; |
| var helpText = "Navigate with mouse click, space bar, Cursor Left/Right, " + |
| "or Pg Up and Pg Dn. Use S and B to change font size."; |
| |
| var sizeIndex = 0; |
| var sizeAdjustment = 0; |
| var sizes = new Array("10pt", "12pt", "14pt", "16pt", "18pt", "20pt", |
| "22pt", "24pt", "26pt", "28pt", "30pt", "32pt"); |
| |
| var okayForIncremental = incrementalElementList(); |
| |
| // needed for efficient resizing |
| var lastWidth = 0; |
| var lastHeight = 0; |
| |
| // Needed for cross browser support for relative width/height on |
| // object elements. The work around is to save width/height attributes |
| // and then to recompute absolute width/height dimensions on resizing |
| var objects; |
| |
| // updated to language specified by html file |
| var lang = "en"; |
| |
| //var localize = {}; |
| |
| // for each language there is an associative array |
| var strings_es = { |
| "slide":"pág.", |
| "help?":"Ayuda", |
| "contents?":"Índice", |
| "table of contents":"tabla de contenidos", |
| "Table of Contents":"Tabla de Contenidos", |
| "restart presentation":"Reiniciar presentación", |
| "restart?":"Inicio" |
| }; |
| |
| strings_es[helpText] = |
| "Utilice el ratón, barra espaciadora, teclas Izda/Dhca, " + |
| "o Re pág y Av pág. Use S y B para cambiar el tamaño de fuente."; |
| |
| var strings_nl = { |
| "slide":"pagina", |
| "help?":"Help?", |
| "contents?":"Inhoud?", |
| "table of contents":"inhoudsopgave", |
| "Table of Contents":"Inhoudsopgave", |
| "restart presentation":"herstart presentatie", |
| "restart?":"Herstart?" |
| }; |
| |
| strings_nl[helpText] = |
| "Navigeer d.m.v. het muis, spatiebar, Links/Rechts toetsen, " + |
| "of PgUp en PgDn. Gebruik S en B om de karaktergrootte te veranderen."; |
| |
| var strings_de = { |
| "slide":"Seite", |
| "help?":"Hilfe", |
| "contents?":"Übersicht", |
| "table of contents":"Inhaltsverzeichnis", |
| "Table of Contents":"Inhaltsverzeichnis", |
| "restart presentation":"Präsentation neu starten", |
| "restart?":"Neustart" |
| }; |
| |
| strings_de[helpText] = |
| "Benutzen Sie die Maus, Leerschlag, die Cursortasten links/rechts" + |
| "oder Page up/Page Down zum Wechseln der Seiten und S und B für die Schriftgrösse."; |
| |
| var strings_pl = { |
| "slide":"slajd", |
| "help?":"pomoc?", |
| "contents?":"spis treści?", |
| "table of contents":"spis treści", |
| "Table of Contents":"Spis Treści", |
| "restart presentation":"Restartuj prezentację", |
| "restart?":"restart?" |
| }; |
| |
| strings_pl[helpText] = |
| "Zmieniaj slajdy klikając myszą, naciskając spację, strzałki lewo/prawo" + |
| "lub PgUp / PgDn. Użyj klawiszy S i B, aby zmienić rozmiar czczionki."; |
| |
| var strings_fr = { |
| "slide":"page", |
| "help?":"Aide", |
| "contents?":"Index", |
| "table of contents":"table des matières", |
| "Table of Contents":"Table des matières", |
| "restart presentation":"Recommencer l'exposé", |
| "restart?":"Début" |
| }; |
| |
| strings_fr[helpText] = |
| "Naviguez avec la souris, la barre d'espace, les flèches" + |
| "gauche/droite ou les touches Pg Up, Pg Dn. Utilisez " + |
| "les touches S et B pour modifier la taille de la police."; |
| |
| var strings_hu = { |
| "slide":"oldal", |
| "help?":"segítség", |
| "contents?":"tartalom", |
| "table of contents":"tartalomjegyzék", |
| "Table of Contents":"Tartalomjegyzék", |
| "restart presentation":"bemutató újraindítása", |
| "restart?":"újraindítás" |
| }; |
| |
| strings_hu[helpText] = |
| "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, " + |
| "illetve a Page Down, Page Up billentyűket. Az S és a B billentyűkkel változtathatja a szöveg méretét."; |
| |
| var strings_it = { |
| "slide":"pag.", |
| "help?":"Aiuto", |
| "contents?":"Indice", |
| "table of contents":"indice", |
| "Table of Contents":"Indice", |
| "restart presentation":"Ricominciare la presentazione", |
| "restart?":"Inizio" |
| }; |
| |
| strings_it[helpText] = |
| "Navigare con mouse, barra spazio, frecce sinistra/destra o " + |
| "PgUp e PgDn. Usare S e B per cambiare la dimensione dei caratteri."; |
| |
| var strings_el = { |
| "slide":"σελίδα", |
| "help?":"βοήθεια;", |
| "contents?":"περιεχόμενα;", |
| "table of contents":"πίνακας περιεχομένων", |
| "Table of Contents":"Πίνακας Περιεχομένων", |
| "restart presentation":"επανεκκίνηση παρουσίασης", |
| "restart?":"επανεκκίνηση;" |
| }; |
| |
| strings_el[helpText] = |
| "Πλοηγηθείτε με το κλίκ του ποντικιού, το space, τα βέλη αριστερά/δεξιά, " + |
| "ή Page Up και Page Down. Χρησιμοποιήστε τα πλήκτρα S και B για να αλλάξετε " + |
| "το μέγεθος της γραμματοσειράς."; |
| |
| var strings_ja = { |
| "slide":"スライド", |
| "help?":"ヘルプ", |
| "contents?":"目次", |
| "table of contents":"目次を表示", |
| "Table of Contents":"目次", |
| "restart presentation":"最初から再生", |
| "restart?":"最初から" |
| }; |
| |
| strings_ja[helpText] = |
| "マウス左クリック ・ スペース ・ 左右キー " + |
| "または Page Up ・ Page Downで操作, S ・ Bでフォントサイズ変更"; |
| |
| |
| // each such language array is declared in the localize array |
| // used indirectly as in help.innerHTML = "help".localize(); |
| var localize = { |
| "es":strings_es, |
| "nl":strings_nl, |
| "de":strings_de, |
| "pl":strings_pl, |
| "fr":strings_fr, |
| "hu":strings_hu, |
| "it":strings_it, |
| "el":strings_el, |
| "jp":strings_ja |
| }; |
| |
| /* general initialization */ |
| function startup() |
| { |
| // find human language from html element |
| // for use in localizing strings |
| lang = document.body.parentNode.getAttribute("lang"); |
| |
| if (!lang) |
| lang = document.body.parentNode.getAttribute("xml:lang"); |
| |
| if (!lang) |
| lang = "en"; |
| |
| document.body.style.visibility = "visible"; |
| title = document.title; |
| toolbar = addToolbar(); |
| wrapImplicitSlides(); |
| slides = collectSlides(); |
| notes = collectNotes(); |
| objects = document.body.getElementsByTagName("object"); |
| backgrounds = collectBackgrounds(); |
| patchAnchors(); |
| |
| slidenum = findSlideNumber(location.href); |
| window.offscreenbuffering = true; |
| sizeAdjustment = findSizeAdjust(); |
| hideImageToolbar(); // suppress IE image toolbar popup |
| initOutliner(); // activate fold/unfold support |
| |
| if (slides.length > 0) |
| { |
| var slide = slides[slidenum]; |
| slide.style.position = "absolute"; |
| |
| if (slidenum > 0) |
| { |
| setVisibilityAllIncremental("visible"); |
| lastShown = previousIncrementalItem(null); |
| setEosStatus(true); |
| } |
| else |
| { |
| lastShown = null; |
| setVisibilityAllIncremental("hidden"); |
| setEosStatus(!nextIncrementalItem(lastShown)); |
| } |
| |
| setLocation(); |
| } |
| |
| toc = tableOfContents(); |
| hideTableOfContents(); |
| |
| // bind event handlers |
| document.onclick = mouseButtonClick; |
| document.onmouseup = mouseButtonUp; |
| document.onkeydown = keyDown; |
| window.onresize = resized; |
| window.onscroll = scrolled; |
| singleSlideView(); |
| |
| setLocation(); |
| resized(); |
| |
| if (ie7) |
| setTimeout("ieHack()", 100); |
| |
| showToolbar(); |
| } |
| |
| // add localize method to all strings for use |
| // as in help.innerHTML = "help".localize(); |
| String.prototype.localize = function() |
| { |
| if (this == "") |
| return this; |
| |
| // try full language code, e.g. en-US |
| var s, lookup = localize[lang]; |
| |
| if (lookup) |
| { |
| s = lookup[this]; |
| |
| if (s) |
| return s; |
| } |
| |
| // try en if undefined for en-US |
| var lg = lang.split("-"); |
| |
| if (lg.length > 1) |
| { |
| lookup = localize[lg[0]]; |
| |
| if (lookup) |
| { |
| s = lookup[this]; |
| |
| if (s) |
| return s; |
| } |
| } |
| |
| // otherwise string as is |
| return this; |
| } |
| |
| // suppress IE's image toolbar pop up |
| function hideImageToolbar() |
| { |
| if (!ns_pos) |
| { |
| var images = document.getElementsByTagName("IMG"); |
| |
| for (var i = 0; i < images.length; ++i) |
| images[i].setAttribute("galleryimg", "no"); |
| } |
| } |
| |
| // hack to persuade IE to compute correct document height |
| // as needed for simulating fixed positioning of toolbar |
| function ieHack() |
| { |
| window.resizeBy(0,-1); |
| window.resizeBy(0, 1); |
| } |
| |
| // Firefox reload SVG bug work around |
| function reload(e) |
| { |
| if (!e) |
| var e = window.event; |
| |
| hideBackgrounds(); |
| setTimeout("document.reload();", 100); |
| |
| stopPropagation(e); |
| e.cancel = true; |
| e.returnValue = false; |
| |
| return false; |
| } |
| |
| // Safari and Konqueror don't yet support getComputedStyle() |
| // and they always reload page when location.href is updated |
| function isKHTML() |
| { |
| var agent = navigator.userAgent; |
| return (agent.indexOf("KHTML") >= 0 ? true : false); |
| } |
| |
| function resized() |
| { |
| var width = 0; |
| |
| if ( typeof( window.innerWidth ) == 'number' ) |
| width = window.innerWidth; // Non IE browser |
| else if (document.documentElement && document.documentElement.clientWidth) |
| width = document.documentElement.clientWidth; // IE6 |
| else if (document.body && document.body.clientWidth) |
| width = document.body.clientWidth; // IE4 |
| |
| var height = 0; |
| |
| if ( typeof( window.innerHeight ) == 'number' ) |
| height = window.innerHeight; // Non IE browser |
| else if (document.documentElement && document.documentElement.clientHeight) |
| height = document.documentElement.clientHeight; // IE6 |
| else if (document.body && document.body.clientHeight) |
| height = document.body.clientHeight; // IE4 |
| |
| if (height && (width/height > 1.05*1024/768)) |
| { |
| width = height * 1024.0/768; |
| } |
| |
| // IE fires onresize even when only font size is changed! |
| // so we do a check to avoid blocking < and > actions |
| if (width != lastWidth || height != lastHeight) |
| { |
| if (width >= 1100) |
| sizeIndex = 5; // 4 |
| else if (width >= 1000) |
| sizeIndex = 4; // 3 |
| else if (width >= 800) |
| sizeIndex = 3; // 2 |
| else if (width >= 600) |
| sizeIndex = 2; // 1 |
| else if (width) |
| sizeIndex = 0; |
| |
| // add in font size adjustment from meta element e.g. |
| // <meta name="font-size-adjustment" content="-2" /> |
| // useful when slides have too much content ;-) |
| |
| if (0 <= sizeIndex + sizeAdjustment && |
| sizeIndex + sizeAdjustment < sizes.length) |
| sizeIndex = sizeIndex + sizeAdjustment; |
| |
| // enables cross browser use of relative width/height |
| // on object elements for use with SVG and Flash media |
| adjustObjectDimensions(width, height); |
| |
| document.body.style.fontSize = sizes[sizeIndex]; |
| |
| lastWidth = width; |
| lastHeight = height; |
| |
| // force reflow to work around Mozilla bug |
| //if (ns_pos) |
| { |
| var slide = slides[slidenum]; |
| hideSlide(slide); |
| showSlide(slide); |
| } |
| |
| // force correct positioning of toolbar |
| refreshToolbar(200); |
| } |
| } |
| |
| function scrolled() |
| { |
| if (toolbar && !ns_pos && !ie7) |
| { |
| hackoffset = scrollXOffset(); |
| // hide toolbar |
| toolbar.style.display = "none"; |
| |
| // make it reappear later |
| if (scrollhack == 0 && !viewAll) |
| { |
| setTimeout(showToolbar, 1000); |
| scrollhack = 1; |
| } |
| } |
| } |
| |
| // used to ensure IE refreshes toolbar in correct position |
| function refreshToolbar(interval) |
| { |
| if (!ns_pos && !ie7) |
| { |
| hideToolbar(); |
| setTimeout(showToolbar, interval); |
| } |
| } |
| |
| // restores toolbar after short delay |
| function showToolbar() |
| { |
| if (wantToolbar) |
| { |
| if (!ns_pos) |
| { |
| // adjust position to allow for scrolling |
| var xoffset = scrollXOffset(); |
| toolbar.style.left = xoffset; |
| toolbar.style.right = xoffset; |
| |
| // determine vertical scroll offset |
| //var yoffset = scrollYOffset(); |
| |
| // bottom is doc height - window height - scroll offset |
| //var bottom = documentHeight() - lastHeight - yoffset |
| |
| //if (yoffset > 0 || documentHeight() > lastHeight) |
| // bottom += 16; // allow for height of scrollbar |
| |
| toolbar.style.bottom = 0; //bottom; |
| } |
| |
| toolbar.style.display = "block"; |
| toolbar.style.visibility = "visible"; |
| } |
| |
| scrollhack = 0; |
| |
| |
| // set the keyboard focus to the help link on the |
| // toolbar to ensure that document has the focus |
| // IE doesn't always work with window.focus() |
| // and this hack has benefit of Enter for help |
| |
| try |
| { |
| if (!opera) |
| helpAnchor.focus(); |
| } |
| catch (e) |
| { |
| } |
| } |
| |
| function test() |
| { |
| var s = "docH: " + documentHeight() + |
| " winH: " + lastHeight + |
| " yoffset: " + scrollYOffset() + |
| " toolbot: " + (documentHeight() - lastHeight - scrollYOffset()); |
| |
| //alert(s); |
| |
| var slide = slides[slidenum]; |
| // IE getAttribute requires "class" to be "className" |
| var name = ns_pos ? "class" : "className"; |
| var style = (slide.currentStyle ? slide.currentStyle["backgroundColor"] : |
| document.defaultView.getComputedStyle(slide, '').getPropertyValue("background-color")); |
| alert("class='" + slide.getAttribute(name) + "' backgroundColor: " + style); |
| } |
| |
| function hideToolbar() |
| { |
| toolbar.style.display = "none"; |
| toolbar.style.visibility = "hidden"; |
| window.focus(); |
| } |
| |
| // invoked via F key |
| function toggleToolbar() |
| { |
| if (!viewAll) |
| { |
| if (toolbar.style.display == "none") |
| { |
| toolbar.style.display = "block"; |
| toolbar.style.visibility = "visible"; |
| wantToolbar = 1; |
| } |
| else |
| { |
| toolbar.style.display = "none"; |
| toolbar.style.visibility = "hidden"; |
| wantToolbar = 0; |
| } |
| } |
| } |
| |
| function scrollXOffset() |
| { |
| if (window.pageXOffset) |
| return self.pageXOffset; |
| |
| if (document.documentElement && |
| document.documentElement.scrollLeft) |
| return document.documentElement.scrollLeft; |
| |
| if (document.body) |
| return document.body.scrollLeft; |
| |
| return 0; |
| } |
| |
| |
| function scrollYOffset() |
| { |
| if (window.pageYOffset) |
| return self.pageYOffset; |
| |
| if (document.documentElement && |
| document.documentElement.scrollTop) |
| return document.documentElement.scrollTop; |
| |
| if (document.body) |
| return document.body.scrollTop; |
| |
| return 0; |
| } |
| |
| // looking for a way to determine height of slide content |
| // the slide itself is set to the height of the window |
| function optimizeFontSize() |
| { |
| var slide = slides[slidenum]; |
| |
| //var dh = documentHeight(); //getDocHeight(document); |
| var dh = slide.scrollHeight; |
| var wh = getWindowHeight(); |
| var u = 100 * dh / wh; |
| |
| alert("window utilization = " + u + "% (doc " |
| + dh + " win " + wh + ")"); |
| } |
| |
| function getDocHeight(doc) // from document object |
| { |
| if (!doc) |
| doc = document; |
| |
| if (doc && doc.body && doc.body.offsetHeight) |
| return doc.body.offsetHeight; // ns/gecko syntax |
| |
| if (doc && doc.body && doc.body.scrollHeight) |
| return doc.body.scrollHeight; |
| |
| alert("couldn't determine document height"); |
| } |
| |
| function getWindowHeight() |
| { |
| if ( typeof( window.innerHeight ) == 'number' ) |
| return window.innerHeight; // Non IE browser |
| |
| if (document.documentElement && document.documentElement.clientHeight) |
| return document.documentElement.clientHeight; // IE6 |
| |
| if (document.body && document.body.clientHeight) |
| return document.body.clientHeight; // IE4 |
| } |
| |
| |
| |
| function documentHeight() |
| { |
| var sh, oh; |
| |
| sh = document.body.scrollHeight; |
| oh = document.body.offsetHeight; |
| |
| if (sh && oh) |
| { |
| return (sh > oh ? sh : oh); |
| } |
| |
| // no idea! |
| return 0; |
| } |
| |
| function smaller() |
| { |
| if (sizeIndex > 0) |
| { |
| --sizeIndex; |
| } |
| |
| toolbar.style.display = "none"; |
| document.body.style.fontSize = sizes[sizeIndex]; |
| var slide = slides[slidenum]; |
| hideSlide(slide); |
| showSlide(slide); |
| setTimeout(showToolbar, 300); |
| } |
| |
| function bigger() |
| { |
| if (sizeIndex < sizes.length - 1) |
| { |
| ++sizeIndex; |
| } |
| |
| toolbar.style.display = "none"; |
| document.body.style.fontSize = sizes[sizeIndex]; |
| var slide = slides[slidenum]; |
| hideSlide(slide); |
| showSlide(slide); |
| setTimeout(showToolbar, 300); |
| } |
| |
| // enables cross browser use of relative width/height |
| // on object elements for use with SVG and Flash media |
| // with thanks to Ivan Herman for the suggestion |
| function adjustObjectDimensions(width, height) |
| { |
| for( var i = 0; i < objects.length; i++ ) |
| { |
| var obj = objects[i]; |
| var mimeType = obj.getAttribute("type"); |
| |
| if (mimeType == "image/svg+xml" || mimeType == "application/x-shockwave-flash") |
| { |
| if ( !obj.initialWidth ) |
| obj.initialWidth = obj.getAttribute("width"); |
| |
| if ( !obj.initialHeight ) |
| obj.initialHeight = obj.getAttribute("height"); |
| |
| if ( obj.initialWidth && obj.initialWidth.charAt(obj.initialWidth.length-1) == "%" ) |
| { |
| var w = parseInt(obj.initialWidth.slice(0, obj.initialWidth.length-1)); |
| var newW = width * (w/100.0); |
| obj.setAttribute("width",newW); |
| } |
| |
| if ( obj.initialHeight && obj.initialHeight.charAt(obj.initialHeight.length-1) == "%" ) |
| { |
| var h = parseInt(obj.initialHeight.slice(0, obj.initialHeight.length-1)); |
| var newH = height * (h/100.0); |
| obj.setAttribute("height", newH); |
| } |
| } |
| } |
| } |
| |
| function cancel(event) |
| { |
| if (event) |
| { |
| event.cancel = true; |
| event.returnValue = false; |
| |
| if (event.preventDefault) |
| event.preventDefault(); |
| } |
| |
| return false; |
| } |
| |
| // See e.g. http://www.quirksmode.org/js/events/keys.html for keycodes |
| function keyDown(event) |
| { |
| var key; |
| |
| if (!event) |
| var event = window.event; |
| |
| // kludge around NS/IE differences |
| if (window.event) |
| key = window.event.keyCode; |
| else if (event.which) |
| key = event.which; |
| else |
| return true; // Yikes! unknown browser |
| |
| // ignore event if key value is zero |
| // as for alt on Opera and Konqueror |
| if (!key) |
| return true; |
| |
| // check for concurrent control/command/alt key |
| // but are these only present on mouse events? |
| |
| if (event.ctrlKey || event.altKey || event.metaKey) |
| return true; |
| |
| // dismiss table of contents if visible |
| if (isShownToc() && key != 9 && key != 16 && key != 38 && key != 40) |
| { |
| hideTableOfContents(); |
| |
| if (key == 27 || key == 84 || key == 67) |
| return cancel(event); |
| } |
| |
| if (key == 34) // Page Down |
| { |
| nextSlide(false); |
| return cancel(event); |
| } |
| else if (key == 33) // Page Up |
| { |
| previousSlide(false); |
| return cancel(event); |
| } |
| else if (key == 32) // space bar |
| { |
| nextSlide(true); |
| return cancel(event); |
| } |
| else if (key == 37 || key == 38) // Left arrow || Up arrow |
| { |
| previousSlide(!event.shiftKey); |
| return cancel(event); |
| } |
| else if (key == 36) // Home |
| { |
| firstSlide(); |
| return cancel(event); |
| } |
| else if (key == 35) // End |
| { |
| lastSlide(); |
| return cancel(event); |
| } |
| else if (key == 39 || key == 40) // Right arrow || Down arrow |
| { |
| nextSlide(!event.shiftKey); |
| return cancel(event); |
| } |
| else if (key == 13) // Enter |
| { |
| if (outline) |
| { |
| if (outline.visible) |
| fold(outline); |
| else |
| unfold(outline); |
| |
| return cancel(event); |
| } |
| } |
| else if (key == 188) // < for smaller fonts |
| { |
| smaller(); |
| return cancel(event); |
| } |
| else if (key == 190) // > for larger fonts |
| { |
| bigger(); |
| return cancel(event); |
| } |
| else if (key == 189 || key == 109) // - for smaller fonts |
| { |
| smaller(); |
| return cancel(event); |
| } |
| else if (key == 187 || key == 191 || key == 107) // = + for larger fonts |
| { |
| bigger(); |
| return cancel(event); |
| } |
| else if (key == 83) // S for smaller fonts |
| { |
| smaller(); |
| return cancel(event); |
| } |
| else if (key == 66) // B for larger fonts |
| { |
| bigger(); |
| return cancel(event); |
| } |
| else if (key == 90) // Z for last slide |
| { |
| lastSlide(); |
| return cancel(event); |
| } |
| else if (key == 70) // F for toggle toolbar |
| { |
| toggleToolbar(); |
| return cancel(event); |
| } |
| else if (key == 65) // A for toggle view single/all slides |
| { |
| toggleView(); |
| return cancel(event); |
| } |
| else if (key == 75) // toggle action of left click for next page |
| { |
| mouseClickEnabled = !mouseClickEnabled; |
| alert((mouseClickEnabled ? "enabled" : "disabled") + " mouse click advance"); |
| return cancel(event); |
| } |
| else if (key == 84 || key == 67) // T or C for table of contents |
| { |
| if (toc) |
| showTableOfContents(); |
| |
| return cancel(event); |
| } |
| else if (key == 72) // H for help |
| { |
| window.location = helpPage; |
| return cancel(event); |
| } |
| |
| //else if (key == 93) // Windows menu key |
| //alert("lastShown is " + lastShown); |
| //else alert("key code is "+ key); |
| |
| |
| return true; |
| } |
| |
| // make note of length of selected text |
| // as this evaluates to zero in click event |
| function mouseButtonUp(e) |
| { |
| selectedTextLen = getSelectedText().length; |
| } |
| |
| // right mouse button click is reserved for context menus |
| // it is more reliable to detect rightclick than leftclick |
| function mouseButtonClick(e) |
| { |
| var rightclick = false; |
| var leftclick = false; |
| var middleclick = false; |
| var target; |
| |
| if (!e) |
| var e = window.event; |
| |
| if (e.target) |
| target = e.target; |
| else if (e.srcElement) |
| target = e.srcElement; |
| |
| // work around Safari bug |
| if (target.nodeType == 3) |
| target = target.parentNode; |
| |
| if (e.which) // all browsers except IE |
| { |
| leftclick = (e.which == 1); |
| middleclick = (e.which == 2); |
| rightclick = (e.which == 3); |
| } |
| else if (e.button) |
| { |
| // Konqueror gives 1 for left, 4 for middle |
| // IE6 gives 0 for left and not 1 as I expected |
| |
| if (e.button == 4) |
| middleclick = true; |
| |
| // all browsers agree on 2 for right button |
| rightclick = (e.button == 2); |
| } |
| else leftclick = true; |
| |
| // dismiss table of contents |
| hideTableOfContents(); |
| |
| if (selectedTextLen > 0) |
| { |
| stopPropagation(e); |
| e.cancel = true; |
| e.returnValue = false; |
| return false; |
| } |
| |
| // check if target is something that probably want's clicks |
| // e.g. embed, object, input, textarea, select, option |
| |
| if (mouseClickEnabled && leftclick && |
| target.nodeName != "EMBED" && |
| target.nodeName != "OBJECT" && |
| target.nodeName != "INPUT" && |
| target.nodeName != "TEXTAREA" && |
| target.nodeName != "SELECT" && |
| target.nodeName != "OPTION") |
| { |
| nextSlide(true); |
| stopPropagation(e); |
| e.cancel = true; |
| e.returnValue = false; |
| } |
| } |
| |
| function previousSlide(incremental) |
| { |
| if (!viewAll) |
| { |
| var slide; |
| |
| if ((incremental || slidenum == 0) && lastShown != null) |
| { |
| lastShown = hidePreviousItem(lastShown); |
| setEosStatus(false); |
| } |
| else if (slidenum > 0) |
| { |
| slide = slides[slidenum]; |
| hideSlide(slide); |
| |
| slidenum = slidenum - 1; |
| slide = slides[slidenum]; |
| setVisibilityAllIncremental("visible"); |
| lastShown = previousIncrementalItem(null); |
| setEosStatus(true); |
| showSlide(slide); |
| } |
| |
| setLocation(); |
| |
| if (!ns_pos) |
| refreshToolbar(200); |
| } |
| } |
| |
| function nextSlide(incremental) |
| { |
| if (!viewAll) |
| { |
| var slide, last = lastShown; |
| |
| if (incremental || slidenum == slides.length - 1) |
| lastShown = revealNextItem(lastShown); |
| |
| if ((!incremental || lastShown == null) && slidenum < slides.length - 1) |
| { |
| slide = slides[slidenum]; |
| hideSlide(slide); |
| |
| slidenum = slidenum + 1; |
| slide = slides[slidenum]; |
| lastShown = null; |
| setVisibilityAllIncremental("hidden"); |
| showSlide(slide); |
| } |
| else if (!lastShown) |
| { |
| if (last && incremental) |
| lastShown = last; |
| } |
| |
| setLocation(); |
| |
| setEosStatus(!nextIncrementalItem(lastShown)); |
| |
| if (!ns_pos) |
| refreshToolbar(200); |
| } |
| } |
| |
| // to first slide with nothing revealed |
| // i.e. state at start of presentation |
| function firstSlide() |
| { |
| if (!viewAll) |
| { |
| var slide; |
| |
| if (slidenum != 0) |
| { |
| slide = slides[slidenum]; |
| hideSlide(slide); |
| |
| slidenum = 0; |
| slide = slides[slidenum]; |
| lastShown = null; |
| setVisibilityAllIncremental("hidden"); |
| showSlide(slide); |
| } |
| |
| setEosStatus(!nextIncrementalItem(lastShown)); |
| setLocation(); |
| } |
| } |
| |
| |
| // to last slide with everything revealed |
| // i.e. state at end of presentation |
| function lastSlide() |
| { |
| if (!viewAll) |
| { |
| var slide; |
| |
| lastShown = null; //revealNextItem(lastShown); |
| |
| if (lastShown == null && slidenum < slides.length - 1) |
| { |
| slide = slides[slidenum]; |
| hideSlide(slide); |
| slidenum = slides.length - 1; |
| slide = slides[slidenum]; |
| setVisibilityAllIncremental("visible"); |
| lastShown = previousIncrementalItem(null); |
| |
| showSlide(slide); |
| } |
| else |
| { |
| setVisibilityAllIncremental("visible"); |
| lastShown = previousIncrementalItem(null); |
| } |
| |
| setEosStatus(true); |
| setLocation(); |
| } |
| } |
| |
| function setEosStatus(state) |
| { |
| if (eos) |
| eos.style.color = (state ? "rgb(240,240,240)" : "red"); |
| } |
| |
| function showSlide(slide) |
| { |
| syncBackground(slide); |
| window.scrollTo(0,0); |
| slide.style.visibility = "visible"; |
| slide.style.display = "block"; |
| } |
| |
| function hideSlide(slide) |
| { |
| slide.style.visibility = "hidden"; |
| slide.style.display = "none"; |
| } |
| |
| function beforePrint() |
| { |
| showAllSlides(); |
| hideToolbar(); |
| } |
| |
| function afterPrint() |
| { |
| if (!viewAll) |
| { |
| singleSlideView(); |
| showToolbar(); |
| } |
| } |
| |
| function printSlides() |
| { |
| beforePrint(); |
| window.print(); |
| afterPrint(); |
| } |
| |
| function toggleView() |
| { |
| if (viewAll) |
| { |
| singleSlideView(); |
| showToolbar(); |
| viewAll = 0; |
| } |
| else |
| { |
| showAllSlides(); |
| hideToolbar(); |
| viewAll = 1; |
| } |
| } |
| |
| // prepare for printing |
| function showAllSlides() |
| { |
| var slide; |
| |
| for (var i = 0; i < slides.length; ++i) |
| { |
| slide = slides[i]; |
| |
| slide.style.position = "relative"; |
| slide.style.borderTopStyle = "solid"; |
| slide.style.borderTopWidth = "thin"; |
| slide.style.borderTopColor = "black"; |
| |
| try { |
| if (i == 0) |
| slide.style.pageBreakBefore = "avoid"; |
| else |
| slide.style.pageBreakBefore = "always"; |
| } |
| catch (e) |
| { |
| //do nothing |
| } |
| |
| setVisibilityAllIncremental("visible"); |
| showSlide(slide); |
| } |
| |
| var note; |
| |
| for (var i = 0; i < notes.length; ++i) |
| { |
| showSlide(notes[i]); |
| } |
| |
| // no easy way to render background under each slide |
| // without duplicating the background divs for each slide |
| // therefore hide backgrounds to avoid messing up slides |
| hideBackgrounds(); |
| } |
| |
| // restore after printing |
| function singleSlideView() |
| { |
| var slide; |
| |
| for (var i = 0; i < slides.length; ++i) |
| { |
| slide = slides[i]; |
| |
| slide.style.position = "absolute"; |
| |
| if (i == slidenum) |
| { |
| slide.style.borderStyle = "none"; |
| showSlide(slide); |
| } |
| else |
| { |
| slide.style.borderStyle = "none"; |
| hideSlide(slide); |
| } |
| } |
| |
| setVisibilityAllIncremental("visible"); |
| lastShown = previousIncrementalItem(null); |
| |
| var note; |
| |
| for (var i = 0; i < notes.length; ++i) |
| { |
| hideSlide(notes[i]); |
| } |
| } |
| |
| // the string str is a whitespace separated list of tokens |
| // test if str contains a particular token, e.g. "slide" |
| function hasToken(str, token) |
| { |
| if (str) |
| { |
| // define pattern as regular expression |
| var pattern = /\w+/g; |
| |
| // check for matches |
| // place result in array |
| var result = str.match(pattern); |
| |
| // now check if desired token is present |
| for (var i = 0; i < result.length; i++) |
| { |
| if (result[i] == token) |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| function getClassList(element) |
| { |
| if (typeof window.pageYOffset =='undefined') |
| return element.getAttribute("className"); |
| |
| return element.getAttribute("class"); |
| } |
| |
| function hasClass(element, name) |
| { |
| var regexp = new RegExp("(^| )" + name + "\W*"); |
| |
| if (regexp.test(getClassList(element))) |
| return true; |
| |
| return false; |
| |
| } |
| |
| function removeClass(element, name) |
| { |
| // IE getAttribute requires "class" to be "className" |
| var clsname = ns_pos ? "class" : "className"; |
| var clsval = element.getAttribute(clsname); |
| |
| var regexp = new RegExp("(^| )" + name + "\W*"); |
| |
| if (clsval) |
| { |
| clsval = clsval.replace(regexp, ""); |
| element.setAttribute(clsname, clsval); |
| } |
| } |
| |
| function addClass(element, name) |
| { |
| if (!hasClass(element, name)) |
| { |
| // IE getAttribute requires "class" to be "className" |
| var clsname = ns_pos ? "class" : "className"; |
| var clsval = element.getAttribute(clsname); |
| element.setAttribute(clsname, (clsval ? clsval + " " + name : name)); |
| } |
| } |
| |
| // wysiwyg editors make it hard to use div elements |
| // e.g. amaya loses the div when you copy and paste |
| // this function wraps div elements around implicit |
| // slides which start with an h1 element and continue |
| // up to the next heading or div element |
| function wrapImplicitSlides() |
| { |
| var i, heading, node, next, div; |
| var headings = document.getElementsByTagName("h1"); |
| |
| if (!headings) |
| return; |
| |
| for (i = 0; i < headings.length; ++i) |
| { |
| heading = headings[i]; |
| |
| if (heading.parentNode != document.body) |
| continue; |
| |
| node = heading.nextSibling; |
| |
| div = document.createElement("div"); |
| div.setAttribute((ns_pos ? "class" : "className"), "slide"); |
| document.body.replaceChild(div, heading); |
| div.appendChild(heading); |
| |
| while (node) |
| { |
| if (node.nodeType == 1 && // an element |
| (node.nodeName == "H1" || |
| node.nodeName == "h1" || |
| node.nodeName == "DIV" || |
| node.nodeName == "div")) |
| break; |
| |
| next = node.nextSibling; |
| node = document.body.removeChild(node); |
| div.appendChild(node); |
| node = next; |
| } |
| } |
| } |
| |
| // return new array of all slides |
| function collectSlides() |
| { |
| var slides = new Array(); |
| var divs = document.body.getElementsByTagName("div"); |
| |
| for (var i = 0; i < divs.length; ++i) |
| { |
| div = divs.item(i); |
| |
| if (hasClass(div, "slide")) |
| { |
| // add slide to collection |
| slides[slides.length] = div; |
| |
| // hide each slide as it is found |
| div.style.display = "none"; |
| div.style.visibility = "hidden"; |
| |
| // add dummy <br/> at end for scrolling hack |
| var node1 = document.createElement("br"); |
| div.appendChild(node1); |
| var node2 = document.createElement("br"); |
| div.appendChild(node2); |
| } |
| else if (hasClass(div, "background")) |
| { // work around for Firefox SVG reload bug |
| // which otherwise replaces 1st SVG graphic with 2nd |
| div.style.display = "block"; |
| } |
| } |
| |
| return slides; |
| } |
| |
| // return new array of all <div class="handout"> |
| function collectNotes() |
| { |
| var notes = new Array(); |
| var divs = document.body.getElementsByTagName("div"); |
| |
| for (var i = 0; i < divs.length; ++i) |
| { |
| div = divs.item(i); |
| |
| if (hasClass(div, "handout")) |
| { |
| // add slide to collection |
| notes[notes.length] = div; |
| |
| // hide handout notes as they are found |
| div.style.display = "none"; |
| div.style.visibility = "hidden"; |
| } |
| } |
| |
| return notes; |
| } |
| |
| // return new array of all <div class="background"> |
| // including named backgrounds e.g. class="background titlepage" |
| function collectBackgrounds() |
| { |
| var backgrounds = new Array(); |
| var divs = document.body.getElementsByTagName("div"); |
| |
| for (var i = 0; i < divs.length; ++i) |
| { |
| div = divs.item(i); |
| |
| if (hasClass(div, "background")) |
| { |
| // add slide to collection |
| backgrounds[backgrounds.length] = div; |
| |
| // hide named backgrounds as they are found |
| // e.g. class="background epilog" |
| if (getClassList(div) != "background") |
| { |
| div.style.display = "none"; |
| div.style.visibility = "hidden"; |
| } |
| } |
| } |
| |
| return backgrounds; |
| } |
| |
| // show just the backgrounds pertinent to this slide |
| function syncBackground(slide) |
| { |
| var background; |
| var bgColor; |
| |
| if (slide.currentStyle) |
| bgColor = slide.currentStyle["backgroundColor"]; |
| else if (document.defaultView) |
| { |
| var styles = document.defaultView.getComputedStyle(slide,null); |
| |
| if (styles) |
| bgColor = styles.getPropertyValue("background-color"); |
| else // broken implementation probably due Safari or Konqueror |
| { |
| //alert("defective implementation of getComputedStyle()"); |
| bgColor = "transparent"; |
| } |
| } |
| else |
| bgColor == "transparent"; |
| |
| if (bgColor == "transparent") |
| { |
| var slideClass = getClassList(slide); |
| |
| for (var i = 0; i < backgrounds.length; i++) |
| { |
| background = backgrounds[i]; |
| |
| var bgClass = getClassList(background); |
| |
| if (matchingBackground(slideClass, bgClass)) |
| { |
| background.style.display = "block"; |
| background.style.visibility = "visible"; |
| } |
| else |
| { |
| background.style.display = "none"; |
| background.style.visibility = "hidden"; |
| } |
| } |
| } |
| else // forcibly hide all backgrounds |
| hideBackgrounds(); |
| } |
| |
| function hideBackgrounds() |
| { |
| for (var i = 0; i < backgrounds.length; i++) |
| { |
| background = backgrounds[i]; |
| background.style.display = "none"; |
| background.style.visibility = "hidden"; |
| } |
| } |
| |
| // compare classes for slide and background |
| function matchingBackground(slideClass, bgClass) |
| { |
| if (bgClass == "background") |
| return true; |
| |
| // define pattern as regular expression |
| var pattern = /\w+/g; |
| |
| // check for matches and place result in array |
| var result = slideClass.match(pattern); |
| |
| // now check if desired name is present for background |
| for (var i = 0; i < result.length; i++) |
| { |
| if (hasToken(bgClass, result[i])) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| // left to right traversal of root's content |
| function nextNode(root, node) |
| { |
| if (node == null) |
| return root.firstChild; |
| |
| if (node.firstChild) |
| return node.firstChild; |
| |
| if (node.nextSibling) |
| return node.nextSibling; |
| |
| for (;;) |
| { |
| node = node.parentNode; |
| |
| if (!node || node == root) |
| break; |
| |
| if (node && node.nextSibling) |
| return node.nextSibling; |
| } |
| |
| return null; |
| } |
| |
| // right to left traversal of root's content |
| function previousNode(root, node) |
| { |
| if (node == null) |
| { |
| node = root.lastChild; |
| |
| if (node) |
| { |
| while (node.lastChild) |
| node = node.lastChild; |
| } |
| |
| return node; |
| } |
| |
| if (node.previousSibling) |
| { |
| node = node.previousSibling; |
| |
| while (node.lastChild) |
| node = node.lastChild; |
| |
| return node; |
| } |
| |
| if (node.parentNode != root) |
| return node.parentNode; |
| |
| return null; |
| } |
| |
| // HTML elements that can be used with class="incremental" |
| // note that you can also put the class on containers like |
| // up, ol, dl, and div to make their contents appear |
| // incrementally. Upper case is used since this is what |
| // browsers report for HTML node names (text/html). |
| function incrementalElementList() |
| { |
| var inclist = new Array(); |
| inclist["P"] = true; |
| inclist["PRE"] = true; |
| inclist["LI"] = true; |
| inclist["BLOCKQUOTE"] = true; |
| inclist["DT"] = true; |
| inclist["DD"] = true; |
| inclist["H2"] = true; |
| inclist["H3"] = true; |
| inclist["H4"] = true; |
| inclist["H5"] = true; |
| inclist["H6"] = true; |
| inclist["SPAN"] = true; |
| inclist["ADDRESS"] = true; |
| inclist["TABLE"] = true; |
| inclist["TR"] = true; |
| inclist["TH"] = true; |
| inclist["TD"] = true; |
| inclist["IMG"] = true; |
| inclist["OBJECT"] = true; |
| return inclist; |
| } |
| |
| function nextIncrementalItem(node) |
| { |
| var slide = slides[slidenum]; |
| |
| for (;;) |
| { |
| node = nextNode(slide, node); |
| |
| if (node == null || node.parentNode == null) |
| break; |
| |
| if (node.nodeType == 1) // ELEMENT |
| { |
| if (node.nodeName == "BR") |
| continue; |
| |
| if (hasClass(node, "incremental") |
| && okayForIncremental[node.nodeName]) |
| return node; |
| |
| if (hasClass(node.parentNode, "incremental") |
| && !hasClass(node, "non-incremental")) |
| return node; |
| } |
| } |
| |
| return node; |
| } |
| |
| function previousIncrementalItem(node) |
| { |
| var slide = slides[slidenum]; |
| |
| for (;;) |
| { |
| node = previousNode(slide, node); |
| |
| if (node == null || node.parentNode == null) |
| break; |
| |
| if (node.nodeType == 1) |
| { |
| if (node.nodeName == "BR") |
| continue; |
| |
| if (hasClass(node, "incremental") |
| && okayForIncremental[node.nodeName]) |
| return node; |
| |
| if (hasClass(node.parentNode, "incremental") |
| && !hasClass(node, "non-incremental")) |
| return node; |
| } |
| } |
| |
| return node; |
| } |
| |
| // set visibility for all elements on current slide with |
| // a parent element with attribute class="incremental" |
| function setVisibilityAllIncremental(value) |
| { |
| var node = nextIncrementalItem(null); |
| |
| while (node) |
| { |
| node.style.visibility = value; |
| node = nextIncrementalItem(node); |
| } |
| } |
| |
| // reveal the next hidden item on the slide |
| // node is null or the node that was last revealed |
| function revealNextItem(node) |
| { |
| node = nextIncrementalItem(node); |
| |
| if (node && node.nodeType == 1) // an element |
| node.style.visibility = "visible"; |
| |
| return node; |
| } |
| |
| |
| // exact inverse of revealNextItem(node) |
| function hidePreviousItem(node) |
| { |
| if (node && node.nodeType == 1) // an element |
| node.style.visibility = "hidden"; |
| |
| return previousIncrementalItem(node); |
| } |
| |
| |
| /* set click handlers on all anchors */ |
| function patchAnchors() |
| { |
| var anchors = document.body.getElementsByTagName("a"); |
| |
| for (var i = 0; i < anchors.length; ++i) |
| { |
| anchors[i].onclick = clickedAnchor; |
| } |
| } |
| |
| function clickedAnchor(e) |
| { |
| if (!e) |
| var e = window.event; |
| |
| // compare this.href with location.href |
| // for link to another slide in this doc |
| |
| if (pageAddress(this.href) == pageAddress(location.href)) |
| { |
| // yes, so find new slide number |
| var newslidenum = findSlideNumber(this.href); |
| |
| if (newslidenum != slidenum) |
| { |
| slide = slides[slidenum]; |
| hideSlide(slide); |
| slidenum = newslidenum; |
| slide = slides[slidenum]; |
| showSlide(slide); |
| setLocation(); |
| } |
| } |
| else if (this.target == null) |
| location.href = this.href; |
| |
| this.blur(); |
| stopPropagation(e); |
| } |
| |
| function pageAddress(uri) |
| { |
| var i = uri.indexOf("#"); |
| |
| // check if anchor is entire page |
| |
| if (i < 0) |
| return uri; // yes |
| |
| return uri.substr(0, i); |
| } |
| |
| function showSlideNumber() |
| { |
| slideNumElement.innerHTML = "slide".localize() + " " + |
| (slidenum + 1) + "/" + slides.length; |
| } |
| |
| function setLocation() |
| { |
| var uri = pageAddress(location.href); |
| |
| //if (slidenum > 0) |
| uri = uri + "#(" + (slidenum+1) + ")"; |
| |
| if (uri != location.href && !khtml) |
| location.href = uri; |
| |
| document.title = title + " (" + (slidenum+1) + ")"; |
| //document.title = (slidenum+1) + ") " + slideName(slidenum); |
| |
| showSlideNumber(); |
| } |
| |
| // find current slide based upon location |
| // first find target anchor and then look |
| // for associated div element enclosing it |
| // finally map that to slide number |
| function findSlideNumber(uri) |
| { |
| // first get anchor from page location |
| |
| var i = uri.indexOf("#"); |
| |
| // check if anchor is entire page |
| |
| if (i < 0) |
| return 0; // yes |
| |
| var anchor = unescape(uri.substr(i+1)); |
| |
| // now use anchor as XML ID to find target |
| var target = document.getElementById(anchor); |
| |
| if (!target) |
| { |
| // does anchor look like "(2)" for slide 2 ?? |
| // where first slide is (1) |
| var re = /\((\d)+\)/; |
| |
| if (anchor.match(re)) |
| { |
| var num = parseInt(anchor.substring(1, anchor.length-1)); |
| |
| if (num > slides.length) |
| num = 1; |
| |
| if (--num < 0) |
| num = 0; |
| |
| return num; |
| } |
| |
| // accept [2] for backwards compatibility |
| re = /\[(\d)+\]/; |
| |
| if (anchor.match(re)) |
| { |
| var num = parseInt(anchor.substring(1, anchor.length-1)); |
| |
| if (num > slides.length) |
| num = 1; |
| |
| if (--num < 0) |
| num = 0; |
| |
| return num; |
| } |
| |
| // oh dear unknown anchor |
| return 0; |
| } |
| |
| // search for enclosing slide |
| |
| while (true) |
| { |
| // browser coerces html elements to uppercase! |
| if (target.nodeName.toLowerCase() == "div" && |
| hasClass(target, "slide")) |
| { |
| // found the slide element |
| break; |
| } |
| |
| // otherwise try parent element if any |
| |
| target = target.parentNode; |
| |
| if (!target) |
| { |
| return 0; // no luck! |
| } |
| }; |
| |
| for (i = 0; i < slides.length; ++i) |
| { |
| if (slides[i] == target) |
| return i; // success |
| } |
| |
| // oh dear still no luck |
| return 0; |
| } |
| |
| // find slide name from first h1 element |
| // default to document title + slide number |
| function slideName(index) |
| { |
| var name = null; |
| var slide = slides[index]; |
| |
| var heading = findHeading(slide); |
| |
| if (heading) |
| name = extractText(heading); |
| |
| if (!name) |
| name = title + "(" + (index + 1) + ")"; |
| |
| name.replace(/\&/g, "&"); |
| name.replace(/\</g, "<"); |
| name.replace(/\>/g, ">"); |
| |
| return name; |
| } |
| |
| // find first h1 element in DOM tree |
| function findHeading(node) |
| { |
| if (!node || node.nodeType != 1) |
| return null; |
| |
| if (node.nodeName == "H1" || node.nodeName == "h1") |
| return node; |
| |
| var child = node.firstChild; |
| |
| while (child) |
| { |
| node = findHeading(child); |
| |
| if (node) |
| return node; |
| |
| child = child.nextSibling; |
| } |
| |
| return null; |
| } |
| |
| // recursively extract text from DOM tree |
| function extractText(node) |
| { |
| if (!node) |
| return ""; |
| |
| // text nodes |
| if (node.nodeType == 3) |
| return node.nodeValue; |
| |
| // elements |
| if (node.nodeType == 1) |
| { |
| node = node.firstChild; |
| var text = ""; |
| |
| while (node) |
| { |
| text = text + extractText(node); |
| node = node.nextSibling; |
| } |
| |
| return text; |
| } |
| |
| return ""; |
| } |
| |
| |
| // find copyright text from meta element |
| function findCopyright() |
| { |
| var name, content; |
| var meta = document.getElementsByTagName("meta"); |
| |
| for (var i = 0; i < meta.length; ++i) |
| { |
| name = meta[i].getAttribute("name"); |
| content = meta[i].getAttribute("content"); |
| |
| if (name == "copyright") |
| return content; |
| } |
| |
| return null; |
| } |
| |
| function findSizeAdjust() |
| { |
| var name, content, offset; |
| var meta = document.getElementsByTagName("meta"); |
| |
| for (var i = 0; i < meta.length; ++i) |
| { |
| name = meta[i].getAttribute("name"); |
| content = meta[i].getAttribute("content"); |
| |
| if (name == "font-size-adjustment") |
| return 1 * content; |
| } |
| |
| return 0; |
| } |
| |
| function addToolbar() |
| { |
| var slideCounter, page; |
| |
| var toolbar = createElement("div"); |
| toolbar.setAttribute("class", "toolbar"); |
| |
| if (ns_pos) // a reasonably behaved browser |
| { |
| var right = document.createElement("div"); |
| right.setAttribute("style", "float: right; text-align: right"); |
| |
| slideCounter = document.createElement("div") |
| slideCounter.innerHTML = "slide".localize() + " n/m"; |
| right.appendChild(slideCounter); |
| toolbar.appendChild(right); |
| |
| var left = document.createElement("div"); |
| left.setAttribute("style", "text-align: left"); |
| |
| // global end of slide indicator |
| eos = document.createElement("span"); |
| eos.innerHTML = "* "; |
| left.appendChild(eos); |
| |
| var help = document.createElement("a"); |
| help.setAttribute("href", helpPage); |
| help.setAttribute("title", helpText.localize()); |
| help.innerHTML = "help?".localize(); |
| left.appendChild(help); |
| helpAnchor = help; // save for focus hack |
| |
| var gap1 = document.createTextNode(" "); |
| left.appendChild(gap1); |
| |
| var contents = document.createElement("a"); |
| contents.setAttribute("href", "javascript:toggleTableOfContents()"); |
| contents.setAttribute("title", "table of contents".localize()); |
| contents.innerHTML = "contents?".localize(); |
| left.appendChild(contents); |
| |
| var gap2 = document.createTextNode(" "); |
| left.appendChild(gap2); |
| |
| var i = location.href.indexOf("#"); |
| |
| // check if anchor is entire page |
| |
| if (i > 0) |
| page = location.href.substr(0, i); |
| else |
| page = location.href; |
| |
| var start = document.createElement("a"); |
| start.setAttribute("href", page); |
| start.setAttribute("title", "restart presentation".localize()); |
| start.innerHTML = "restart?".localize(); |
| // start.setAttribute("href", "javascript:printSlides()"); |
| // start.setAttribute("title", "print all slides".localize()); |
| // start.innerHTML = "print!".localize(); |
| left.appendChild(start); |
| |
| var copyright = findCopyright(); |
| |
| if (copyright) |
| { |
| var span = document.createElement("span"); |
| span.innerHTML = copyright; |
| span.style.color = "black"; |
| span.style.marginLeft = "4em"; |
| left.appendChild(span); |
| } |
| |
| toolbar.appendChild(left); |
| } |
| else // IE so need to work around its poor CSS support |
| { |
| toolbar.style.position = (ie7 ? "fixed" : "absolute"); |
| toolbar.style.zIndex = "200"; |
| toolbar.style.width = "99.9%"; |
| toolbar.style.height = "1.2em"; |
| toolbar.style.top = "auto"; |
| toolbar.style.bottom = "0"; |
| toolbar.style.left = "0"; |
| toolbar.style.right = "0"; |
| toolbar.style.textAlign = "left"; |
| toolbar.style.fontSize = "60%"; |
| toolbar.style.color = "red"; |
| toolbar.borderWidth = 0; |
| toolbar.style.background = "rgb(240,240,240)"; |
| |
| // would like to have help text left aligned |
| // and page counter right aligned, floating |
| // div's don't work, so instead use nested |
| // absolutely positioned div's. |
| |
| var sp = document.createElement("span"); |
| sp.innerHTML = " * "; |
| toolbar.appendChild(sp); |
| eos = sp; // end of slide indicator |
| |
| var help = document.createElement("a"); |
| help.setAttribute("href", helpPage); |
| help.setAttribute("title", helpText.localize()); |
| help.innerHTML = "help?".localize(); |
| toolbar.appendChild(help); |
| helpAnchor = help; // save for focus hack |
| |
| var gap1 = document.createTextNode(" "); |
| toolbar.appendChild(gap1); |
| |
| var contents = document.createElement("a"); |
| contents.setAttribute("href", "javascript:toggleTableOfContents()"); |
| contents.setAttribute("title", "table of contents".localize()); |
| contents.innerHTML = "contents?".localize(); |
| toolbar.appendChild(contents); |
| |
| var gap2 = document.createTextNode(" "); |
| toolbar.appendChild(gap2); |
| |
| var i = location.href.indexOf("#"); |
| |
| // check if anchor is entire page |
| |
| if (i > 0) |
| page = location.href.substr(0, i); |
| else |
| page = location.href; |
| |
| var start = document.createElement("a"); |
| start.setAttribute("href", page); |
| start.setAttribute("title", "restart presentation".localize()); |
| start.innerHTML = "restart?".localize(); |
| // start.setAttribute("href", "javascript:printSlides()"); |
| // start.setAttribute("title", "print all slides".localize()); |
| // start.innerHTML = "print!".localize(); |
| toolbar.appendChild(start); |
| |
| var copyright = findCopyright(); |
| |
| if (copyright) |
| { |
| var span = document.createElement("span"); |
| span.innerHTML = copyright; |
| span.style.color = "black"; |
| span.style.marginLeft = "2em"; |
| toolbar.appendChild(span); |
| } |
| |
| slideCounter = document.createElement("div") |
| slideCounter.style.position = "absolute"; |
| slideCounter.style.width = "auto"; //"20%"; |
| slideCounter.style.height = "1.2em"; |
| slideCounter.style.top = "auto"; |
| slideCounter.style.bottom = 0; |
| slideCounter.style.right = "0"; |
| slideCounter.style.textAlign = "right"; |
| slideCounter.style.color = "red"; |
| slideCounter.style.background = "rgb(240,240,240)"; |
| |
| slideCounter.innerHTML = "slide".localize() + " n/m"; |
| toolbar.appendChild(slideCounter); |
| } |
| |
| // ensure that click isn't passed through to the page |
| toolbar.onclick = stopPropagation; |
| document.body.appendChild(toolbar); |
| slideNumElement = slideCounter; |
| setEosStatus(false); |
| |
| return toolbar; |
| } |
| |
| function isShownToc() |
| { |
| if (toc && toc.style.visible == "visible") |
| return true; |
| |
| return false; |
| } |
| |
| function showTableOfContents() |
| { |
| if (toc) |
| { |
| if (toc.style.visibility != "visible") |
| { |
| toc.style.visibility = "visible"; |
| toc.style.display = "block"; |
| toc.focus(); |
| |
| if (ie7 && slidenum == 0) |
| setTimeout("ieHack()", 100); |
| } |
| else |
| hideTableOfContents(); |
| } |
| } |
| |
| function hideTableOfContents() |
| { |
| if (toc && toc.style.visibility != "hidden") |
| { |
| toc.style.visibility = "hidden"; |
| toc.style.display = "none"; |
| |
| try |
| { |
| if (!opera) |
| helpAnchor.focus(); |
| } |
| catch (e) |
| { |
| } |
| } |
| } |
| |
| function toggleTableOfContents() |
| { |
| if (toc) |
| { |
| if (toc.style.visible != "visible") |
| showTableOfContents(); |
| else |
| hideTableOfContents(); |
| } |
| } |
| |
| // called on clicking toc entry |
| function gotoEntry(e) |
| { |
| var target; |
| |
| if (!e) |
| var e = window.event; |
| |
| if (e.target) |
| target = e.target; |
| else if (e.srcElement) |
| target = e.srcElement; |
| |
| // work around Safari bug |
| if (target.nodeType == 3) |
| target = target.parentNode; |
| |
| if (target && target.nodeType == 1) |
| { |
| var uri = target.getAttribute("href"); |
| |
| if (uri) |
| { |
| //alert("going to " + uri); |
| var slide = slides[slidenum]; |
| hideSlide(slide); |
| slidenum = findSlideNumber(uri); |
| slide = slides[slidenum]; |
| lastShown = null; |
| setLocation(); |
| setVisibilityAllIncremental("hidden"); |
| setEosStatus(!nextIncrementalItem(lastShown)); |
| showSlide(slide); |
| //target.focus(); |
| |
| try |
| { |
| if (!opera) |
| helpAnchor.focus(); |
| } |
| catch (e) |
| { |
| } |
| } |
| } |
| |
| hideTableOfContents(e); |
| if (ie7) ieHack(); |
| stopPropagation(e); |
| return cancel(e); |
| } |
| |
| // called onkeydown for toc entry |
| function gotoTocEntry(event) |
| { |
| var key; |
| |
| if (!event) |
| var event = window.event; |
| |
| // kludge around NS/IE differences |
| if (window.event) |
| key = window.event.keyCode; |
| else if (event.which) |
| key = event.which; |
| else |
| return true; // Yikes! unknown browser |
| |
| // ignore event if key value is zero |
| // as for alt on Opera and Konqueror |
| if (!key) |
| return true; |
| |
| // check for concurrent control/command/alt key |
| // but are these only present on mouse events? |
| |
| if (event.ctrlKey || event.altKey) |
| return true; |
| |
| if (key == 13) |
| { |
| var uri = this.getAttribute("href"); |
| |
| if (uri) |
| { |
| //alert("going to " + uri); |
| var slide = slides[slidenum]; |
| hideSlide(slide); |
| slidenum = findSlideNumber(uri); |
| slide = slides[slidenum]; |
| lastShown = null; |
| setLocation(); |
| setVisibilityAllIncremental("hidden"); |
| setEosStatus(!nextIncrementalItem(lastShown)); |
| showSlide(slide); |
| //target.focus(); |
| |
| try |
| { |
| if (!opera) |
| helpAnchor.focus(); |
| } |
| catch (e) |
| { |
| } |
| } |
| |
| hideTableOfContents(); |
| if (ie7) ieHack(); |
| return cancel(event); |
| } |
| |
| if (key == 40 && this.next) |
| { |
| this.next.focus(); |
| return cancel(event); |
| } |
| |
| if (key == 38 && this.previous) |
| { |
| this.previous.focus(); |
| return cancel(event); |
| } |
| |
| return true; |
| } |
| |
| function isTitleSlide(slide) |
| { |
| return hasClass(slide, "title"); |
| } |
| |
| // create div element with links to each slide |
| function tableOfContents() |
| { |
| var toc = document.createElement("div"); |
| addClass(toc, "toc"); |
| //toc.setAttribute("tabindex", "0"); |
| |
| var heading = document.createElement("div"); |
| addClass(heading, "toc-heading"); |
| heading.innerHTML = "Table of Contents".localize(); |
| |
| heading.style.textAlign = "center"; |
| heading.style.width = "100%"; |
| heading.style.margin = "0"; |
| heading.style.marginBottom = "1em"; |
| heading.style.borderBottomStyle = "solid"; |
| heading.style.borderBottomColor = "rgb(180,180,180)"; |
| heading.style.borderBottomWidth = "1px"; |
| |
| toc.appendChild(heading); |
| var previous = null; |
| |
| for (var i = 0; i < slides.length; ++i) |
| { |
| var title = hasClass(slides[i], "title"); |
| var num = document.createTextNode((i + 1) + ". "); |
| |
| toc.appendChild(num); |
| |
| var a = document.createElement("a"); |
| a.setAttribute("href", "#(" + (i+1) + ")"); |
| |
| if (title) |
| addClass(a, "titleslide"); |
| |
| var name = document.createTextNode(slideName(i)); |
| a.appendChild(name); |
| a.onclick = gotoEntry; |
| a.onkeydown = gotoTocEntry; |
| a.previous = previous; |
| |
| if (previous) |
| previous.next = a; |
| |
| toc.appendChild(a); |
| |
| if (i == 0) |
| toc.first = a; |
| |
| if (i < slides.length - 1) |
| { |
| var br = document.createElement("br"); |
| toc.appendChild(br); |
| } |
| |
| previous = a; |
| } |
| |
| toc.focus = function () { |
| if (this.first) |
| this.first.focus(); |
| } |
| |
| toc.onclick = function (e) { |
| e||(e=window.event); |
| hideTableOfContents(); |
| stopPropagation(e); |
| |
| if (e.cancel != undefined) |
| e.cancel = true; |
| |
| if (e.returnValue != undefined) |
| e.returnValue = false; |
| |
| return false; |
| }; |
| |
| toc.style.position = "absolute"; |
| toc.style.zIndex = "300"; |
| toc.style.width = "60%"; |
| toc.style.maxWidth = "30em"; |
| toc.style.height = "30em"; |
| toc.style.overflow = "auto"; |
| toc.style.top = "auto"; |
| toc.style.right = "auto"; |
| toc.style.left = "4em"; |
| toc.style.bottom = "4em"; |
| toc.style.padding = "1em"; |
| toc.style.background = "rgb(240,240,240)"; |
| toc.style.borderStyle = "solid"; |
| toc.style.borderWidth = "2px"; |
| toc.style.fontSize = "60%"; |
| |
| document.body.insertBefore(toc, document.body.firstChild); |
| return toc; |
| } |
| |
| function replaceByNonBreakingSpace(str) |
| { |
| for (var i = 0; i < str.length; ++i) |
| str[i] = 160; |
| } |
| |
| |
| function initOutliner() |
| { |
| var items = document.getElementsByTagName("LI"); |
| |
| for (var i = 0; i < items.length; ++i) |
| { |
| var target = items[i]; |
| |
| if (!hasClass(target.parentNode, "outline")) |
| continue; |
| |
| target.onclick = outlineClick; |
| |
| if (!ns_pos) |
| { |
| target.onmouseover = hoverOutline; |
| target.onmouseout = unhoverOutline; |
| } |
| |
| if (foldable(target)) |
| { |
| target.foldable = true; |
| target.onfocus = function () {outline = this;}; |
| target.onblur = function () {outline = null;}; |
| |
| if (!target.getAttribute("tabindex")) |
| target.setAttribute("tabindex", "0"); |
| |
| if (hasClass(target, "expand")) |
| unfold(target); |
| else |
| fold(target); |
| } |
| else |
| { |
| addClass(target, "nofold"); |
| target.visible = true; |
| target.foldable = false; |
| } |
| } |
| } |
| |
| function foldable(item) |
| { |
| if (!item || item.nodeType != 1) |
| return false; |
| |
| var node = item.firstChild; |
| |
| while (node) |
| { |
| if (node.nodeType == 1 && isBlock(node)) |
| return true; |
| |
| node = node.nextSibling; |
| } |
| |
| return false; |
| } |
| |
| function fold(item) |
| { |
| if (item) |
| { |
| removeClass(item, "unfolded"); |
| addClass(item, "folded"); |
| } |
| |
| var node = item ? item.firstChild : null; |
| |
| while (node) |
| { |
| if (node.nodeType == 1 && isBlock(node)) // element |
| { |
| // note that getElementStyle won't work for Safari 1.3 |
| node.display = getElementStyle(node, "display", "display"); |
| node.style.display = "none"; |
| node.style.visibility = "hidden"; |
| } |
| |
| node = node.nextSibling; |
| } |
| |
| item.visible = false; |
| } |
| |
| function unfold(item) |
| { |
| if (item) |
| { |
| addClass(item, "unfolded"); |
| removeClass(item, "folded"); |
| } |
| |
| var node = item ? item.firstChild : null; |
| |
| while (node) |
| { |
| if (node.nodeType == 1 && isBlock(node)) // element |
| { |
| // with fallback for Safari, see above |
| node.style.display = (node.display ? node.display : "block"); |
| node.style.visibility = "visible"; |
| } |
| |
| node = node.nextSibling; |
| } |
| |
| item.visible = true; |
| } |
| |
| function outlineClick(e) |
| { |
| var rightclick = false; |
| var target; |
| |
| if (!e) |
| var e = window.event; |
| |
| if (e.target) |
| target = e.target; |
| else if (e.srcElement) |
| target = e.srcElement; |
| |
| // work around Safari bug |
| if (target.nodeType == 3) |
| target = target.parentNode; |
| |
| while (target && target.visible == undefined) |
| target = target.parentNode; |
| |
| if (!target) |
| return true; |
| |
| if (e.which) |
| rightclick = (e.which == 3); |
| else if (e.button) |
| rightclick = (e.button == 2); |
| |
| if (!rightclick && target.visible != undefined) |
| { |
| if (target.foldable) |
| { |
| if (target.visible) |
| fold(target); |
| else |
| unfold(target); |
| } |
| |
| stopPropagation(e); |
| e.cancel = true; |
| e.returnValue = false; |
| } |
| |
| return false; |
| } |
| |
| function hoverOutline(e) |
| { |
| var target; |
| |
| if (!e) |
| var e = window.event; |
| |
| if (e.target) |
| target = e.target; |
| else if (e.srcElement) |
| target = e.srcElement; |
| |
| // work around Safari bug |
| if (target.nodeType == 3) |
| target = target.parentNode; |
| |
| while (target && target.visible == undefined) |
| target = target.parentNode; |
| |
| if (target && target.foldable) |
| target.style.cursor = "pointer"; |
| |
| return true; |
| } |
| |
| function unhoverOutline(e) |
| { |
| var target; |
| |
| if (!e) |
| var e = window.event; |
| |
| if (e.target) |
| target = e.target; |
| else if (e.srcElement) |
| target = e.srcElement; |
| |
| // work around Safari bug |
| if (target.nodeType == 3) |
| target = target.parentNode; |
| |
| while (target && target.visible == undefined) |
| target = target.parentNode; |
| |
| if (target) |
| target.style.cursor = "default"; |
| |
| return true; |
| } |
| |
| |
| function stopPropagation(e) |
| { |
| if (window.event) |
| { |
| window.event.cancelBubble = true; |
| //window.event.returnValue = false; |
| } |
| else if (e) |
| { |
| e.cancelBubble = true; |
| e.stopPropagation(); |
| //e.preventDefault(); |
| } |
| } |
| |
| /* can't rely on display since we set that to none to hide things */ |
| function isBlock(elem) |
| { |
| var tag = elem.nodeName; |
| |
| return tag == "OL" || tag == "UL" || tag == "P" || |
| tag == "LI" || tag == "TABLE" || tag == "PRE" || |
| tag == "H1" || tag == "H2" || tag == "H3" || |
| tag == "H4" || tag == "H5" || tag == "H6" || |
| tag == "BLOCKQUOTE" || tag == "ADDRESS"; |
| } |
| |
| function getElementStyle(elem, IEStyleProp, CSSStyleProp) |
| { |
| if (elem.currentStyle) |
| { |
| return elem.currentStyle[IEStyleProp]; |
| } |
| else if (window.getComputedStyle) |
| { |
| var compStyle = window.getComputedStyle(elem, ""); |
| return compStyle.getPropertyValue(CSSStyleProp); |
| } |
| return ""; |
| } |
| |
| // works with text/html and text/xhtml+xml with thanks to Simon Willison |
| function createElement(element) |
| { |
| if (typeof document.createElementNS != 'undefined') |
| { |
| return document.createElementNS('http://www.w3.org/1999/xhtml', element); |
| } |
| |
| if (typeof document.createElement != 'undefined') |
| { |
| return document.createElement(element); |
| } |
| |
| return false; |
| } |
| |
| // designed to work with both text/html and text/xhtml+xml |
| function getElementsByTagName(name) |
| { |
| if (typeof document.getElementsByTagNameNS != 'undefined') |
| { |
| return document.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', name); |
| } |
| |
| if (typeof document.getElementsByTagName != 'undefined') |
| { |
| return document.getElementsByTagName(name); |
| } |
| |
| return null; |
| } |
| |
| /* |
| // clean alternative to innerHTML method, but on IE6 |
| // it doesn't work with named entities like |
| // which need to be replaced by numeric entities |
| function insertText(element, text) |
| { |
| try |
| { |
| element.textContent = text; // DOM3 only |
| } |
| catch (e) |
| { |
| if (element.firstChild) |
| { |
| // remove current children |
| while (element.firstChild) |
| element.removeChild(element.firstChild); |
| } |
| |
| element.appendChild(document.createTextNode(text)); |
| } |
| } |
| |
| // as above, but as method of all element nodes |
| // doesn't work in IE6 which doesn't allow you to |
| // add methods to the HTMLElement prototype |
| if (HTMLElement != undefined) |
| { |
| HTMLElement.prototype.insertText = function(text) { |
| var element = this; |
| |
| try |
| { |
| element.textContent = text; // DOM3 only |
| } |
| catch (e) |
| { |
| if (element.firstChild) |
| { |
| // remove current children |
| while (element.firstChild) |
| element.removeChild(element.firstChild); |
| } |
| |
| element.appendChild(document.createTextNode(text)); |
| } |
| }; |
| } |
| */ |
| |
| function getSelectedText() |
| { |
| try |
| { |
| if (window.getSelection) |
| return window.getSelection().toString(); |
| |
| if (document.getSelection) |
| return document.getSelection().toString(); |
| |
| if (document.selection) |
| return document.selection.createRange().text; |
| } |
| catch (e) |
| { |
| return ""; |
| } |
| return ""; |
| } |