/* slidy.js Copyright (c) 2005-2011 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 Defines single name "w3c_slidy" in global namespace Adds event handlers without trampling on any others */ // the slidy object implementation var w3c_slidy = { // classify which kind of browser we're running under ns_pos: (typeof window.pageYOffset!='undefined'), khtml: ((navigator.userAgent).indexOf("KHTML") >= 0 ? true : false), opera: ((navigator.userAgent).indexOf("Opera") >= 0 ? true : false), ipad: ((navigator.userAgent).indexOf("iPad") >= 0 ? true : false), iphone: ((navigator.userAgent).indexOf("iPhone") >= 0 ? true : false), android: ((navigator.userAgent).indexOf("Android") >= 0 ? true : false), ie: (typeof document.all != "undefined" && !this.opera), ie6: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 6") != -1), ie7: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 7") != -1), ie8: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 8") != -1), ie9: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 9") != -1), // data for swipe and double tap detection on touch screens last_tap: 0, prev_tap: 0, start_x: 0, start_y: 0, delta_x: 0, delta_y: 0, // are we running as XHTML? (doesn't work on Opera) is_xhtml: /xml/.test(document.contentType), slide_number: 0, // integer slide count: 0, 1, 2, ... slide_number_element: null, // element containing slide number slides: [], // set to array of slide div's notes: [], // set to array of handout div's backgrounds: [], // set to array of background div's toolbar: null, // element containing toolbar title: null, // document title last_shown: null, // last incrementally shown item eos: null, // span element for end of slide indicator toc: null, // table of contents outline: null, // outline element with the focus selected_text_len: 0, // length of drag selection on document view_all: 0, // 1 to view all slides + handouts want_toolbar: true, // user preference to show/hide toolbar mouse_click_enabled: true, // enables left click for next slide scroll_hack: 0, // IE work around for position: fixed disable_slide_click: false, // used by clicked anchors lang: "en", // updated to language specified by html file help_anchor: null, // used for keyboard focus hack in showToolbar() help_page: "http://www.w3.org/Talks/Tools/Slidy2/help/help.html", help_text: "Navigate with mouse click, space bar, Cursor Left/Right, " + "or Pg Up and Pg Dn. Use S and B to change font size.", size_index: 0, size_adjustment: 0, sizes: new Array("10pt", "12pt", "14pt", "16pt", "18pt", "20pt", "22pt", "24pt", "26pt", "28pt", "30pt", "32pt"), // needed for efficient resizing last_width: 0, last_height: 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 objects: [], // attach initialiation event handlers set_up: function () { var init = function() { w3c_slidy.init(); }; if (typeof window.addEventListener != "undefined") window.addEventListener("load", init, false); else window.attachEvent("onload", init); }, hide_slides: function () { if (document.body && !w3c_slidy.initialized) document.body.style.visibility = "hidden"; else setTimeout(w3c_slidy.hide_slides, 50); }, // hack to persuade IE to compute correct document height // as needed for simulating fixed positioning of toolbar ie_hack: function () { window.resizeBy(0,-1); window.resizeBy(0, 1); }, init: function () { //alert("slidy starting test 10"); document.body.style.visibility = "visible"; this.init_localization(); this.add_toolbar(); this.wrap_implicit_slides(); this.collect_slides(); this.collect_notes(); this.collect_backgrounds(); this.objects = document.body.getElementsByTagName("object"); this.patch_anchors(); this.slide_number = this.find_slide_number(location.href); window.offscreenbuffering = true; this.size_adjustment = this.find_size_adjust(); this.time_left = this.find_duration(); this.hide_image_toolbar(); // suppress IE image toolbar popup this.init_outliner(); // activate fold/unfold support this.title = document.title; this.keyboardless = (this.ipad||this.iphone||this.android); if (this.keyboardless) { w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden") this.want_toolbar = 0; } // work around for opera bug this.is_xhtml = (document.body.tagName == "BODY" ? false : true); if (this.slides.length > 0) { var slide = this.slides[this.slide_number]; if (this.slide_number > 0) { this.set_visibility_all_incremental("visible"); this.last_shown = this.previous_incremental_item(null); this.set_eos_status(true); } else { this.last_shown = null; this.set_visibility_all_incremental("hidden"); this.set_eos_status(!this.next_incremental_item(this.last_shown)); } this.set_location(); this.add_class(this.slides[0], "first-slide"); w3c_slidy.show_slide(slide); } this.toc = this.table_of_contents(); this.add_initial_prompt(); // bind event handlers without interfering with custom page scripts // Tap events behave too weirdly to support clicks reliably on // iPhone and iPad, so exclude these from click handler if (!this.keyboardless) this.add_listener(document.body, "click", this.mouse_button_click); this.add_listener(document, "keydown", this.key_down); this.add_listener(document, "keypress", this.key_press); this.add_listener(window, "resize", this.resized); this.add_listener(window, "scroll", this.scrolled); this.add_listener(window, "unload", this.unloaded); this.add_listener(document, "touchstart", this.touchstart); this.add_listener(document, "touchmove", this.touchmove); this.add_listener(document, "touchend", this.touchend); // this seems to be a debugging hack //if (!document.body.onclick) // document.body.onclick = function () { }; this.single_slide_view(); //this.set_location(); this.resized(); if (this.ie7) setTimeout(w3c_slidy.ie_hack, 100); this.show_toolbar(); // for back button detection setInterval(function () { w3c_slidy.check_location(); }, 200); w3c_slidy.initialized = true; }, // create div element with links to each slide table_of_contents: function () { var toc = this.create_element("div"); this.add_class(toc, "slidy_toc hidden"); //toc.setAttribute("tabindex", "0"); var heading = this.create_element("div"); this.add_class(heading, "toc-heading"); heading.innerHTML = this.localize("Table of Contents"); toc.appendChild(heading); var previous = null; for (var i = 0; i < this.slides.length; ++i) { var title = this.has_class(this.slides[i], "title"); var num = document.createTextNode((i + 1) + ". "); toc.appendChild(num); var a = this.create_element("a"); a.setAttribute("href", "#(" + (i+1) + ")"); if (title) this.add_class(a, "titleslide"); var name = document.createTextNode(this.slide_name(i)); a.appendChild(name); a.onclick = w3c_slidy.toc_click; a.onkeydown = w3c_slidy.toc_key_down; a.previous = previous; if (previous) previous.next = a; toc.appendChild(a); if (i == 0) toc.first = a; if (i < this.slides.length - 1) { var br = this.create_element("br"); toc.appendChild(br); } previous = a; } toc.focus = function () { if (this.first) this.first.focus(); } toc.onmouseup = w3c_slidy.mouse_button_up; toc.onclick = function (e) { e||(e=window.event); if (w3c_slidy.selected_text_len <= 0) w3c_slidy.hide_table_of_contents(true); w3c_slidy.stop_propagation(e); if (e.cancel != undefined) e.cancel = true; if (e.returnValue != undefined) e.returnValue = false; return false; }; document.body.insertBefore(toc, document.body.firstChild); return toc; }, is_shown_toc: function () { return !w3c_slidy.has_class(w3c_slidy.toc, "hidden"); }, show_table_of_contents: function () { w3c_slidy.remove_class(w3c_slidy.toc, "hidden"); var toc = w3c_slidy.toc; toc.focus(); if (w3c_slidy.ie7 && w3c_slidy.slide_number == 0) setTimeout(w3c_slidy.ie_hack, 100); }, hide_table_of_contents: function (focus) { w3c_slidy.add_class(w3c_slidy.toc, "hidden"); if (focus && !w3c_slidy.opera) w3c_slidy.help_anchor.focus(); }, toggle_table_of_contents: function () { if (w3c_slidy.is_shown_toc()) w3c_slidy.hide_table_of_contents(true); else w3c_slidy.show_table_of_contents(); }, // called on clicking toc entry toc_click: function (e) { if (!e) e = window.event; var target = w3c_slidy.get_target(e); if (target && target.nodeType == 1) { var uri = target.getAttribute("href"); if (uri) { //alert("going to " + uri); var slide = w3c_slidy.slides[w3c_slidy.slide_number]; w3c_slidy.hide_slide(slide); w3c_slidy.slide_number = w3c_slidy.find_slide_number(uri); slide = w3c_slidy.slides[w3c_slidy.slide_number]; w3c_slidy.last_shown = null; w3c_slidy.set_location(); w3c_slidy.set_visibility_all_incremental("hidden"); w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown)); w3c_slidy.show_slide(slide); //target.focus(); try { if (!w3c_slidy.opera) w3c_slidy.help_anchor.focus(); } catch (e) { } } } w3c_slidy.hide_table_of_contents(true); if (w3c_slidy.ie7) w3c_slidy.ie_hack(); w3c_slidy.stop_propagation(e); return w3c_slidy.cancel(e); }, // called onkeydown for toc entry toc_key_down: function (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 = w3c_slidy.slides[w3c_slidy.slide_number]; w3c_slidy.hide_slide(slide); w3c_slidy.slide_number = w3c_slidy.find_slide_number(uri); slide = w3c_slidy.slides[w3c_slidy.slide_number]; w3c_slidy.last_shown = null; w3c_slidy.set_location(); w3c_slidy.set_visibility_all_incremental("hidden"); w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown)); w3c_slidy.show_slide(slide); //target.focus(); try { if (!w3c_slidy.opera) w3c_slidy.help_anchor.focus(); } catch (e) { } } w3c_slidy.hide_table_of_contents(true); if (self.ie7) w3c_slidy.ie_hack(); return w3c_slidy.cancel(event); } if (key == 40 && this.next) { this.next.focus(); return w3c_slidy.cancel(event); } if (key == 38 && this.previous) { this.previous.focus(); return w3c_slidy.cancel(event); } return true; }, touchstart: function (e) { //e.preventDefault(); this.prev_tap = this.last_tap; this.last_tap = (new Date).getTime(); var tap_delay = this.last_tap - this.prev_tap; if (tap_delay <= 200) { // double tap } var touch = e.touches[0]; this.start_x = touch.pageX; this.start_y = touch.pageY; this.delta_x = this.delta_y = 0; }, touchmove: function (e) { //e.preventDefault(); var touch = e.touches[0]; this.delta_x = touch.pageX - this.start_x; this.delta_y = touch.pageY - this.start_y; }, touchend: function (e) { //e.preventDefault(); var delay = (new Date).getTime() - this.last_tap; var dx = this.delta_x; var dy = this.delta_y; var abs_dx = Math.abs(dx); var abs_dy = Math.abs(dy); if (delay < 500 && (abs_dx > 100 || abs_dy > 100)) { if (abs_dx > 0.5 * abs_dy) { if (dx < 0) w3c_slidy.next_slide(true); else w3c_slidy.previous_slide(true); } else if (abs_dy > 2 * abs_dx) { w3c_slidy.toggle_table_of_contents(); } } }, // ### OBSOLETE ### before_print: function () { this.show_all_slides(); this.hide_toolbar(); alert("before print"); }, // ### OBSOLETE ### after_print: function () { if (!this.view_all) { this.single_slide_view(); this.show_toolbar(); } alert("after print"); }, // ### OBSOLETE ### print_slides: function () { this.before_print(); window.print(); this.after_print(); }, // ### OBSOLETE ?? ### toggle_view: function () { if (this.view_all) { this.single_slide_view(); this.show_toolbar(); this.view_all = 0; } else { this.show_all_slides(); this.hide_toolbar(); this.view_all = 1; } }, // prepare for printing ### OBSOLETE ### show_all_slides: function () { this.remove_class(document.body, "single_slide"); this.set_visibility_all_incremental("visible"); }, // restore after printing ### OBSOLETE ### single_slide_view: function () { this.add_class(document.body, "single_slide"); this.set_visibility_all_incremental("visible"); this.last_shown = this.previous_incremental_item(null); }, // suppress IE's image toolbar pop up hide_image_toolbar: function () { if (!this.ns_pos) { var images = document.getElementsByTagName("IMG"); for (var i = 0; i < images.length; ++i) images[i].setAttribute("galleryimg", "no"); } }, unloaded: function (e) { //alert("unloaded"); }, // Safari and Konqueror don't yet support getComputedStyle() // and they always reload page when location.href is updated is_KHTML: function () { var agent = navigator.userAgent; return (agent.indexOf("KHTML") >= 0 ? true : false); }, // find slide name from first h1 element // default to document title + slide number slide_name: function (index) { var name = null; var slide = this.slides[index]; var heading = this.find_heading(slide); if (heading) name = this.extract_text(heading); if (!name) name = this.title + "(" + (index + 1) + ")"; name.replace(/\&/g, "&"); name.replace(/\</g, "<"); name.replace(/\>/g, ">"); return name; }, // find first h1 element in DOM tree find_heading: function (node) { if (!node || node.nodeType != 1) return null; if (node.nodeName == "H1" || node.nodeName == "h1") return node; var child = node.firstChild; while (child) { node = this.find_heading(child); if (node) return node; child = child.nextSibling; } return null; }, // recursively extract text from DOM tree extract_text: function (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 + this.extract_text(node); node = node.nextSibling; } return text; } return ""; }, // find copyright text from meta element find_copyright: function () { 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; }, find_size_adjust: function () { 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 1; }, // <meta name="duration" content="20" /> for 20 minutes find_duration: function () { 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 == "duration") return 60000 * content; } return null; }, replace_by_non_breaking_space: function (str) { for (var i = 0; i < str.length; ++i) str[i] = 160; }, // ### CHECK ME ### is use of "li" okay for text/html? // for XHTML do we also need to specify namespace? init_outliner: function () { var items = document.getElementsByTagName("li"); for (var i = 0; i < items.length; ++i) { var target = items[i]; if (!this.has_class(target.parentNode, "outline")) continue; target.onclick = this.outline_click; /* ### more work needed for IE6 if (!this.ns_pos) { target.onmouseover = this.hover_outline; target.onmouseout = this.unhover_outline; } */ if (this.foldable(target)) { target.foldable = true; target.onfocus = function () {w3c_slidy.outline = this;}; target.onblur = function () {w3c_slidy.outline = null;}; if (!target.getAttribute("tabindex")) target.setAttribute("tabindex", "0"); if (this.has_class(target, "expand")) this.unfold(target); else this.fold(target); } else { this.add_class(target, "nofold"); target.visible = true; target.foldable = false; } } }, foldable: function (item) { if (!item || item.nodeType != 1) return false; var node = item.firstChild; while (node) { if (node.nodeType == 1 && this.is_block(node)) return true; node = node.nextSibling; } return false; }, // ### CHECK ME ### switch to add/remove "hidden" class fold: function (item) { if (item) { this.remove_class(item, "unfolded"); this.add_class(item, "folded"); } var node = item ? item.firstChild : null; while (node) { if (node.nodeType == 1 && this.is_block(node)) // element { w3c_slidy.add_class(node, "hidden"); } node = node.nextSibling; } item.visible = false; }, // ### CHECK ME ### switch to add/remove "hidden" class unfold: function (item) { if (item) { this.add_class(item, "unfolded"); this.remove_class(item, "folded"); } var node = item ? item.firstChild : null; while (node) { if (node.nodeType == 1 && this.is_block(node)) // element { w3c_slidy.remove_class(node, "hidden"); } node = node.nextSibling; } item.visible = true; }, outline_click: function (e) { if (!e) e = window.event; var rightclick = false; var target = w3c_slidy.get_target(e); 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) w3c_slidy.fold(target); else w3c_slidy.unfold(target); } w3c_slidy.stop_propagation(e); e.cancel = true; e.returnValue = false; } return false; }, add_initial_prompt: function () { var prompt = this.create_element("div"); prompt.setAttribute("class", "initial_prompt"); var p1 = this.create_element("p"); prompt.appendChild(p1); p1.setAttribute("class", "help"); if (this.keyboardless) p1.innerHTML = "swipe left to move to next slide"; else p1.innerHTML = "Space, Right Arrow or swipe left to move to " + "next slide, click help below for more details"; this.add_listener(prompt, "click", function (e) { document.body.removeChild(prompt); w3c_slidy.stop_propagation(e); if (e.cancel != undefined) e.cancel = true; if (e.returnValue != undefined) e.returnValue = false; return false; }); document.body.appendChild(prompt); this.initial_prompt = prompt; setTimeout(function() {document.body.removeChild(prompt);}, 5000); }, add_toolbar: function () { var counter, page; this.toolbar = this.create_element("div"); this.toolbar.setAttribute("class", "toolbar"); // a reasonably behaved browser if (this.ns_pos || !this.ie6) { var right = this.create_element("div"); right.setAttribute("style", "float: right; text-align: right"); counter = this.create_element("span") counter.innerHTML = this.localize("slide") + " n/m"; right.appendChild(counter); this.toolbar.appendChild(right); var left = this.create_element("div"); left.setAttribute("style", "text-align: left"); // global end of slide indicator this.eos = this.create_element("span"); this.eos.innerHTML = "* "; left.appendChild(this.eos); var help = this.create_element("a"); help.setAttribute("href", this.help_page); help.setAttribute("title", this.localize(this.help_text)); help.innerHTML = this.localize("help?"); left.appendChild(help); this.help_anchor = help; // save for focus hack var gap1 = document.createTextNode(" "); left.appendChild(gap1); var contents = this.create_element("a"); contents.setAttribute("href", "javascript:w3c_slidy.toggle_table_of_contents()"); contents.setAttribute("title", this.localize("table of contents")); contents.innerHTML = this.localize("contents?"); left.appendChild(contents); var gap2 = document.createTextNode(" "); left.appendChild(gap2); var copyright = this.find_copyright(); if (copyright) { var span = this.create_element("span"); span.className = "copyright"; span.innerHTML = copyright; left.appendChild(span); } this.toolbar.setAttribute("tabindex", "0"); this.toolbar.appendChild(left); } else // IE6 so need to work around its poor CSS support { this.toolbar.style.position = (this.ie7 ? "fixed" : "absolute"); this.toolbar.style.zIndex = "200"; this.toolbar.style.width = "99.9%"; this.toolbar.style.height = "1.2em"; this.toolbar.style.top = "auto"; this.toolbar.style.bottom = "0"; this.toolbar.style.left = "0"; this.toolbar.style.right = "0"; this.toolbar.style.textAlign = "left"; this.toolbar.style.fontSize = "60%"; this.toolbar.style.color = "red"; this.toolbar.borderWidth = 0; this.toolbar.className = "toolbar"; this.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 = this.create_element("span"); sp.innerHTML = " * "; this.toolbar.appendChild(sp); this.eos = sp; // end of slide indicator var help = this.create_element("a"); help.setAttribute("href", this.help_page); help.setAttribute("title", this.localize(this.help_text)); help.innerHTML = this.localize("help?"); this.toolbar.appendChild(help); this.help_anchor = help; // save for focus hack var gap1 = document.createTextNode(" "); this.toolbar.appendChild(gap1); var contents = this.create_element("a"); contents.setAttribute("href", "javascript:toggleTableOfContents()"); contents.setAttribute("title", this.localize("table of contents".localize)); contents.innerHTML = this.localize("contents?"); this.toolbar.appendChild(contents); var gap2 = document.createTextNode(" "); this.toolbar.appendChild(gap2); var copyright = this.find_copyright(); if (copyright) { var span = this.create_element("span"); span.innerHTML = copyright; span.style.color = "black"; span.style.marginLeft = "0.5em"; this.toolbar.appendChild(span); } counter = this.create_element("div") counter.style.position = "absolute"; counter.style.width = "auto"; //"20%"; counter.style.height = "1.2em"; counter.style.top = "auto"; counter.style.bottom = 0; counter.style.right = "0"; counter.style.textAlign = "right"; counter.style.color = "red"; counter.style.background = "rgb(240,240,240)"; counter.innerHTML = this.localize("slide") + " n/m"; this.toolbar.appendChild(counter); } // ensure that click isn't passed through to the page this.toolbar.onclick = function (e) { if (!e) e = window.event; var target = e.target; if (!target && e.srcElement) target = e.srcElement; // work around Safari bug if (target && target.nodeType == 3) target = target.parentNode; w3c_slidy.stop_propagation(e); if (target && target.nodeName.toLowerCase() != "a") w3c_slidy.mouse_button_click(e); }; this.slide_number_element = counter; this.set_eos_status(false); document.body.appendChild(this.toolbar); }, // 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 wrap_implicit_slides: function () { 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"); this.add_class(div, "slide"); document.body.replaceChild(div, heading); div.appendChild(heading); while (node) { if (node.nodeType == 1) // an element { if (node.nodeName == "H1" || node.nodeName == "h1") break; if (node.nodeName == "DIV" || node.nodeName == "div") { if (this.has_class(node, "slide")) break; if (this.has_class(node, "handout")) break; } } next = node.nextSibling; node = document.body.removeChild(node); div.appendChild(node); node = next; } } }, // return new array of all slides collect_slides: function () { var slides = new Array(); var divs = document.body.getElementsByTagName("div"); for (var i = 0; i < divs.length; ++i) { div = divs.item(i); if (this.has_class(div, "slide")) { // add slide to collection slides[slides.length] = div; // hide each slide as it is found this.add_class(div, "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 (this.has_class(div, "background")) { // work around for Firefox SVG reload bug // which otherwise replaces 1st SVG graphic with 2nd div.style.display = "block"; } } this.slides = slides; }, // return new array of all <div class="handout"> collect_notes: function () { var notes = new Array(); var divs = document.body.getElementsByTagName("div"); for (var i = 0; i < divs.length; ++i) { div = divs.item(i); if (this.has_class(div, "handout")) { // add note to collection notes[notes.length] = div; // and hide it this.add_class(div, "hidden"); } } this.notes = notes; }, // return new array of all <div class="background"> // including named backgrounds e.g. class="background titlepage" collect_backgrounds: function () { var backgrounds = new Array(); var divs = document.body.getElementsByTagName("div"); for (var i = 0; i < divs.length; ++i) { div = divs.item(i); if (this.has_class(div, "background")) { // add background to collection backgrounds[backgrounds.length] = div; // and hide it this.add_class(div, "hidden"); } } this.backgrounds = backgrounds; }, // set click handlers on all anchors patch_anchors: function () { var self = w3c_slidy; var handler = function (event) { // compare this.href with location.href // for link to another slide in this doc if (self.page_address(this.href) == self.page_address(location.href)) { // yes, so find new slide number var newslidenum = self.find_slide_number(this.href); if (newslidenum != self.slide_number) { var slide = self.slides[self.slide_number]; self.hide_slide(slide); self.slide_number = newslidenum; slide = self.slides[self.slide_number]; self.show_slide(slide); self.set_location(); } } else w3c_slidy.stop_propagation(event); // else if (this.target == null) // location.href = this.href; this.blur(); self.disable_slide_click = true; }; var anchors = document.body.getElementsByTagName("a"); for (var i = 0; i < anchors.length; ++i) { if (window.addEventListener) anchors[i].addEventListener("click", handler, false); else anchors[i].attachEvent("onclick", handler); } }, // ### CHECK ME ### see which functions are invoked via setTimeout // either directly or indirectly for use of w3c_slidy vs this show_slide_number: function () { var timer = w3c_slidy.get_timer(); w3c_slidy.slide_number_element.innerHTML = timer + w3c_slidy.localize("slide") + " " + (w3c_slidy.slide_number + 1) + "/" + w3c_slidy.slides.length; }, // every 200mS check if the location has been changed as a // result of the user activating the Back button/menu item // doesn't work for Opera < 9.5 check_location: function () { var hash = location.hash; if (w3c_slidy.slide_number > 0 && (hash == "" || hash == "#")) w3c_slidy.goto_slide(0); else if (hash.length > 2 && hash != "#("+(w3c_slidy.slide_number+1)+")") { var num = parseInt(location.hash.substr(2)); if (!isNaN(num)) w3c_slidy.goto_slide(num-1); } if (w3c_slidy.time_left && w3c_slidy.slide_number > 0) { w3c_slidy.show_slide_number(); if (w3c_slidy.time_left > 0) w3c_slidy.time_left -= 200; } }, get_timer: function () { var timer = ""; if (w3c_slidy.time_left) { var mins, secs; secs = Math.floor(w3c_slidy.time_left/1000); mins = Math.floor(secs / 60); secs = secs % 60; timer = (mins ? mins+"m" : "") + secs + "s "; } return timer; }, // this doesn't push location onto history stack for IE // for which a hidden iframe hack is needed: load page into // the iframe with script that set's parent's location.hash // but that won't work for standalone use unless we can // create the page dynamically via a javascript: URL // ### use history.pushState if available set_location: function () { var uri = w3c_slidy.page_address(location.href); var hash = "#(" + (w3c_slidy.slide_number+1) + ")"; if (w3c_slidy.slide_number >= 0) uri = uri + hash; if (typeof(history.pushState) != "undefined") { document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")"; history.pushState(0, document.title, hash); w3c_slidy.show_slide_number(); return; } if (w3c_slidy.ie && (w3c_slidy.ie6 || w3c_slidy.ie7)) w3c_slidy.push_hash(hash); if (uri != location.href) // && !khtml location.href = uri; if (this.khtml) hash = "(" + (w3c_slidy.slide_number+1) + ")"; if (!this.ie && location.hash != hash && location.hash != "") location.hash = hash; document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")"; w3c_slidy.show_slide_number(); }, page_address: function (uri) { var i = uri.indexOf("#"); if (i < 0) i = uri.indexOf("%23"); // check if anchor is entire page if (i < 0) return uri; // yes return uri.substr(0, i); }, // only used for IE6 and IE7 on_frame_loaded: function (hash) { location.hash = hash; var uri = w3c_slidy.page_address(location.href); location.href = uri + hash; }, // history hack with thanks to Bertrand Le Roy push_hash: function (hash) { if (hash == "") hash = "#(1)"; window.location.hash = hash; var doc = document.getElementById("historyFrame").contentWindow.document; doc.open("javascript:'<html></html>'"); doc.write("<html><head><script type=\"text/javascript\">window.parent.w3c_slidy.on_frame_loaded('"+ (hash) + "');</script></head><body>hello mum</body></html>"); doc.close(); }, // 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 find_slide_number: function (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 > this.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 > this.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" && this.has_class(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; }, previous_slide: function (incremental) { if (!w3c_slidy.view_all) { var slide; if ((incremental || w3c_slidy.slide_number == 0) && w3c_slidy.last_shown != null) { w3c_slidy.last_shown = w3c_slidy.hide_previous_item(w3c_slidy.last_shown); w3c_slidy.set_eos_status(false); } else if (w3c_slidy.slide_number > 0) { slide = w3c_slidy.slides[w3c_slidy.slide_number]; w3c_slidy.hide_slide(slide); w3c_slidy.slide_number = w3c_slidy.slide_number - 1; slide = w3c_slidy.slides[w3c_slidy.slide_number]; w3c_slidy.set_visibility_all_incremental("visible"); w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null); w3c_slidy.set_eos_status(true); w3c_slidy.show_slide(slide); } w3c_slidy.set_location(); if (!w3c_slidy.ns_pos) w3c_slidy.refresh_toolbar(200); } }, next_slide: function (incremental) { if (!w3c_slidy.view_all) { var slide, last = w3c_slidy.last_shown; if (incremental || w3c_slidy.slide_number == w3c_slidy.slides.length - 1) w3c_slidy.last_shown = w3c_slidy.reveal_next_item(w3c_slidy.last_shown); if ((!incremental || w3c_slidy.last_shown == null) && w3c_slidy.slide_number < w3c_slidy.slides.length - 1) { slide = w3c_slidy.slides[w3c_slidy.slide_number]; w3c_slidy.hide_slide(slide); w3c_slidy.slide_number = w3c_slidy.slide_number + 1; slide = w3c_slidy.slides[w3c_slidy.slide_number]; w3c_slidy.last_shown = null; w3c_slidy.set_visibility_all_incremental("hidden"); w3c_slidy.show_slide(slide); } else if (!w3c_slidy.last_shown) { if (last && incremental) w3c_slidy.last_shown = last; } w3c_slidy.set_location(); w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown)); if (!w3c_slidy.ns_pos) w3c_slidy.refresh_toolbar(200); } }, // to first slide with nothing revealed // i.e. state at start of presentation first_slide: function () { if (!w3c_slidy.view_all) { var slide; if (w3c_slidy.slide_number != 0) { slide = w3c_slidy.slides[w3c_slidy.slide_number]; w3c_slidy.hide_slide(slide); w3c_slidy.slide_number = 0; slide = w3c_slidy.slides[w3c_slidy.slide_number]; w3c_slidy.last_shown = null; w3c_slidy.set_visibility_all_incremental("hidden"); w3c_slidy.show_slide(slide); } w3c_slidy.set_eos_status( !w3c_slidy.next_incremental_item(w3c_slidy.last_shown)); w3c_slidy.set_location(); } }, // goto last slide with everything revealed // i.e. state at end of presentation last_slide: function () { if (!w3c_slidy.view_all) { var slide; w3c_slidy.last_shown = null; //revealNextItem(lastShown); if (w3c_slidy.last_shown == null && w3c_slidy.slide_number < w3c_slidy.slides.length - 1) { slide = w3c_slidy.slides[w3c_slidy.slide_number]; w3c_slidy.hide_slide(slide); w3c_slidy.slide_number = w3c_slidy.slides.length - 1; slide = w3c_slidy.slides[w3c_slidy.slide_number]; w3c_slidy.set_visibility_all_incremental("visible"); w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null); w3c_slidy.show_slide(slide); } else { w3c_slidy.set_visibility_all_incremental("visible"); w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null); } w3c_slidy.set_eos_status(true); w3c_slidy.set_location(); } }, // ### check this and consider add/remove class set_eos_status: function (state) { if (this.eos) this.eos.style.color = (state ? "rgb(240,240,240)" : "red"); }, // first slide is 0 goto_slide: function (num) { //alert("going to slide " + (num+1)); var slide = w3c_slidy.slides[w3c_slidy.slide_number]; w3c_slidy.hide_slide(slide); w3c_slidy.slide_number = num; slide = w3c_slidy.slides[w3c_slidy.slide_number]; w3c_slidy.last_shown = null; w3c_slidy.set_visibility_all_incremental("hidden"); w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown)); document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")"; w3c_slidy.show_slide(slide); w3c_slidy.show_slide_number(); }, show_slide: function (slide) { this.sync_background(slide); window.scrollTo(0,0); this.remove_class(slide, "hidden"); }, hide_slide: function (slide) { this.add_class(slide, "hidden"); }, // show just the backgrounds pertinent to this slide // when slide background-color is transparent // this should now work with rgba color values sync_background: function (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" || bgColor.indexOf("rgba") >= 0 || bgColor.indexOf("opacity") >= 0) { var slideClass = this.get_class_list(slide); for (var i = 0; i < this.backgrounds.length; i++) { background = this.backgrounds[i]; var bgClass = this.get_class_list(background); if (this.matching_background(slideClass, bgClass)) this.remove_class(background, "hidden"); else this.add_class(background, "hidden"); } } else // forcibly hide all backgrounds this.hide_backgrounds(); }, hide_backgrounds: function () { for (var i = 0; i < this.backgrounds.length; i++) { background = this.backgrounds[i]; this.add_class(background, "hidden"); } }, // compare classes for slide and background matching_background: function (slideClass, bgClass) { var i, count, pattern, result; // define pattern as regular expression pattern = /\w+/g; // check background class names result = bgClass.match(pattern); for (i = count = 0; i < result.length; i++) { if (result[i] == "hidden") continue; if (result[i] == "background") continue; ++count; } if (count == 0) // default match return true; // check for matches and place result in array result = slideClass.match(pattern); // now check if desired name is present for background for (i = count = 0; i < result.length; i++) { if (result[i] == "hidden") continue; if (this.has_token(bgClass, result[i])) return true; } return false; }, resized: function () { 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 != w3c_slidy.last_width || height != w3c_slidy.last_height) { if (width >= 1100) w3c_slidy.size_index = 5; // 4 else if (width >= 1000) w3c_slidy.size_index = 4; // 3 else if (width >= 800) w3c_slidy.size_index = 3; // 2 else if (width >= 600) w3c_slidy.size_index = 2; // 1 else if (width) w3c_slidy.size_index = 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 <= w3c_slidy.size_index + w3c_slidy.size_adjustment && w3c_slidy.size_index + w3c_slidy.size_adjustment < w3c_slidy.sizes.length) w3c_slidy.size_index = w3c_slidy.size_index + w3c_slidy.size_adjustment; // enables cross browser use of relative width/height // on object elements for use with SVG and Flash media w3c_slidy.adjust_object_dimensions(width, height); if (document.body.style.fontSize != w3c_slidy.sizes[w3c_slidy.size_index]) { document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index]; } w3c_slidy.last_width = width; w3c_slidy.last_height = height; // force reflow to work around Mozilla bug if (w3c_slidy.ns_pos) { var slide = w3c_slidy.slides[w3c_slidy.slide_number]; w3c_slidy.hide_slide(slide); w3c_slidy.show_slide(slide); } // force correct positioning of toolbar w3c_slidy.refresh_toolbar(200); } }, scrolled: function () { if (w3c_slidy.toolbar && !w3c_slidy.ns_pos && !w3c_slidy.ie7) { w3c_slidy.hack_offset = w3c_slidy.scroll_x_offset(); // hide toolbar w3c_slidy.toolbar.style.display = "none"; // make it reappear later if (w3c_slidy.scrollhack == 0 && !w3c_slidy.view_all) { setTimeout(function () {w3c_slidy.show_toolbar(); }, 1000); w3c_slidy.scrollhack = 1; } } }, hide_toolbar: function () { w3c_slidy.add_class(w3c_slidy.toolbar, "hidden"); window.focus(); }, // used to ensure IE refreshes toolbar in correct position refresh_toolbar: function (interval) { if (!w3c_slidy.ns_pos && !w3c_slidy.ie7) { w3c_slidy.hide_toolbar(); setTimeout(function () {w3c_slidy.show_toolbar(); }, interval); } }, // restores toolbar after short delay show_toolbar: function () { if (w3c_slidy.want_toolbar) { w3c_slidy.toolbar.style.display = "block"; if (!w3c_slidy.ns_pos) { // adjust position to allow for scrolling var xoffset = w3c_slidy.scroll_x_offset(); w3c_slidy.toolbar.style.left = xoffset; w3c_slidy.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 w3c_slidy.toolbar.style.bottom = 0; //bottom; } w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden"); } w3c_slidy.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 (!w3c_slidy.opera) w3c_slidy.help_anchor.focus(); } catch (e) { } }, // invoked via F key toggle_toolbar: function () { if (!w3c_slidy.view_all) { if (w3c_slidy.has_class(w3c_slidy.toolbar, "hidden")) { w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden") w3c_slidy.want_toolbar = 1; } else { w3c_slidy.add_class(w3c_slidy.toolbar, "hidden") w3c_slidy.want_toolbar = 0; } } }, scroll_x_offset: function () { 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; }, scroll_y_offset: function () { 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 optimize_font_size: function () { var slide = w3c_slidy.slides[w3c_slidy.slide_number]; //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 + ")"); }, // from document object get_doc_height: function (doc) { 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"); }, get_window_height: function () { 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 }, document_height: function () { var sh, oh; sh = document.body.scrollHeight; oh = document.body.offsetHeight; if (sh && oh) { return (sh > oh ? sh : oh); } // no idea! return 0; }, smaller: function () { if (w3c_slidy.size_index > 0) { --w3c_slidy.size_index; } w3c_slidy.toolbar.style.display = "none"; document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index]; var slide = w3c_slidy.slides[w3c_slidy.slide_number]; w3c_slidy.hide_slide(slide); w3c_slidy.show_slide(slide); setTimeout(function () {w3c_slidy.show_toolbar(); }, 50); }, bigger: function () { if (w3c_slidy.size_index < w3c_slidy.sizes.length - 1) { ++w3c_slidy.size_index; } w3c_slidy.toolbar.style.display = "none"; document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index]; var slide = w3c_slidy.slides[w3c_slidy.slide_number]; w3c_slidy.hide_slide(slide); w3c_slidy.show_slide(slide); setTimeout(function () {w3c_slidy.show_toolbar(); }, 50); }, // 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 adjust_object_dimensions: function (width, height) { for( var i = 0; i < w3c_slidy.objects.length; i++ ) { var obj = this.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); } } } }, // needed for Opera to inhibit default behavior // since Opera delivers keyPress even if keyDown // was cancelled key_press: function (event) { if (!event) event = window.event; if (!w3c_slidy.key_wanted) return w3c_slidy.cancel(event); return true; }, // See e.g. http://www.quirksmode.org/js/events/keys.html for keycodes key_down: function (event) { var key, target, tag; w3c_slidy.key_wanted = true; if (!event) event = window.event; // kludge around NS/IE differences if (window.event) { key = window.event.keyCode; target = window.event.srcElement; } else if (event.which) { key = event.which; target = event.target; } else return true; // Yikes! unknown browser // ignore event if key value is zero // as for alt on Opera and Konqueror if (!key) return true; // avoid interfering with keystroke // behavior for non-slidy chrome elements if (!w3c_slidy.slidy_chrome(target) && w3c_slidy.special_element(target)) 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 (w3c_slidy.is_shown_toc() && key != 9 && key != 16 && key != 38 && key != 40) { w3c_slidy.hide_table_of_contents(true); if (key == 27 || key == 84 || key == 67) return w3c_slidy.cancel(event); } if (key == 34) // Page Down { if (w3c_slidy.view_all) return true; w3c_slidy.next_slide(false); return w3c_slidy.cancel(event); } else if (key == 33) // Page Up { if (w3c_slidy.view_all) return true; w3c_slidy.previous_slide(false); return w3c_slidy.cancel(event); } else if (key == 32) // space bar { w3c_slidy.next_slide(true); return w3c_slidy.cancel(event); } else if (key == 37) // Left arrow { w3c_slidy.previous_slide(!event.shiftKey); return w3c_slidy.cancel(event); } else if (key == 36) // Home { w3c_slidy.first_slide(); return w3c_slidy.cancel(event); } else if (key == 35) // End { w3c_slidy.last_slide(); return w3c_slidy.cancel(event); } else if (key == 39) // Right arrow { w3c_slidy.next_slide(!event.shiftKey); return w3c_slidy.cancel(event); } else if (key == 13) // Enter { if (w3c_slidy.outline) { if (w3c_slidy.outline.visible) w3c_slidy.fold(w3c_slidy.outline); else w3c_slidy.unfold(w3c_slidy.outline); return w3c_slidy.cancel(event); } } else if (key == 188) // < for smaller fonts { w3c_slidy.smaller(); return w3c_slidy.cancel(event); } else if (key == 190) // > for larger fonts { w3c_slidy.bigger(); return w3c_slidy.cancel(event); } else if (key == 189 || key == 109) // - for smaller fonts { w3c_slidy.smaller(); return w3c_slidy.cancel(event); } else if (key == 187 || key == 191 || key == 107) // = + for larger fonts { w3c_slidy.bigger(); return w3c_slidy.cancel(event); } else if (key == 83) // S for smaller fonts { w3c_slidy.smaller(); return w3c_slidy.cancel(event); } else if (key == 66) // B for larger fonts { w3c_slidy.bigger(); return w3c_slidy.cancel(event); } else if (key == 90) // Z for last slide { w3c_slidy.last_slide(); return w3c_slidy.cancel(event); } else if (key == 70) // F for toggle toolbar { w3c_slidy.toggle_toolbar(); return w3c_slidy.cancel(event); } else if (key == 65) // A for toggle view single/all slides { w3c_slidy.toggle_view(); return w3c_slidy.cancel(event); } else if (key == 75) // toggle action of left click for next page { w3c_slidy.mouse_click_enabled = !w3c_slidy.mouse_click_enabled; var alert_msg = (w3c_slidy.mouse_click_enabled ? "enabled" : "disabled") + " mouse click advance"; alert(w3c_slidy.localize(alert_msg)); return w3c_slidy.cancel(event); } else if (key == 84 || key == 67) // T or C for table of contents { if (w3c_slidy.toc) w3c_slidy.toggle_table_of_contents(); return w3c_slidy.cancel(event); } else if (key == 72) // H for help { window.location = w3c_slidy.help_page; return w3c_slidy.cancel(event); } //else alert("key code is "+ key); return true; }, // safe for both text/html and application/xhtml+xml create_element: function (name) { if (this.xhtml && (typeof document.createElementNS != 'undefined')) return document.createElementNS("http://www.w3.org/1999/xhtml", name) return document.createElement(name); }, get_element_style: function (elem, IEStyleProp, CSSStyleProp) { if (elem.currentStyle) { return elem.currentStyle[IEStyleProp]; } else if (window.getComputedStyle) { var compStyle = window.getComputedStyle(elem, ""); return compStyle.getPropertyValue(CSSStyleProp); } return ""; }, // the string str is a whitespace separated list of tokens // test if str contains a particular token, e.g. "slide" has_token: function (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; }, get_class_list: function (element) { if (typeof element.className != 'undefined') return element.className; return element.getAttribute("class"); }, has_class: function (element, name) { if (element.nodeType != 1) return false; var regexp = new RegExp("(^| )" + name + "\W*"); if (typeof element.className != 'undefined') return regexp.test(element.className); return regexp.test(element.getAttribute("class")); }, remove_class: function (element, name) { var regexp = new RegExp("(^| )" + name + "\W*"); var clsval = ""; if (typeof element.className != 'undefined') { clsval = element.className; if (clsval) { clsval = clsval.replace(regexp, ""); element.className = clsval; } } else { clsval = element.getAttribute("class"); if (clsval) { clsval = clsval.replace(regexp, ""); element.setAttribute("class", clsval); } } }, add_class: function (element, name) { if (!this.has_class(element, name)) { if (typeof element.className != 'undefined') element.className += " " + name; else { var clsval = element.getAttribute("class"); clsval = clsval ? clsval + " " + name : name; element.setAttribute("class", clsval); } } }, // 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). incremental_elements: null, okay_for_incremental: function (name) { if (!this.incremental_elements) { 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; this.incremental_elements = inclist; } return this.incremental_elements[name.toLowerCase()]; }, next_incremental_item: function (node) { var br = this.is_xhtml ? "br" : "BR"; var slide = w3c_slidy.slides[w3c_slidy.slide_number]; for (;;) { node = w3c_slidy.next_node(slide, node); if (node == null || node.parentNode == null) break; if (node.nodeType == 1) // ELEMENT { if (node.nodeName == br) continue; if (w3c_slidy.has_class(node, "incremental") && w3c_slidy.okay_for_incremental(node.nodeName)) return node; if (w3c_slidy.has_class(node.parentNode, "incremental") && !w3c_slidy.has_class(node, "non-incremental")) return node; } } return node; }, previous_incremental_item: function (node) { var br = this.is_xhtml ? "br" : "BR"; var slide = w3c_slidy.slides[w3c_slidy.slide_number]; for (;;) { node = w3c_slidy.previous_node(slide, node); if (node == null || node.parentNode == null) break; if (node.nodeType == 1) { if (node.nodeName == br) continue; if (w3c_slidy.has_class(node, "incremental") && w3c_slidy.okay_for_incremental(node.nodeName)) return node; if (w3c_slidy.has_class(node.parentNode, "incremental") && !w3c_slidy.has_class(node, "non-incremental")) return node; } } return node; }, // set visibility for all elements on current slide with // a parent element with attribute class="incremental" set_visibility_all_incremental: function (value) { var node = this.next_incremental_item(null); if (value == "hidden") { while (node) { w3c_slidy.add_class(node, "invisible"); node = w3c_slidy.next_incremental_item(node); } } else // value == "visible" { while (node) { w3c_slidy.remove_class(node, "invisible"); node = w3c_slidy.next_incremental_item(node); } } }, // reveal the next hidden item on the slide // node is null or the node that was last revealed reveal_next_item: function (node) { node = w3c_slidy.next_incremental_item(node); if (node && node.nodeType == 1) // an element w3c_slidy.remove_class(node, "invisible"); return node; }, // exact inverse of revealNextItem(node) hide_previous_item: function (node) { if (node && node.nodeType == 1) // an element w3c_slidy.add_class(node, "invisible"); return this.previous_incremental_item(node); }, // left to right traversal of root's content next_node: function (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 previous_node: function (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; }, previous_sibling_element: function (el) { el = el.previousSibling; while (el && el.nodeType != 1) el = el.previousSibling; return el; }, next_sibling_element: function (el) { el = el.nextSibling; while (el && el.nodeType != 1) el = el.nextSibling; return el; }, first_child_element: function (el) { var node; for (node = el.firstChild; node; node = node.nextSibling) { if (node.nodeType == 1) break; } return node; }, first_tag: function (element, tag) { var node; if (!this.is_xhtml) tag = tag.toUpperCase(); for (node = element.firstChild; node; node = node.nextSibling) { if (node.nodeType == 1 && node.nodeName == tag) break; } return node; }, hide_selection: function () { if (window.getSelection) // Firefox, Chromium, Safari, Opera { var selection = window.getSelection(); if (selection.rangeCount > 0) { var range = selection.getRangeAt(0); range.collapse (false); } } else // Internet Explorer { var textRange = document.selection.createRange (); textRange.collapse (false); } }, get_selected_text: function () { 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 ""; }, // make note of length of selected text // as this evaluates to zero in click event mouse_button_up: function (e) { w3c_slidy.selected_text_len = w3c_slidy.get_selected_text().length; }, // right mouse button click is reserved for context menus // it is more reliable to detect rightclick than leftclick mouse_button_click: function (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; if (w3c_slidy.selected_text_len > 0) { w3c_slidy.stop_propagation(e); e.cancel = true; e.returnValue = false; return false; } // dismiss table of contents w3c_slidy.hide_table_of_contents(false); // check if target is something that probably want's clicks // e.g. a, embed, object, input, textarea, select, option var tag = target.nodeName.toLowerCase(); if (w3c_slidy.mouse_click_enabled && leftclick && !w3c_slidy.special_element(target) && !target.onclick) { w3c_slidy.next_slide(true); w3c_slidy.stop_propagation(e); e.cancel = true; e.returnValue = false; return false; } return true; }, special_element: function (element) { if (this.has_class(element, "non-interactive")) return false; var tag = element.nodeName.toLowerCase(); return element.onkeydown || element.onclick || tag == "a" || tag == "embed" || tag == "object" || tag == "video" || tag == "audio" || tag == "svg" || tag == "canvas" || tag == "input" || tag == "textarea" || tag == "select" || tag == "option"; }, slidy_chrome: function (el) { while (el) { if (el == w3c_slidy.toc || el == w3c_slidy.toolbar || w3c_slidy.has_class(el, "outline")) return true; el = el.parentNode; } return false; }, get_key: function (e) { var key; // kludge around NS/IE differences if (typeof window.event != "undefined") key = window.event.keyCode; else if (e.which) key = e.which; return key; }, get_target: function (e) { var target; if (!e) e = window.event; if (e.target) target = e.target; else if (e.srcElement) target = e.srcElement; if (target.nodeType != 1) target = target.parentNode; return target; }, // does display property provide correct defaults? is_block: function (elem) { var tag = elem.nodeName.toLowerCase(); 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"; }, add_listener: function (element, event, handler) { if (window.addEventListener) element.addEventListener(event, handler, false); else element.attachEvent("on"+event, handler); }, // used to prevent event propagation from field controls stop_propagation: function (event) { event = event ? event : window.event; event.cancelBubble = true; // for IE if (event.stopPropagation) event.stopPropagation(); return true; }, cancel: function (event) { if (event) { event.cancel = true; event.returnValue = false; if (event.preventDefault) event.preventDefault(); } w3c_slidy.key_wanted = false; return false; }, // for each language define an associative array // and also the help text which is longer 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" }, help_es: "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.", 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" }, help_ca: "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.", strings_cs: { "slide":"snímek", "help?":"nápověda", "contents?":"obsah", "table of contents":"obsah prezentace", "Table of Contents":"Obsah prezentace", "restart presentation":"znovu spustit prezentaci", "restart?":"restart" }, help_cs: "Prezentaci můžete procházet pomocí kliknutí myši, mezerníku, " + "šipek vlevo a vpravo nebo kláves PageUp a PageDown. Písmo se " + "dá zvětšit a zmenšit pomocí kláves B a S.", strings_nl: { "slide":"pagina", "help?":"Help?", "contents?":"Inhoud?", "table of contents":"inhoudsopgave", "Table of Contents":"Inhoudsopgave", "restart presentation":"herstart presentatie", "restart?":"Herstart?" }, help_nl: "Navigeer d.m.v. het muis, spatiebar, Links/Rechts toetsen, " + "of PgUp en PgDn. Gebruik S en B om de karaktergrootte te veranderen.", strings_de: { "slide":"Seite", "help?":"Hilfe", "contents?":"Übersicht", "table of contents":"Inhaltsverzeichnis", "Table of Contents":"Inhaltsverzeichnis", "restart presentation":"Präsentation neu starten", "restart?":"Neustart" }, help_de: "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.", 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?" }, help_pl: "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.", 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" }, help_fr: "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.", 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" }, help_hu: "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.", strings_it: { "slide":"pag.", "help?":"Aiuto", "contents?":"Indice", "table of contents":"indice", "Table of Contents":"Indice", "restart presentation":"Ricominciare la presentazione", "restart?":"Inizio" }, help_it: "Navigare con mouse, barra spazio, frecce sinistra/destra o " + "PgUp e PgDn. Usare S e B per cambiare la dimensione dei caratteri.", strings_el: { "slide":"σελίδα", "help?":"βοήθεια;", "contents?":"περιεχόμενα;", "table of contents":"πίνακας περιεχομένων", "Table of Contents":"Πίνακας Περιεχομένων", "restart presentation":"επανεκκίνηση παρουσίασης", "restart?":"επανεκκίνηση;" }, help_el: "Πλοηγηθείτε με το κλίκ του ποντικιού, το space, τα βέλη αριστερά/δεξιά, " + "ή Page Up και Page Down. Χρησιμοποιήστε τα πλήκτρα S και B για να αλλάξετε " + "το μέγεθος της γραμματοσειράς.", strings_ja: { "slide":"スライド", "help?":"ヘルプ", "contents?":"目次", "table of contents":"目次を表示", "Table of Contents":"目次", "restart presentation":"最初から再生", "restart?":"最初から" }, help_ja: "マウス左クリック ・ スペース ・ 左右キー " + "または Page Up ・ Page Downで操作, S ・ Bでフォントサイズ変更", strings_zh: { "slide":"幻灯片", "help?":"帮助?", "contents?":"内容?", "table of contents":"目录", "Table of Contents":"目录", "restart presentation":"重新启动展示", "restart?":"重新启动?" }, help_zh: "用鼠标点击, 空格条, 左右箭头, Pg Up 和 Pg Dn 导航. " + "用 S, B 改变字体大小.", strings_ru: { "slide":"слайд", "help?":"помощь?", "contents?":"содержание?", "table of contents":"оглавление", "Table of Contents":"Оглавление", "restart presentation":"перезапустить презентацию", "restart?":"перезапуск?" }, help_ru: "Перемещайтесь кликая мышкой, используя клавишу пробел, стрелки" + "влево/вправо или Pg Up и Pg Dn. Клавиши S и B меняют размер шрифта.", strings_sv: { "slide":"sida", "help?":"hjälp", "contents?":"innehåll", "table of contents":"innehållsförteckning", "Table of Contents":"Innehållsförteckning", "restart presentation":"visa presentationen från början", "restart?":"börja om" }, help_sv: "Bläddra med ett klick med vänstra musknappen, mellanslagstangenten, " + "vänster- och högerpiltangenterna eller tangenterna Pg Up, Pg Dn. " + "Använd tangenterna S och B för att ändra textens storlek.", strings: { }, localize: function (src) { if (src == "") return src; // try full language code, e.g. en-US var s, lookup = w3c_slidy.strings[w3c_slidy.lang]; if (lookup) { s = lookup[src]; if (s) return s; } // strip country code suffix, e.g. // try en if undefined for en-US var lg = w3c_slidy.lang.split("-"); if (lg.length > 1) { lookup = w3c_slidy.strings[lg[0]]; if (lookup) { s = lookup[src]; if (s) return s; } } // otherwise string as is return src; }, init_localization: function () { var i18n = w3c_slidy; var help_text = w3c_slidy.help_text; // each such language array is declared in the localize array // this is used as in w3c_slidy.localize("foo"); this.strings = { "es":this.strings_es, "ca":this.strings_ca, "cs":this.strings_cs, "nl":this.strings_nl, "de":this.strings_de, "pl":this.strings_pl, "fr":this.strings_fr, "hu":this.strings_hu, "it":this.strings_it, "el":this.strings_el, "jp":this.strings_ja, "zh":this.strings_zh, "ru":this.strings_ru, "sv":this.strings_sv }, i18n.strings_es[help_text] = i18n.help_es; i18n.strings_ca[help_text] = i18n.help_ca; i18n.strings_cs[help_text] = i18n.help_cs; i18n.strings_nl[help_text] = i18n.help_nl; i18n.strings_de[help_text] = i18n.help_de; i18n.strings_pl[help_text] = i18n.help_pl; i18n.strings_fr[help_text] = i18n.help_fr; i18n.strings_hu[help_text] = i18n.help_hu; i18n.strings_it[help_text] = i18n.help_it; i18n.strings_el[help_text] = i18n.help_el; i18n.strings_ja[help_text] = i18n.help_ja; i18n.strings_zh[help_text] = i18n.help_zh; i18n.strings_ru[help_text] = i18n.help_ru; i18n.strings_sv[help_text] = i18n.help_sv; w3c_slidy.lang = document.body.parentNode.getAttribute("lang"); if (!w3c_slidy.lang) w3c_slidy.lang = document.body.parentNode.getAttribute("xml:lang"); if (!w3c_slidy.lang) w3c_slidy.lang = "en"; } }; // hack for back button behavior if (w3c_slidy.ie6 || w3c_slidy.ie7) { document.write("<iframe id='historyFrame' " + "src='javascript:\"<html"+"></"+"html>\"' " + "height='1' width='1' " + "style='position:absolute;left:-800px'></iframe>"); } // attach event listeners for initialization w3c_slidy.set_up(); // hide the slides as soon as body element is available // to reduce annoying screen mess before the onload event setTimeout(w3c_slidy.hide_slides, 50);
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 26953 | Paul Allen | Move //guest/perforce_software/p4convert to //guest/perforce_software/p4convert/main | ||
//guest/perforce_software/p4convert/docs/docbook-xsl-ns-1.78.1/slides/slidy/scripts/slidy.js | |||||
#2 | 14806 | Paul Allen | Update docs and add +w. | ||
#1 | 13920 | Paul Allen | copy part 2 (no errors) | ||
//guest/paul_allen/p4convert-maven/docs/docbook-xsl-ns-1.78.1/slides/slidy/scripts/slidy.js | |||||
#1 | 13895 | Paul Allen | Copying using p4convert-docbook | ||
//guest/perforce_software/doc_build/main/docbook-xsl-ns-1.78.1/slides/slidy/scripts/slidy.js | |||||
#1 | 12728 | eedwards |
Upgrade ANT doc build infrastructure to assemble PDFs: - remove non-namespaced DocBook source and add namespaced DocBook source. - add Apache FOP 1.1 - copy fonts, images, XSL into _build, establishing new asset structure. The original structure remains until all guides using it can be upgraded, and several other issues can be resolved. - updated build.xml to allow for per-target build properties. - upgraded the P4SAG to use the new infrastructure. - tweaked admonition presentation in PDFs to remove admonition graphics, and resemble closely the presentation used in the new HTML layout, including the same colors. With these changes, building PDFs involves using a shell, navigating into the guide's directory (just P4SAG for now), and executing "ant pdf". Issues still to be resolved: - PDF generation encounters several warnings about missing fonts (bold versions of Symbol and ZapfDingbats), and a couple of locations where the page content exceeds the defined content area. - Due to issues within Apache FOP, PDF generation emits a substantial amount of output that is not easily suppressed without losing important warning information. - Apache FOP's interface to ANT does not expose a way to set the font base directory. The current configuration does work under Mac OSX, but further testing on Windows will need to be done to determine if the relative paths defined continue to work. The workaround is for Windows users to customize the fop-config.xml to provide absolute system paths to the required fonts. - HTML generation needs further browser testing, and exhibits broken navigation on iOS browsers within the TOC sidebar. - A number of PDF and HTML presentation tweaks still need to be made, for example: sidebars, gui* DocBook tags, whitespace, section separation, etc. |