/* 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/Dcha, " + "o Re pág y Av pág. Use S y B para cambiar el tamaño de fuente."; var strings_ca = { "slide":"pàg..", "help?":"Ajuda", "contents?":"Índex", "table of contents":"taula de continguts", "Table of Contents":"Taula de Continguts", "restart presentation":"Reiniciar presentació", "restart?":"Inici" }; strings_ca[helpText] = "Utilitzi el ratolí, barra espaiadora, tecles Esq./Dta. " + "o Re pàg y Av pàg. Usi S i B per canviar grandària de font."; 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, "ca":strings_ca, "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. // // 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) // Left 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) // Right 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
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
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
// 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, ">"); 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 ""; }