/templates/slidy.js
JavaScript | 2879 lines | 2103 code | 535 blank | 241 comment | 634 complexity | 4f52094bf0c0d11351fd166107618e47 MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0, WTFPL
Large files files are truncated, but you can click here to view the full file
- /* slidy.js
- Copyright (c) 2005-2010 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),
- 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),
- keyboardless: (this.ipad || this.iphone),
- // 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;
- // 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 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;
- },
- // ### 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 = "Tap footer to move to next slide";
- else
- p1.innerHTML = "Space or Right Arrow 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
- (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
- 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
- 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 (w3c_slidy.ie && !w3c_slidy.ie8)
- 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_slid…
Large files files are truncated, but you can click here to view the full file