PageRenderTime 69ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/samples/scalate-presentation/src/scripts/slidy.js

http://github.com/scalate/scalate
JavaScript | 2881 lines | 2105 code | 535 blank | 241 comment | 634 complexity | 4b09909ae79f7bc1201001ec7e146571 MD5 | raw file
  1. /* slidy.js
  2. Copyright (c) 2005-2010 W3C (MIT, ERCIM, Keio), All Rights Reserved.
  3. W3C liability, trademark, document use and software licensing
  4. rules apply, see:
  5. http://www.w3.org/Consortium/Legal/copyright-documents
  6. http://www.w3.org/Consortium/Legal/copyright-software
  7. Defines single name "w3c_slidy" in global namespace
  8. Adds event handlers without trampling on any others
  9. */
  10. // the slidy object implementation
  11. var w3c_slidy = {
  12. // classify which kind of browser we're running under
  13. ns_pos: (typeof window.pageYOffset!='undefined'),
  14. khtml: ((navigator.userAgent).indexOf("KHTML") >= 0 ? true : false),
  15. opera: ((navigator.userAgent).indexOf("Opera") >= 0 ? true : false),
  16. ipad: ((navigator.userAgent).indexOf("iPad") >= 0 ? true : false),
  17. iphone: ((navigator.userAgent).indexOf("iPhone") >= 0 ? true : false),
  18. ie: (typeof document.all != "undefined" && !this.opera),
  19. ie6: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 6") != -1),
  20. ie7: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 7") != -1),
  21. ie8: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 8") != -1),
  22. ie9: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 9") != -1),
  23. keyboardless: (this.ipad || this.iphone),
  24. // are we running as XHTML? (doesn't work on Opera)
  25. is_xhtml: /xml/.test(document.contentType),
  26. slide_number: 0, // integer slide count: 0, 1, 2, ...
  27. slide_number_element: null, // element containing slide number
  28. slides: [], // set to array of slide div's
  29. notes: [], // set to array of handout div's
  30. backgrounds: [], // set to array of background div's
  31. toolbar: null, // element containing toolbar
  32. title: null, // document title
  33. last_shown: null, // last incrementally shown item
  34. eos: null, // span element for end of slide indicator
  35. toc: null, // table of contents
  36. outline: null, // outline element with the focus
  37. selected_text_len: 0, // length of drag selection on document
  38. view_all: 0, // 1 to view all slides + handouts
  39. want_toolbar: true, // user preference to show/hide toolbar
  40. mouse_click_enabled: true, // enables left click for next slide
  41. scroll_hack: 0, // IE work around for position: fixed
  42. disable_slide_click: false, // used by clicked anchors
  43. lang: "en", // updated to language specified by html file
  44. help_anchor: null, // used for keyboard focus hack in showToolbar()
  45. help_page: "http://www.w3.org/Talks/Tools/Slidy2/help/help.html",
  46. help_text: "Navigate with mouse click, space bar, Cursor Left/Right, " +
  47. "or Pg Up and Pg Dn. Use S and B to change font size.",
  48. size_index: 0,
  49. size_adjustment: 0,
  50. sizes: new Array("10pt", "12pt", "14pt", "16pt", "18pt", "20pt",
  51. "22pt", "24pt", "26pt", "28pt", "30pt", "32pt"),
  52. // needed for efficient resizing
  53. last_width: 0,
  54. last_height: 0,
  55. // Needed for cross browser support for relative width/height on
  56. // object elements. The work around is to save width/height attributes
  57. // and then to recompute absolute width/height dimensions on resizing
  58. objects: [],
  59. // attach initialiation event handlers
  60. set_up: function () {
  61. var init = function() { w3c_slidy.init(); };
  62. if (typeof window.addEventListener != "undefined")
  63. window.addEventListener("load", init, false);
  64. else
  65. window.attachEvent("onload", init);
  66. },
  67. hide_slides: function () {
  68. if (document.body && !w3c_slidy.initialized)
  69. document.body.style.visibility = "hidden";
  70. else
  71. setTimeout(w3c_slidy.hide_slides, 50);
  72. },
  73. // hack to persuade IE to compute correct document height
  74. // as needed for simulating fixed positioning of toolbar
  75. ie_hack: function () {
  76. window.resizeBy(0,-1);
  77. window.resizeBy(0, 1);
  78. },
  79. init: function () {
  80. //alert("slidy starting test 10");
  81. document.body.style.visibility = "visible";
  82. this.init_localization();
  83. this.add_toolbar();
  84. this.wrap_implicit_slides();
  85. this.collect_slides();
  86. this.collect_notes();
  87. this.collect_backgrounds();
  88. this.objects = document.body.getElementsByTagName("object");
  89. this.patch_anchors();
  90. this.slide_number = this.find_slide_number(location.href);
  91. window.offscreenbuffering = true;
  92. this.size_adjustment = this.find_size_adjust();
  93. this.time_left = this.find_duration();
  94. this.hide_image_toolbar(); // suppress IE image toolbar popup
  95. this.init_outliner(); // activate fold/unfold support
  96. this.title = document.title;
  97. // work around for opera bug
  98. this.is_xhtml = (document.body.tagName == "BODY" ? false : true);
  99. if (this.slides.length > 0)
  100. {
  101. var slide = this.slides[this.slide_number];
  102. if (this.slide_number > 0)
  103. {
  104. this.set_visibility_all_incremental("visible");
  105. this.last_shown = this.previous_incremental_item(null);
  106. this.set_eos_status(true);
  107. }
  108. else
  109. {
  110. this.last_shown = null;
  111. this.set_visibility_all_incremental("hidden");
  112. this.set_eos_status(!this.next_incremental_item(this.last_shown));
  113. }
  114. this.set_location();
  115. this.add_class(this.slides[0], "first-slide");
  116. w3c_slidy.show_slide(slide);
  117. }
  118. this.toc = this.table_of_contents();
  119. this.add_initial_prompt();
  120. // bind event handlers without interfering with custom page scripts
  121. // Tap events behave too weirdly to support clicks reliably on
  122. // iPhone and iPad, so exclude these from click handler
  123. if (!this.keyboardless)
  124. this.add_listener(document.body, "click", this.mouse_button_click);
  125. this.add_listener(document, "keydown", this.key_down);
  126. this.add_listener(document, "keypress", this.key_press);
  127. this.add_listener(window, "resize", this.resized);
  128. this.add_listener(window, "scroll", this.scrolled);
  129. this.add_listener(window, "unload", this.unloaded);
  130. // this seems to be a debugging hack
  131. //if (!document.body.onclick)
  132. // document.body.onclick = function () { };
  133. this.single_slide_view();
  134. //this.set_location();
  135. this.resized();
  136. if (this.ie7)
  137. setTimeout(w3c_slidy.ie_hack, 100);
  138. this.show_toolbar();
  139. // for back button detection
  140. setInterval(function () { w3c_slidy.check_location(); }, 200);
  141. w3c_slidy.initialized = true;
  142. },
  143. // create div element with links to each slide
  144. table_of_contents: function () {
  145. var toc = this.create_element("div");
  146. this.add_class(toc, "slidy_toc hidden");
  147. //toc.setAttribute("tabindex", "0");
  148. var heading = this.create_element("div");
  149. this.add_class(heading, "toc-heading");
  150. heading.innerHTML = this.localize("Table of Contents");
  151. toc.appendChild(heading);
  152. var previous = null;
  153. for (var i = 0; i < this.slides.length; ++i)
  154. {
  155. var title = this.has_class(this.slides[i], "title");
  156. var num = document.createTextNode((i + 1) + ". ");
  157. toc.appendChild(num);
  158. var a = this.create_element("a");
  159. a.setAttribute("href", "#(" + (i+1) + ")");
  160. if (title)
  161. this.add_class(a, "titleslide");
  162. var name = document.createTextNode(this.slide_name(i));
  163. a.appendChild(name);
  164. a.onclick = w3c_slidy.toc_click;
  165. a.onkeydown = w3c_slidy.toc_key_down;
  166. a.previous = previous;
  167. if (previous)
  168. previous.next = a;
  169. toc.appendChild(a);
  170. if (i == 0)
  171. toc.first = a;
  172. if (i < this.slides.length - 1)
  173. {
  174. var br = this.create_element("br");
  175. toc.appendChild(br);
  176. }
  177. previous = a;
  178. }
  179. toc.focus = function () {
  180. if (this.first)
  181. this.first.focus();
  182. }
  183. toc.onmouseup = w3c_slidy.mouse_button_up;
  184. toc.onclick = function (e) {
  185. e||(e=window.event);
  186. if (w3c_slidy.selected_text_len <= 0)
  187. w3c_slidy.hide_table_of_contents(true);
  188. w3c_slidy.stop_propagation(e);
  189. if (e.cancel != undefined)
  190. e.cancel = true;
  191. if (e.returnValue != undefined)
  192. e.returnValue = false;
  193. return false;
  194. };
  195. document.body.insertBefore(toc, document.body.firstChild);
  196. return toc;
  197. },
  198. is_shown_toc: function () {
  199. return !w3c_slidy.has_class(w3c_slidy.toc, "hidden");
  200. },
  201. show_table_of_contents: function () {
  202. w3c_slidy.remove_class(w3c_slidy.toc, "hidden");
  203. var toc = w3c_slidy.toc;
  204. toc.focus();
  205. if (w3c_slidy.ie7 && w3c_slidy.slide_number == 0)
  206. setTimeout(w3c_slidy.ie_hack, 100);
  207. },
  208. hide_table_of_contents: function (focus) {
  209. w3c_slidy.add_class(w3c_slidy.toc, "hidden");
  210. if (focus && !w3c_slidy.opera)
  211. w3c_slidy.help_anchor.focus();
  212. },
  213. toggle_table_of_contents: function () {
  214. if (w3c_slidy.is_shown_toc())
  215. w3c_slidy.hide_table_of_contents(true);
  216. else
  217. w3c_slidy.show_table_of_contents();
  218. },
  219. // called on clicking toc entry
  220. toc_click: function (e) {
  221. if (!e)
  222. e = window.event;
  223. var target = w3c_slidy.get_target(e);
  224. if (target && target.nodeType == 1)
  225. {
  226. var uri = target.getAttribute("href");
  227. if (uri)
  228. {
  229. //alert("going to " + uri);
  230. var slide = w3c_slidy.slides[w3c_slidy.slide_number];
  231. w3c_slidy.hide_slide(slide);
  232. w3c_slidy.slide_number = w3c_slidy.find_slide_number(uri);
  233. slide = w3c_slidy.slides[w3c_slidy.slide_number];
  234. w3c_slidy.last_shown = null;
  235. w3c_slidy.set_location();
  236. w3c_slidy.set_visibility_all_incremental("hidden");
  237. w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
  238. w3c_slidy.show_slide(slide);
  239. //target.focus();
  240. try
  241. {
  242. if (!w3c_slidy.opera)
  243. w3c_slidy.help_anchor.focus();
  244. }
  245. catch (e)
  246. {
  247. }
  248. }
  249. }
  250. w3c_slidy.hide_table_of_contents(true);
  251. if (w3c_slidy.ie7) w3c_slidy.ie_hack();
  252. w3c_slidy.stop_propagation(e);
  253. return w3c_slidy.cancel(e);
  254. },
  255. // called onkeydown for toc entry
  256. toc_key_down: function (event) {
  257. var key;
  258. if (!event)
  259. var event = window.event;
  260. // kludge around NS/IE differences
  261. if (window.event)
  262. key = window.event.keyCode;
  263. else if (event.which)
  264. key = event.which;
  265. else
  266. return true; // Yikes! unknown browser
  267. // ignore event if key value is zero
  268. // as for alt on Opera and Konqueror
  269. if (!key)
  270. return true;
  271. // check for concurrent control/command/alt key
  272. // but are these only present on mouse events?
  273. if (event.ctrlKey || event.altKey)
  274. return true;
  275. if (key == 13)
  276. {
  277. var uri = this.getAttribute("href");
  278. if (uri)
  279. {
  280. //alert("going to " + uri);
  281. var slide = w3c_slidy.slides[w3c_slidy.slide_number];
  282. w3c_slidy.hide_slide(slide);
  283. w3c_slidy.slide_number = w3c_slidy.find_slide_number(uri);
  284. slide = w3c_slidy.slides[w3c_slidy.slide_number];
  285. w3c_slidy.last_shown = null;
  286. w3c_slidy.set_location();
  287. w3c_slidy.set_visibility_all_incremental("hidden");
  288. w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
  289. w3c_slidy.show_slide(slide);
  290. //target.focus();
  291. try
  292. {
  293. if (!w3c_slidy.opera)
  294. w3c_slidy.help_anchor.focus();
  295. }
  296. catch (e)
  297. {
  298. }
  299. }
  300. w3c_slidy.hide_table_of_contents(true);
  301. if (self.ie7)
  302. w3c_slidy.ie_hack();
  303. return w3c_slidy.cancel(event);
  304. }
  305. if (key == 40 && this.next)
  306. {
  307. this.next.focus();
  308. return w3c_slidy.cancel(event);
  309. }
  310. if (key == 38 && this.previous)
  311. {
  312. this.previous.focus();
  313. return w3c_slidy.cancel(event);
  314. }
  315. return true;
  316. },
  317. // ### OBSOLETE ###
  318. before_print: function () {
  319. this.show_all_slides();
  320. this.hide_toolbar();
  321. alert("before print");
  322. },
  323. // ### OBSOLETE ###
  324. after_print: function () {
  325. if (!this.view_all)
  326. {
  327. this.single_slide_view();
  328. this.show_toolbar();
  329. }
  330. alert("after print");
  331. },
  332. // ### OBSOLETE ###
  333. print_slides: function () {
  334. this.before_print();
  335. window.print();
  336. this.after_print();
  337. },
  338. // ### OBSOLETE ?? ###
  339. toggle_view: function () {
  340. if (this.view_all)
  341. {
  342. this.single_slide_view();
  343. this.show_toolbar();
  344. this.view_all = 0;
  345. }
  346. else
  347. {
  348. this.show_all_slides();
  349. this.hide_toolbar();
  350. this.view_all = 1;
  351. }
  352. },
  353. // prepare for printing ### OBSOLETE ###
  354. show_all_slides: function () {
  355. this.remove_class(document.body, "single_slide");
  356. this.set_visibility_all_incremental("visible");
  357. },
  358. // restore after printing ### OBSOLETE ###
  359. single_slide_view: function () {
  360. this.add_class(document.body, "single_slide");
  361. this.set_visibility_all_incremental("visible");
  362. this.last_shown = this.previous_incremental_item(null);
  363. },
  364. // suppress IE's image toolbar pop up
  365. hide_image_toolbar: function () {
  366. if (!this.ns_pos)
  367. {
  368. var images = document.getElementsByTagName("IMG");
  369. for (var i = 0; i < images.length; ++i)
  370. images[i].setAttribute("galleryimg", "no");
  371. }
  372. },
  373. unloaded: function (e) {
  374. //alert("unloaded");
  375. },
  376. // Safari and Konqueror don't yet support getComputedStyle()
  377. // and they always reload page when location.href is updated
  378. is_KHTML: function () {
  379. var agent = navigator.userAgent;
  380. return (agent.indexOf("KHTML") >= 0 ? true : false);
  381. },
  382. // find slide name from first h1 element
  383. // default to document title + slide number
  384. slide_name: function (index) {
  385. var name = null;
  386. var slide = this.slides[index];
  387. var heading = this.find_heading(slide);
  388. if (heading)
  389. name = this.extract_text(heading);
  390. if (!name)
  391. name = this.title + "(" + (index + 1) + ")";
  392. name.replace(/\&/g, "&amp;");
  393. name.replace(/\</g, "&lt;");
  394. name.replace(/\>/g, "&gt;");
  395. return name;
  396. },
  397. // find first h1 element in DOM tree
  398. find_heading: function (node) {
  399. if (!node || node.nodeType != 1)
  400. return null;
  401. if (node.nodeName == "H1" || node.nodeName == "h1")
  402. return node;
  403. var child = node.firstChild;
  404. while (child)
  405. {
  406. node = this.find_heading(child);
  407. if (node)
  408. return node;
  409. child = child.nextSibling;
  410. }
  411. return null;
  412. },
  413. // recursively extract text from DOM tree
  414. extract_text: function (node) {
  415. if (!node)
  416. return "";
  417. // text nodes
  418. if (node.nodeType == 3)
  419. return node.nodeValue;
  420. // elements
  421. if (node.nodeType == 1)
  422. {
  423. node = node.firstChild;
  424. var text = "";
  425. while (node)
  426. {
  427. text = text + this.extract_text(node);
  428. node = node.nextSibling;
  429. }
  430. return text;
  431. }
  432. return "";
  433. },
  434. // find copyright text from meta element
  435. find_copyright: function () {
  436. var name, content;
  437. var meta = document.getElementsByTagName("meta");
  438. for (var i = 0; i < meta.length; ++i)
  439. {
  440. name = meta[i].getAttribute("name");
  441. content = meta[i].getAttribute("content");
  442. if (name == "copyright")
  443. return content;
  444. }
  445. return null;
  446. },
  447. find_size_adjust: function () {
  448. var name, content, offset;
  449. var meta = document.getElementsByTagName("meta");
  450. for (var i = 0; i < meta.length; ++i)
  451. {
  452. name = meta[i].getAttribute("name");
  453. content = meta[i].getAttribute("content");
  454. if (name == "font-size-adjustment")
  455. return 1 * content;
  456. }
  457. return 1;
  458. },
  459. // <meta name="duration" content="20" /> for 20 minutes
  460. find_duration: function () {
  461. var name, content, offset;
  462. var meta = document.getElementsByTagName("meta");
  463. for (var i = 0; i < meta.length; ++i)
  464. {
  465. name = meta[i].getAttribute("name");
  466. content = meta[i].getAttribute("content");
  467. if (name == "duration")
  468. return 60000 * content;
  469. }
  470. return null;
  471. },
  472. replace_by_non_breaking_space: function (str) {
  473. for (var i = 0; i < str.length; ++i)
  474. str[i] = 160;
  475. },
  476. // ### CHECK ME ### is use of "li" okay for text/html?
  477. // for XHTML do we also need to specify namespace?
  478. init_outliner: function () {
  479. var items = document.getElementsByTagName("li");
  480. for (var i = 0; i < items.length; ++i)
  481. {
  482. var target = items[i];
  483. if (!this.has_class(target.parentNode, "outline"))
  484. continue;
  485. target.onclick = this.outline_click;
  486. /* ### more work needed for IE6
  487. if (!this.ns_pos)
  488. {
  489. target.onmouseover = this.hover_outline;
  490. target.onmouseout = this.unhover_outline;
  491. }
  492. */
  493. if (this.foldable(target))
  494. {
  495. target.foldable = true;
  496. target.onfocus = function () {w3c_slidy.outline = this;};
  497. target.onblur = function () {w3c_slidy.outline = null;};
  498. if (!target.getAttribute("tabindex"))
  499. target.setAttribute("tabindex", "0");
  500. if (this.has_class(target, "expand"))
  501. this.unfold(target);
  502. else
  503. this.fold(target);
  504. }
  505. else
  506. {
  507. this.add_class(target, "nofold");
  508. target.visible = true;
  509. target.foldable = false;
  510. }
  511. }
  512. },
  513. foldable: function (item) {
  514. if (!item || item.nodeType != 1)
  515. return false;
  516. var node = item.firstChild;
  517. while (node)
  518. {
  519. if (node.nodeType == 1 && this.is_block(node))
  520. return true;
  521. node = node.nextSibling;
  522. }
  523. return false;
  524. },
  525. // ### CHECK ME ### switch to add/remove "hidden" class
  526. fold: function (item) {
  527. if (item)
  528. {
  529. this.remove_class(item, "unfolded");
  530. this.add_class(item, "folded");
  531. }
  532. var node = item ? item.firstChild : null;
  533. while (node)
  534. {
  535. if (node.nodeType == 1 && this.is_block(node)) // element
  536. {
  537. w3c_slidy.add_class(node, "hidden");
  538. }
  539. node = node.nextSibling;
  540. }
  541. item.visible = false;
  542. },
  543. // ### CHECK ME ### switch to add/remove "hidden" class
  544. unfold: function (item) {
  545. if (item)
  546. {
  547. this.add_class(item, "unfolded");
  548. this.remove_class(item, "folded");
  549. }
  550. var node = item ? item.firstChild : null;
  551. while (node)
  552. {
  553. if (node.nodeType == 1 && this.is_block(node)) // element
  554. {
  555. w3c_slidy.remove_class(node, "hidden");
  556. }
  557. node = node.nextSibling;
  558. }
  559. item.visible = true;
  560. },
  561. outline_click: function (e) {
  562. if (!e)
  563. e = window.event;
  564. var rightclick = false;
  565. var target = w3c_slidy.get_target(e);
  566. while (target && target.visible == undefined)
  567. target = target.parentNode;
  568. if (!target)
  569. return true;
  570. if (e.which)
  571. rightclick = (e.which == 3);
  572. else if (e.button)
  573. rightclick = (e.button == 2);
  574. if (!rightclick && target.visible != undefined)
  575. {
  576. if (target.foldable)
  577. {
  578. if (target.visible)
  579. w3c_slidy.fold(target);
  580. else
  581. w3c_slidy.unfold(target);
  582. }
  583. w3c_slidy.stop_propagation(e);
  584. e.cancel = true;
  585. e.returnValue = false;
  586. }
  587. return false;
  588. },
  589. add_initial_prompt: function () {
  590. var prompt = this.create_element("div");
  591. prompt.setAttribute("class", "initial_prompt");
  592. var p1 = this.create_element("p");
  593. prompt.appendChild(p1);
  594. p1.setAttribute("class", "help");
  595. if (this.keyboardless)
  596. p1.innerHTML = "Tap footer to move to next slide";
  597. else
  598. p1.innerHTML = "Space or Right Arrow to move to next " +
  599. "slide, click help below for more details";
  600. this.add_listener(prompt, "click", function (e) {
  601. document.body.removeChild(prompt);
  602. w3c_slidy.stop_propagation(e);
  603. if (e.cancel != undefined)
  604. e.cancel = true;
  605. if (e.returnValue != undefined)
  606. e.returnValue = false;
  607. return false;
  608. });
  609. document.body.appendChild(prompt);
  610. this.initial_prompt = prompt;
  611. setTimeout(function() {document.body.removeChild(prompt);}, 5000);
  612. },
  613. add_toolbar: function () {
  614. var counter, page;
  615. this.toolbar = this.create_element("div");
  616. this.toolbar.setAttribute("class", "toolbar");
  617. // a reasonably behaved browser
  618. if (this.ns_pos || !this.ie6)
  619. {
  620. var right = this.create_element("div");
  621. right.setAttribute("style", "float: right; text-align: right");
  622. counter = this.create_element("span")
  623. counter.innerHTML = this.localize("slide") + " n/m";
  624. right.appendChild(counter);
  625. this.toolbar.appendChild(right);
  626. var left = this.create_element("div");
  627. left.setAttribute("style", "text-align: left");
  628. // global end of slide indicator
  629. this.eos = this.create_element("span");
  630. this.eos.innerHTML = "* ";
  631. left.appendChild(this.eos);
  632. var help = this.create_element("a");
  633. help.setAttribute("href", this.help_page);
  634. help.setAttribute("title", this.localize(this.help_text));
  635. help.innerHTML = this.localize("help?");
  636. left.appendChild(help);
  637. this.help_anchor = help; // save for focus hack
  638. var gap1 = document.createTextNode(" ");
  639. left.appendChild(gap1);
  640. var contents = this.create_element("a");
  641. contents.setAttribute("href", "javascript:w3c_slidy.toggle_table_of_contents()");
  642. contents.setAttribute("title", this.localize("table of contents"));
  643. contents.innerHTML = this.localize("contents?");
  644. left.appendChild(contents);
  645. var gap2 = document.createTextNode(" ");
  646. left.appendChild(gap2);
  647. var copyright = this.find_copyright();
  648. if (copyright)
  649. {
  650. var span = this.create_element("span");
  651. span.className = "copyright";
  652. span.innerHTML = copyright;
  653. left.appendChild(span);
  654. }
  655. this.toolbar.setAttribute("tabindex", "0");
  656. this.toolbar.appendChild(left);
  657. }
  658. else // IE6 so need to work around its poor CSS support
  659. {
  660. this.toolbar.style.position = (this.ie7 ? "fixed" : "absolute");
  661. this.toolbar.style.zIndex = "200";
  662. this.toolbar.style.width = "99.9%";
  663. this.toolbar.style.height = "1.2em";
  664. this.toolbar.style.top = "auto";
  665. this.toolbar.style.bottom = "0";
  666. this.toolbar.style.left = "0";
  667. this.toolbar.style.right = "0";
  668. this.toolbar.style.textAlign = "left";
  669. this.toolbar.style.fontSize = "60%";
  670. this.toolbar.style.color = "red";
  671. this.toolbar.borderWidth = 0;
  672. this.toolbar.className = "toolbar";
  673. this.toolbar.style.background = "rgb(240,240,240)";
  674. // would like to have help text left aligned
  675. // and page counter right aligned, floating
  676. // div's don't work, so instead use nested
  677. // absolutely positioned div's.
  678. var sp = this.create_element("span");
  679. sp.innerHTML = "&nbsp;&nbsp;*&nbsp;";
  680. this.toolbar.appendChild(sp);
  681. this.eos = sp; // end of slide indicator
  682. var help = this.create_element("a");
  683. help.setAttribute("href", this.help_page);
  684. help.setAttribute("title", this.localize(this.help_text));
  685. help.innerHTML = this.localize("help?");
  686. this.toolbar.appendChild(help);
  687. this.help_anchor = help; // save for focus hack
  688. var gap1 = document.createTextNode(" ");
  689. this.toolbar.appendChild(gap1);
  690. var contents = this.create_element("a");
  691. contents.setAttribute("href", "javascript:toggleTableOfContents()");
  692. contents.setAttribute("title", this.localize("table of contents".localize));
  693. contents.innerHTML = this.localize("contents?");
  694. this.toolbar.appendChild(contents);
  695. var gap2 = document.createTextNode(" ");
  696. this.toolbar.appendChild(gap2);
  697. var copyright = this.find_copyright();
  698. if (copyright)
  699. {
  700. var span = this.create_element("span");
  701. span.innerHTML = copyright;
  702. span.style.color = "black";
  703. span.style.marginLeft = "0.5em";
  704. this.toolbar.appendChild(span);
  705. }
  706. counter = this.create_element("div")
  707. counter.style.position = "absolute";
  708. counter.style.width = "auto"; //"20%";
  709. counter.style.height = "1.2em";
  710. counter.style.top = "auto";
  711. counter.style.bottom = 0;
  712. counter.style.right = "0";
  713. counter.style.textAlign = "right";
  714. counter.style.color = "red";
  715. counter.style.background = "rgb(240,240,240)";
  716. counter.innerHTML = this.localize("slide") + " n/m";
  717. this.toolbar.appendChild(counter);
  718. }
  719. // ensure that click isn't passed through to the page
  720. this.toolbar.onclick =
  721. function (e) {
  722. if (!e)
  723. e = window.event;
  724. var target = e.target;
  725. if (!target && e.srcElement)
  726. target = e.srcElement;
  727. // work around Safari bug
  728. if (target && target.nodeType == 3)
  729. target = target.parentNode;
  730. w3c_slidy.stop_propagation(e);
  731. if (target && target.nodeName.toLowerCase() != "a")
  732. w3c_slidy.mouse_button_click(e);
  733. };
  734. this.slide_number_element = counter;
  735. this.set_eos_status(false);
  736. document.body.appendChild(this.toolbar);
  737. },
  738. // wysiwyg editors make it hard to use div elements
  739. // e.g. amaya loses the div when you copy and paste
  740. // this function wraps div elements around implicit
  741. // slides which start with an h1 element and continue
  742. // up to the next heading or div element
  743. wrap_implicit_slides: function () {
  744. var i, heading, node, next, div;
  745. var headings = document.getElementsByTagName("h1");
  746. if (!headings)
  747. return;
  748. for (i = 0; i < headings.length; ++i)
  749. {
  750. heading = headings[i];
  751. if (heading.parentNode != document.body)
  752. continue;
  753. node = heading.nextSibling;
  754. div = document.createElement("div");
  755. this.add_class(div, "slide");
  756. document.body.replaceChild(div, heading);
  757. div.appendChild(heading);
  758. while (node)
  759. {
  760. if (node.nodeType == 1 && // an element
  761. (node.nodeName == "H1" ||
  762. node.nodeName == "h1" ||
  763. node.nodeName == "DIV" ||
  764. node.nodeName == "div"))
  765. break;
  766. next = node.nextSibling;
  767. node = document.body.removeChild(node);
  768. div.appendChild(node);
  769. node = next;
  770. }
  771. }
  772. },
  773. // return new array of all slides
  774. collect_slides: function () {
  775. var slides = new Array();
  776. var divs = document.body.getElementsByTagName("div");
  777. for (var i = 0; i < divs.length; ++i)
  778. {
  779. div = divs.item(i);
  780. if (this.has_class(div, "slide"))
  781. {
  782. // add slide to collection
  783. slides[slides.length] = div;
  784. // hide each slide as it is found
  785. this.add_class(div, "hidden");
  786. // add dummy <br/> at end for scrolling hack
  787. var node1 = document.createElement("br");
  788. div.appendChild(node1);
  789. var node2 = document.createElement("br");
  790. div.appendChild(node2);
  791. }
  792. else if (this.has_class(div, "background"))
  793. { // work around for Firefox SVG reload bug
  794. // which otherwise replaces 1st SVG graphic with 2nd
  795. div.style.display = "block";
  796. }
  797. }
  798. this.slides = slides;
  799. },
  800. // return new array of all <div class="handout">
  801. collect_notes: function () {
  802. var notes = new Array();
  803. var divs = document.body.getElementsByTagName("div");
  804. for (var i = 0; i < divs.length; ++i)
  805. {
  806. div = divs.item(i);
  807. if (this.has_class(div, "handout"))
  808. {
  809. // add note to collection
  810. notes[notes.length] = div;
  811. // and hide it
  812. this.add_class(div, "hidden");
  813. }
  814. }
  815. this.notes = notes;
  816. },
  817. // return new array of all <div class="background">
  818. // including named backgrounds e.g. class="background titlepage"
  819. collect_backgrounds: function () {
  820. var backgrounds = new Array();
  821. var divs = document.body.getElementsByTagName("div");
  822. for (var i = 0; i < divs.length; ++i)
  823. {
  824. div = divs.item(i);
  825. if (this.has_class(div, "background"))
  826. {
  827. // add background to collection
  828. backgrounds[backgrounds.length] = div;
  829. // and hide it
  830. this.add_class(div, "hidden");
  831. }
  832. }
  833. this.backgrounds = backgrounds;
  834. },
  835. // set click handlers on all anchors
  836. patch_anchors: function () {
  837. var self = w3c_slidy;
  838. var handler = function (event) {
  839. // compare this.href with location.href
  840. // for link to another slide in this doc
  841. if (self.page_address(this.href) == self.page_address(location.href))
  842. {
  843. // yes, so find new slide number
  844. var newslidenum = self.find_slide_number(this.href);
  845. if (newslidenum != self.slide_number)
  846. {
  847. var slide = self.slides[self.slide_number];
  848. self.hide_slide(slide);
  849. self.slide_number = newslidenum;
  850. slide = self.slides[self.slide_number];
  851. self.show_slide(slide);
  852. self.set_location();
  853. }
  854. }
  855. else
  856. w3c_slidy.stop_propagation(event);
  857. // else if (this.target == null)
  858. // location.href = this.href;
  859. this.blur();
  860. self.disable_slide_click = true;
  861. };
  862. var anchors = document.body.getElementsByTagName("a");
  863. for (var i = 0; i < anchors.length; ++i)
  864. {
  865. if (window.addEventListener)
  866. anchors[i].addEventListener("click", handler, false);
  867. else
  868. anchors[i].attachEvent("onclick", handler);
  869. }
  870. },
  871. // ### CHECK ME ### see which functions are invoked via setTimeout
  872. // either directly or indirectly for use of w3c_slidy vs this
  873. show_slide_number: function () {
  874. var timer = w3c_slidy.get_timer();
  875. w3c_slidy.slide_number_element.innerHTML = timer + w3c_slidy.localize("slide") + " " +
  876. (w3c_slidy.slide_number + 1) + "/" + w3c_slidy.slides.length;
  877. },
  878. // every 200mS check if the location has been changed as a
  879. // result of the user activating the Back button/menu item
  880. // doesn't work for Opera < 9.5
  881. check_location: function () {
  882. var hash = location.hash;
  883. if (w3c_slidy.slide_number > 0 && (hash == "" || hash == "#"))
  884. w3c_slidy.goto_slide(0);
  885. else if (hash.length > 2 && hash != "#("+(w3c_slidy.slide_number+1)+")")
  886. {
  887. var num = parseInt(location.hash.substr(2));
  888. if (!isNaN(num))
  889. w3c_slidy.goto_slide(num-1);
  890. }
  891. if (w3c_slidy.time_left && w3c_slidy.slide_number > 0)
  892. {
  893. w3c_slidy.show_slide_number();
  894. if (w3c_slidy.time_left > 0)
  895. w3c_slidy.time_left -= 200;
  896. }
  897. },
  898. get_timer: function () {
  899. var timer = "";
  900. if (w3c_slidy.time_left)
  901. {
  902. var mins, secs;
  903. secs = Math.floor(w3c_slidy.time_left/1000);
  904. mins = Math.floor(secs / 60);
  905. secs = secs % 60;
  906. timer = (mins ? mins+"m" : "") + secs + "s ";
  907. }
  908. return timer;
  909. },
  910. // this doesn't push location onto history stack for IE
  911. // for which a hidden iframe hack is needed: load page into
  912. // the iframe with script that set's parent's location.hash
  913. // but that won't work for standalone use unless we can
  914. // create the page dynamically via a javascript: URL
  915. set_location: function () {
  916. var uri = w3c_slidy.page_address(location.href);
  917. var hash = "#(" + (w3c_slidy.slide_number+1) + ")";
  918. if (w3c_slidy.slide_number >= 0)
  919. uri = uri + hash;
  920. if (w3c_slidy.ie && (w3c_slidy.ie6 || w3c_slidy.ie7))
  921. w3c_slidy.push_hash(hash);
  922. if (uri != location.href) // && !khtml
  923. location.href = uri;
  924. if (this.khtml)
  925. hash = "(" + (w3c_slidy.slide_number+1) + ")";
  926. if (!this.ie && location.hash != hash && location.hash != "")
  927. location.hash = hash;
  928. document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")";
  929. w3c_slidy.show_slide_number();
  930. },
  931. page_address: function (uri) {
  932. var i = uri.indexOf("#");
  933. if (i < 0)
  934. i = uri.indexOf("%23");
  935. // check if anchor is entire page
  936. if (i < 0)
  937. return uri; // yes
  938. return uri.substr(0, i);
  939. },
  940. // only used for IE6 and IE7
  941. on_frame_loaded: function (hash) {
  942. location.hash = hash;
  943. var uri = w3c_slidy.page_address(location.href);
  944. location.href = uri + hash;
  945. },
  946. // history hack with thanks to Bertrand Le Roy
  947. push_hash: function (hash) {
  948. if (hash == "") hash = "#(1)";
  949. window.location.hash = hash;
  950. var doc = document.getElementById("historyFrame").contentWindow.document;
  951. doc.open("javascript:'<html></html>'");
  952. doc.write("<html><head><script type=\"text/javascript\">window.parent.w3c_slidy.on_frame_loaded('"+
  953. (hash) + "');</script></head><body>hello mum</body></html>");
  954. doc.close();
  955. },
  956. // find current slide based upon location
  957. // first find target anchor and then look
  958. // for associated div element enclosing it
  959. // finally map that to slide number
  960. find_slide_number: function (uri) {
  961. // first get anchor from page location
  962. var i = uri.indexOf("#");
  963. // check if anchor is entire page
  964. if (i < 0)
  965. return 0; // yes
  966. var anchor = unescape(uri.substr(i+1));
  967. // now use anchor as XML ID to find target
  968. var target = document.getElementById(anchor);
  969. if (!target)
  970. {
  971. // does anchor look like "(2)" for slide 2 ??
  972. // where first slide is (1)
  973. var re = /\((\d)+\)/;
  974. if (anchor.match(re))
  975. {
  976. var num = parseInt(anchor.substring(1, anchor.length-1));
  977. if (num > this.slides.length)
  978. num = 1;
  979. if (--num < 0)
  980. num = 0;
  981. return num;
  982. }
  983. // accept [2] for backwards compatibility
  984. re = /\[(\d)+\]/;
  985. if (anchor.match(re))
  986. {
  987. var num = parseInt(anchor.substring(1, anchor.length-1));
  988. if (num > this.slides.length)
  989. num = 1;
  990. if (--num < 0)
  991. num = 0;
  992. return num;
  993. }
  994. // oh dear unknown anchor
  995. return 0;
  996. }
  997. // search for enclosing slide
  998. while (true)
  999. {
  1000. // browser coerces html elements to uppercase!
  1001. if (target.nodeName.toLowerCase() == "div" &&
  1002. this.has_class(target, "slide"))
  1003. {
  1004. // found the slide element
  1005. break;
  1006. }
  1007. // otherwise try parent element if any
  1008. target = target.parentNode;
  1009. if (!target)
  1010. {
  1011. return 0; // no luck!
  1012. }
  1013. };
  1014. for (i = 0; i < slides.length; ++i)
  1015. {
  1016. if (slides[i] == target)
  1017. return i; // success
  1018. }
  1019. // oh dear still no luck
  1020. return 0;
  1021. },
  1022. previous_slide: function (incremental) {
  1023. if (!w3c_slidy.view_all)
  1024. {
  1025. var slide;
  1026. if ((incremental || w3c_slidy.slide_number == 0) && w3c_slidy.last_shown != null)
  1027. {
  1028. w3c_slidy.last_shown = w3c_slidy.hide_previous_item(w3c_slidy.last_shown);
  1029. w3c_slidy.set_eos_status(false);
  1030. }
  1031. else if (w3c_slidy.slide_number > 0)
  1032. {
  1033. slide = w3c_slidy.slides[w3c_slidy.slide_number];
  1034. w3c_slidy.hide_slide(slide);
  1035. w3c_slidy.slide_number = w3c_slidy.slide_number - 1;
  1036. slide = w3c_slidy.slides[w3c_slidy.slide_number];
  1037. w3c_slidy.set_visibility_all_incremental("visible");
  1038. w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
  1039. w3c_slidy.set_eos_status(true);
  1040. w3c_slidy.show_slide(slide);
  1041. }
  1042. w3c_slidy.set_location();
  1043. if (!w3c_slidy.ns_pos)
  1044. w3c_slidy.refresh_toolbar(200);
  1045. }
  1046. },
  1047. next_slide: function (incremental) {
  1048. if (!w3c_slidy.view_all)
  1049. {
  1050. var slide, last = w3c_slidy.last_shown;
  1051. if (incremental || w3c_slidy.slide_number == w3c_slidy.slides.length - 1)
  1052. w3c_slidy.last_shown = w3c_slidy.reveal_next_item(w3c_slidy.last_shown);
  1053. if ((!incremental || w3c_slidy.last_shown == null) &&
  1054. w3c_slidy.slide_number < w3c_slidy.slides.length - 1)
  1055. {
  1056. slide = w3c_slidy.slides[w3c_slidy.slide_number];
  1057. w3c_slidy.hide_slide(slide);
  1058. w3c_slidy.slide_number = w3c_slidy.slide_number + 1;
  1059. slide = w3c_slidy.slides[w3c_slidy.slide_number];
  1060. w3c_slidy.last_shown = null;
  1061. w3c_slidy.set_visibility_all_incremental("hidden");
  1062. w3c_slidy.show_slide(slide);
  1063. }
  1064. else if (!w3c_slidy.last_shown)
  1065. {
  1066. if (last && incremental)
  1067. w3c_slidy.last_shown = last;
  1068. }
  1069. w3c_slidy.set_location();
  1070. w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
  1071. if (!w3c_slidy.ns_pos)
  1072. w3c_slidy.refresh_toolbar(200);
  1073. }
  1074. },
  1075. // to first slide with nothing revealed
  1076. // i.e. state at start of presentation
  1077. first_slide: function () {
  1078. if (!w3c_slidy.view_all)
  1079. {
  1080. var slide;
  1081. if (w3c_slidy.slide_number != 0)
  1082. {
  1083. slide = w3c_slidy.slides[w3c_slidy.slide_number];
  1084. w3c_slidy.hide_slide(slide);
  1085. w3c_slidy.slide_number = 0;
  1086. slide = w3c_slidy.slides[w3c_slidy.slide_number];
  1087. w3c_slidy.last_shown = null;
  1088. w3c_slidy.set_visibility_all_incremental("hidden");
  1089. w3c_slidy.show_slide(slide);
  1090. }
  1091. w3c_slidy.set_eos_status(
  1092. !w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
  1093. w3c_slidy.set_location();
  1094. }
  1095. },
  1096. // goto last slide with everything revealed
  1097. // i.e. state at end of presentation
  1098. last_slide: function () {
  1099. if (!w3c_slidy.view_all)
  1100. {
  1101. var slide;
  1102. w3c_slidy.last_shown = null; //revealNextItem(lastShown);
  1103. if (w3c_slidy.last_shown == null &&
  1104. w3c_slidy.slide_number < w3c_slidy.slides.length - 1)
  1105. {
  1106. slide = w3c_slidy.slides[w3c_slidy.slide_number];
  1107. w3c_slidy.hide_slide(slide);
  1108. w3c_slidy.slide_number = w3c_slidy.slides.length - 1;
  1109. slide = w3c_slidy.slides[w3c_slidy.slide_number];
  1110. w3c_slidy.set_visibility_all_incremental("visible");
  1111. w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
  1112. w3c_slidy.show_slide(slide);
  1113. }
  1114. else
  1115. {
  1116. w3c_slidy.set_visibility_all_incremental("visible");
  1117. w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
  1118. }
  1119. w3c_slidy.set_eos_status(true);
  1120. w3c_slidy.set_location();
  1121. }
  1122. },
  1123. // ### check this and consider add/remove class
  1124. set_eos_status: function (state) {
  1125. if (this.eos)
  1126. this.eos.style.color = (state ? "rgb(240,240,240)" : "red");
  1127. },
  1128. // first slide is 0
  1129. goto_slide: function (num) {
  1130. //alert("going to slide " + (num+1));
  1131. var slide = w3c_slidy.slides[w3c_slidy.slide_number];
  1132. w3c_slidy.hide_slide(slide);
  1133. w3c_slidy.slide_number = num;
  1134. slide = w3c_slidy.slides[w3c_slidy.slide_number];
  1135. w3c_slidy.last_shown = null;
  1136. w3c_slidy.set_visibility_all_incremental("hidden");
  1137. w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
  1138. document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")";
  1139. w3c_slidy.show_slide(slide);
  1140. w3c_slidy.show_slide_number();
  1141. },
  1142. show_slide: function (slide) {
  1143. this.sync_background(slide);
  1144. window.scrollTo(0,0);
  1145. this.remove_class(slide, "hidden");
  1146. },
  1147. hide_slide: function (slide) {
  1148. this.add_class(slide, "hidden");
  1149. },
  1150. // show just the backgrounds pertinent to this slide
  1151. // when slide background-color is transparent
  1152. // this should now work with rgba color values
  1153. sync_background: function (slide) {
  1154. var background;
  1155. var bgColor;
  1156. if (slide.currentStyle)
  1157. bgColor = slide.currentStyle["backgroundColor"];
  1158. else if (document.defaultView)
  1159. {
  1160. var styles = document.defaultView.getComputedStyle(slide,null);
  1161. if (styles)
  1162. bgColor = styles.getPropertyValue("background-color");
  1163. else // broken implementation probably due Safari or Konqueror
  1164. {
  1165. //alert("defective implementation of getComputedStyle()");
  1166. bgColor = "transparent";
  1167. }
  1168. }
  1169. else
  1170. bgColor == "transparent";
  1171. if (bgColor == "transparent" ||
  1172. bgColor.indexOf("rgba") >= 0 ||
  1173. bgColor.indexOf("opacity") >= 0)
  1174. {
  1175. var slideClass = this.get_class_list(slide);
  1176. for (var i = 0; i < this.backgrounds.length; i++)
  1177. {
  1178. background = this.backgrounds[i];
  1179. var bgClass = this.get_class_list(background);
  1180. if (this.matching_background(slideClass, bgClass))
  1181. this.remove_class(background, "hidden");
  1182. else
  1183. this.add_class(background, "hidden");
  1184. }
  1185. }
  1186. else // forcibly hide all backgrounds
  1187. this.hide_backgrounds();
  1188. },
  1189. hide_backgrounds: function () {
  1190. for (var i = 0; i < this.backgrounds.length; i++)
  1191. {
  1192. background = this.backgrounds[i];
  1193. this.add_class(background, "hidden");
  1194. }
  1195. },
  1196. // compare classes for slide and background
  1197. matching_background: function (slideClass, bgClass) {
  1198. var i, count, pattern, result;
  1199. // define pattern as regular expression
  1200. pattern = /\w+/g;
  1201. // check background class names
  1202. result = bgClass.match(pattern);
  1203. for (i = count = 0; i < result.length; i++)
  1204. {
  1205. if (result[i] == "hidden")
  1206. continue;
  1207. if (result[i] == "background")
  1208. continue;
  1209. ++count;
  1210. }
  1211. if (count == 0) // default match
  1212. return true;
  1213. // check for matches and place result in array
  1214. result = slideClass.match(pattern);
  1215. // now check if desired name is present for background
  1216. for (i = count = 0; i < result.length; i++)
  1217. {
  1218. if (result[i] == "hidden")
  1219. continue;
  1220. if (this.has_token(bgClass, result[i]))
  1221. return true;
  1222. }
  1223. return false;
  1224. },
  1225. resized: function () {
  1226. var width = 0;
  1227. if ( typeof( window.innerWidth ) == 'number' )
  1228. width = window.innerWidth; // Non IE browser
  1229. else if (document.documentElement && document.documentElement.clientWidth)
  1230. width = document.documentElement.clientWidth; // IE6
  1231. else if (document.body && document.body.clientWidth)
  1232. width = document.body.clientWidth; // IE4
  1233. var height = 0;
  1234. if ( typeof( window.innerHeight ) == 'number' )
  1235. height = window.innerHeight; // Non IE browser
  1236. else if (document.documentElement && document.documentElement.clientHeight)
  1237. height = document.documentElement.clientHeight; // IE6
  1238. else if (document.body && document.body.clientHeight)
  1239. height = document.body.clientHeight; // IE4
  1240. if (height && (width/height > 1.05*1024/768))
  1241. {
  1242. width = height * 1024.0/768;
  1243. }
  1244. // IE fires onresize even when only font size is changed!
  1245. // so we do a check to avoid blocking < and > actions
  1246. if (width != w3c_slidy.last_width || height != w3c_slidy.last_height)
  1247. {
  1248. if (width >= 1100)
  1249. w3c_slidy.size_index = 5; // 4
  1250. else if (width >= 1000)
  1251. w3c_slidy.size_index = 4; // 3
  1252. else if (width >= 800)
  1253. w3c_slidy.size_index = 3; // 2
  1254. else if (width >= 600)
  1255. w3c_slidy.size_index = 2; // 1
  1256. else if (width)
  1257. w3c_slidy.size_index = 0;
  1258. // add in font size adjustment from meta element e.g.
  1259. // <meta name="font-size-adjustment" content="-2" />
  1260. // useful when slides have too much content ;-)
  1261. if (0 <= w3c_slidy.size_index + w3c_slidy.size_adjustment &&
  1262. w3c_slidy.size_index + w3c_slidy.size_adjustment < w3c_slidy.sizes.length)
  1263. w3c_slidy.size_index = w3c_slidy.size_index + w3c_slidy.size_adjustment;
  1264. // enables cross browser use of relative width/height
  1265. // on object elements for use with SVG and Flash media
  1266. w3c_slidy.adjust_object_dimensions(width, height);
  1267. if (document.body.style.fontSize != w3c_slidy.sizes[w3c_slidy.size_index])
  1268. {
  1269. document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
  1270. }
  1271. w3c_slidy.last_width = width;
  1272. w3c_slidy.last_height = height;
  1273. // force reflow to work around Mozilla bug
  1274. if (w3c_slidy.ns_pos)
  1275. {
  1276. var slide = w3c_slidy.slides[w3c_slidy.slide_number];
  1277. w3c_slidy.hide_slide(slide);
  1278. w3c_slidy.show_slide(slide);
  1279. }
  1280. // force correct positioning of toolbar
  1281. w3c_slidy.refresh_toolbar(200);
  1282. }
  1283. },
  1284. scrolled: function () {
  1285. if (w3c_slidy.toolbar && !w3c_slidy.ns_pos && !w3c_slidy.ie7)
  1286. {
  1287. w3c_slidy.hack_offset = w3c_slidy.scroll_x_offset();
  1288. // hide toolbar
  1289. w3c_slidy.toolbar.style.display = "none";
  1290. // make it reappear later
  1291. if (w3c_slidy.scrollhack == 0 && !w3c_slidy.view_all)
  1292. {
  1293. setTimeout(function () {w3c_slidy.show_toolbar(); }, 1000);
  1294. w3c_slidy.scrollhack = 1;
  1295. }
  1296. }
  1297. },
  1298. hide_toolbar: function () {
  1299. w3c_slidy.add_class(w3c_slidy.toolbar, "hidden");
  1300. window.focus();
  1301. },
  1302. // used to ensure IE refreshes toolbar in correct position
  1303. refresh_toolbar: function (interval) {
  1304. if (!w3c_slidy.ns_pos && !w3c_slidy.ie7)
  1305. {
  1306. w3c_slidy.hide_toolbar();
  1307. setTimeout(function () {w3c_slidy.show_toolbar(); }, interval);
  1308. }
  1309. },
  1310. // restores toolbar after short delay
  1311. show_toolbar: function () {
  1312. if (w3c_slidy.want_toolbar)
  1313. {
  1314. w3c_slidy.toolbar.style.display = "block";
  1315. if (!w3c_slidy.ns_pos)
  1316. {
  1317. // adjust position to allow for scrolling
  1318. var xoffset = w3c_slidy.scroll_x_offset();
  1319. w3c_slidy.toolbar.style.left = xoffset;
  1320. w3c_slidy.toolbar.style.right = xoffset;
  1321. // determine vertical scroll offset
  1322. //var yoffset = scrollYOffset();
  1323. // bottom is doc height - window height - scroll offset
  1324. //var bottom = documentHeight() - lastHeight - yoffset
  1325. //if (yoffset > 0 || documentHeight() > lastHeight)
  1326. // bottom += 16; // allow for height of scrollbar
  1327. w3c_slidy.toolbar.style.bottom = 0; //bottom;
  1328. }
  1329. w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden");
  1330. }
  1331. w3c_slidy.scrollhack = 0;
  1332. // set the keyboard focus to the help link on the
  1333. // toolbar to ensure that document has the focus
  1334. // IE doesn't always work with window.focus()
  1335. // and this hack has benefit of Enter for help
  1336. try
  1337. {
  1338. if (!w3c_slidy.opera)
  1339. w3c_slidy.help_anchor.focus();
  1340. }
  1341. catch (e)
  1342. {
  1343. }
  1344. },
  1345. // invoked via F key
  1346. toggle_toolbar: function () {
  1347. if (!w3c_slidy.view_all)
  1348. {
  1349. if (w3c_slidy.has_class(w3c_slidy.toolbar, "hidden"))
  1350. {
  1351. w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden")
  1352. w3c_slidy.want_toolbar = 1;
  1353. }
  1354. else
  1355. {
  1356. w3c_slidy.add_class(w3c_slidy.toolbar, "hidden")
  1357. w3c_slidy.want_toolbar = 0;
  1358. }
  1359. }
  1360. },
  1361. scroll_x_offset: function () {
  1362. if (window.pageXOffset)
  1363. return self.pageXOffset;
  1364. if (document.documentElement &&
  1365. document.documentElement.scrollLeft)
  1366. return document.documentElement.scrollLeft;
  1367. if (document.body)
  1368. return document.body.scrollLeft;
  1369. return 0;
  1370. },
  1371. scroll_y_offset: function () {
  1372. if (window.pageYOffset)
  1373. return self.pageYOffset;
  1374. if (document.documentElement &&
  1375. document.documentElement.scrollTop)
  1376. return document.documentElement.scrollTop;
  1377. if (document.body)
  1378. return document.body.scrollTop;
  1379. return 0;
  1380. },
  1381. // looking for a way to determine height of slide content
  1382. // the slide itself is set to the height of the window
  1383. optimize_font_size: function () {
  1384. var slide = w3c_slidy.slides[w3c_slidy.slide_number];
  1385. //var dh = documentHeight(); //getDocHeight(document);
  1386. var dh = slide.scrollHeight;
  1387. var wh = getWindowHeight();
  1388. var u = 100 * dh / wh;
  1389. alert("window utilization = " + u + "% (doc "
  1390. + dh + " win " + wh + ")");
  1391. },
  1392. // from document object
  1393. get_doc_height: function (doc) {
  1394. if (!doc)
  1395. doc = document;
  1396. if (doc && doc.body && doc.body.offsetHeight)
  1397. return doc.body.offsetHeight; // ns/gecko syntax
  1398. if (doc && doc.body && doc.body.scrollHeight)
  1399. return doc.body.scrollHeight;
  1400. alert("couldn't determine document height");
  1401. },
  1402. get_window_height: function () {
  1403. if ( typeof( window.innerHeight ) == 'number' )
  1404. return window.innerHeight; // Non IE browser
  1405. if (document.documentElement && document.documentElement.clientHeight)
  1406. return document.documentElement.clientHeight; // IE6
  1407. if (document.body && document.body.clientHeight)
  1408. return document.body.clientHeight; // IE4
  1409. },
  1410. document_height: function () {
  1411. var sh, oh;
  1412. sh = document.body.scrollHeight;
  1413. oh = document.body.offsetHeight;
  1414. if (sh && oh)
  1415. {
  1416. return (sh > oh ? sh : oh);
  1417. }
  1418. // no idea!
  1419. return 0;
  1420. },
  1421. smaller: function () {
  1422. if (w3c_slidy.size_index > 0)
  1423. {
  1424. --w3c_slidy.size_index;
  1425. }
  1426. w3c_slidy.toolbar.style.display = "none";
  1427. document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
  1428. var slide = w3c_slidy.slides[w3c_slidy.slide_number];
  1429. w3c_slidy.hide_slide(slide);
  1430. w3c_slidy.show_slide(slide);
  1431. setTimeout(function () {w3c_slidy.show_toolbar(); }, 50);
  1432. },
  1433. bigger: function () {
  1434. if (w3c_slidy.size_index < w3c_slidy.sizes.length - 1)
  1435. {
  1436. ++w3c_slidy.size_index;
  1437. }
  1438. w3c_slidy.toolbar.style.display = "none";
  1439. document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
  1440. var slide = w3c_slidy.slides[w3c_slidy.slide_number];
  1441. w3c_slidy.hide_slide(slide);
  1442. w3c_slidy.show_slide(slide);
  1443. setTimeout(function () {w3c_slidy.show_toolbar(); }, 50);
  1444. },
  1445. // enables cross browser use of relative width/height
  1446. // on object elements for use with SVG and Flash media
  1447. // with thanks to Ivan Herman for the suggestion
  1448. adjust_object_dimensions: function (width, height) {
  1449. for( var i = 0; i < w3c_slidy.objects.length; i++ )
  1450. {
  1451. var obj = this.objects[i];
  1452. var mimeType = obj.getAttribute("type");
  1453. if (mimeType == "image/svg+xml" || mimeType == "application/x-shockwave-flash")
  1454. {
  1455. if ( !obj.initialWidth )
  1456. obj.initialWidth = obj.getAttribute("width");
  1457. if ( !obj.initialHeight )
  1458. obj.initialHeight = obj.getAttribute("height");
  1459. if ( obj.initialWidth && obj.initialWidth.charAt(obj.initialWidth.length-1) == "%" )
  1460. {
  1461. var w = parseInt(obj.initialWidth.slice(0, obj.initialWidth.length-1));
  1462. var newW = width * (w/100.0);
  1463. obj.setAttribute("width",newW);
  1464. }
  1465. if ( obj.initialHeight &&
  1466. obj.initialHeight.charAt(obj.initialHeight.length-1) == "%" )
  1467. {
  1468. var h = parseInt(obj.initialHeight.slice(0, obj.initialHeight.length-1));
  1469. var newH = height * (h/100.0);
  1470. obj.setAttribute("height", newH);
  1471. }
  1472. }
  1473. }
  1474. },
  1475. // needed for Opera to inhibit default behavior
  1476. // since Opera delivers keyPress even if keyDown
  1477. // was cancelled
  1478. key_press: function (event) {
  1479. if (!event)
  1480. event = window.event;
  1481. if (!w3c_slidy.key_wanted)
  1482. return w3c_slidy.cancel(event);
  1483. return true;
  1484. },
  1485. // See e.g. http://www.quirksmode.org/js/events/keys.html for keycodes
  1486. key_down: function (event) {
  1487. var key, target, tag;
  1488. w3c_slidy.key_wanted = true;
  1489. if (!event)
  1490. event = window.event;
  1491. // kludge around NS/IE differences
  1492. if (window.event)
  1493. {
  1494. key = window.event.keyCode;
  1495. target = window.event.srcElement;
  1496. }
  1497. else if (event.which)
  1498. {
  1499. key = event.which;
  1500. target = event.target;
  1501. }
  1502. else
  1503. return true; // Yikes! unknown browser
  1504. // ignore event if key value is zero
  1505. // as for alt on Opera and Konqueror
  1506. if (!key)
  1507. return true;
  1508. // avoid interfering with keystroke
  1509. // behavior for non-slidy chrome elements
  1510. if (!w3c_slidy.slidy_chrome(target) &&
  1511. w3c_slidy.special_element(target))
  1512. return true;
  1513. // check for concurrent control/command/alt key
  1514. // but are these only present on mouse events?
  1515. if (event.ctrlKey || event.altKey || event.metaKey)
  1516. return true;
  1517. // dismiss table of contents if visible
  1518. if (w3c_slidy.is_shown_toc() && key != 9 && key != 16 && key != 38 && key != 40)
  1519. {
  1520. w3c_slidy.hide_table_of_contents(true);
  1521. if (key == 27 || key == 84 || key == 67)
  1522. return w3c_slidy.cancel(event);
  1523. }
  1524. if (key == 34) // Page Down
  1525. {
  1526. if (w3c_slidy.view_all)
  1527. return true;
  1528. w3c_slidy.next_slide(false);
  1529. return w3c_slidy.cancel(event);
  1530. }
  1531. else if (key == 33) // Page Up
  1532. {
  1533. if (w3c_slidy.view_all)
  1534. return true;
  1535. w3c_slidy.previous_slide(false);
  1536. return w3c_slidy.cancel(event);
  1537. }
  1538. else if (key == 32) // space bar
  1539. {
  1540. w3c_slidy.next_slide(true);
  1541. return w3c_slidy.cancel(event);
  1542. }
  1543. else if (key == 37) // Left arrow
  1544. {
  1545. w3c_slidy.previous_slide(!event.shiftKey);
  1546. return w3c_slidy.cancel(event);
  1547. }
  1548. else if (key == 36) // Home
  1549. {
  1550. w3c_slidy.first_slide();
  1551. return w3c_slidy.cancel(event);
  1552. }
  1553. else if (key == 35) // End
  1554. {
  1555. w3c_slidy.last_slide();
  1556. return w3c_slidy.cancel(event);
  1557. }
  1558. else if (key == 39) // Right arrow
  1559. {
  1560. w3c_slidy.next_slide(!event.shiftKey);
  1561. return w3c_slidy.cancel(event);
  1562. }
  1563. else if (key == 13) // Enter
  1564. {
  1565. if (w3c_slidy.outline)
  1566. {
  1567. if (w3c_slidy.outline.visible)
  1568. w3c_slidy.fold(w3c_slidy.outline);
  1569. else
  1570. w3c_slidy.unfold(w3c_slidy.outline);
  1571. return w3c_slidy.cancel(event);
  1572. }
  1573. }
  1574. else if (key == 188) // < for smaller fonts
  1575. {
  1576. w3c_slidy.smaller();
  1577. return w3c_slidy.cancel(event);
  1578. }
  1579. else if (key == 190) // > for larger fonts
  1580. {
  1581. w3c_slidy.bigger();
  1582. return w3c_slidy.cancel(event);
  1583. }
  1584. else if (key == 189 || key == 109) // - for smaller fonts
  1585. {
  1586. w3c_slidy.smaller();
  1587. return w3c_slidy.cancel(event);
  1588. }
  1589. else if (key == 187 || key == 191 || key == 107) // = + for larger fonts
  1590. {
  1591. w3c_slidy.bigger();
  1592. return w3c_slidy.cancel(event);
  1593. }
  1594. else if (key == 83) // S for smaller fonts
  1595. {
  1596. w3c_slidy.smaller();
  1597. return w3c_slidy.cancel(event);
  1598. }
  1599. else if (key == 66) // B for larger fonts
  1600. {
  1601. w3c_slidy.bigger();
  1602. return w3c_slidy.cancel(event);
  1603. }
  1604. else if (key == 90) // Z for last slide
  1605. {
  1606. w3c_slidy.last_slide();
  1607. return w3c_slidy.cancel(event);
  1608. }
  1609. else if (key == 70) // F for toggle toolbar
  1610. {
  1611. w3c_slidy.toggle_toolbar();
  1612. return w3c_slidy.cancel(event);
  1613. }
  1614. else if (key == 65) // A for toggle view single/all slides
  1615. {
  1616. w3c_slidy.toggle_view();
  1617. return w3c_slidy.cancel(event);
  1618. }
  1619. else if (key == 75) // toggle action of left click for next page
  1620. {
  1621. w3c_slidy.mouse_click_enabled = !w3c_slidy.mouse_click_enabled;
  1622. var alert_msg = (w3c_slidy.mouse_click_enabled ?
  1623. "enabled" : "disabled") + " mouse click advance";
  1624. alert(w3c_slidy.localize(alert_msg));
  1625. return w3c_slidy.cancel(event);
  1626. }
  1627. else if (key == 84 || key == 67) // T or C for table of contents
  1628. {
  1629. if (w3c_slidy.toc)
  1630. w3c_slidy.toggle_table_of_contents();
  1631. return w3c_slidy.cancel(event);
  1632. }
  1633. else if (key == 72) // H for help
  1634. {
  1635. window.location = w3c_slidy.help_page;
  1636. return w3c_slidy.cancel(event);
  1637. }
  1638. //else alert("key code is "+ key);
  1639. return true;
  1640. },
  1641. // safe for both text/html and application/xhtml+xml
  1642. create_element: function (name) {
  1643. if (this.xhtml && (typeof document.createElementNS != 'undefined'))
  1644. return document.createElementNS("http://www.w3.org/1999/xhtml", name)
  1645. return document.createElement(name);
  1646. },
  1647. get_element_style: function (elem, IEStyleProp, CSSStyleProp) {
  1648. if (elem.currentStyle)
  1649. {
  1650. return elem.currentStyle[IEStyleProp];
  1651. }
  1652. else if (window.getComputedStyle)
  1653. {
  1654. var compStyle = window.getComputedStyle(elem, "");
  1655. return compStyle.getPropertyValue(CSSStyleProp);
  1656. }
  1657. return "";
  1658. },
  1659. // the string str is a whitespace separated list of tokens
  1660. // test if str contains a particular token, e.g. "slide"
  1661. has_token: function (str, token) {
  1662. if (str)
  1663. {
  1664. // define pattern as regular expression
  1665. var pattern = /\w+/g;
  1666. // check for matches
  1667. // place result in array
  1668. var result = str.match(pattern);
  1669. // now check if desired token is present
  1670. for (var i = 0; i < result.length; i++)
  1671. {
  1672. if (result[i] == token)
  1673. return true;
  1674. }
  1675. }
  1676. return false;
  1677. },
  1678. get_class_list: function (element) {
  1679. if (typeof element.className != 'undefined')
  1680. return element.className;
  1681. return element.getAttribute("class");
  1682. },
  1683. has_class: function (element, name) {
  1684. if (element.nodeType != 1)
  1685. return false;
  1686. var regexp = new RegExp("(^| )" + name + "\W*");
  1687. if (typeof element.className != 'undefined')
  1688. return regexp.test(element.className);
  1689. return regexp.test(element.getAttribute("class"));
  1690. },
  1691. remove_class: function (element, name) {
  1692. var regexp = new RegExp("(^| )" + name + "\W*");
  1693. var clsval = "";
  1694. if (typeof element.className != 'undefined')
  1695. {
  1696. clsval = element.className;
  1697. if (clsval)
  1698. {
  1699. clsval = clsval.replace(regexp, "");
  1700. element.className = clsval;
  1701. }
  1702. }
  1703. else
  1704. {
  1705. clsval = element.getAttribute("class");
  1706. if (clsval)
  1707. {
  1708. clsval = clsval.replace(regexp, "");
  1709. element.setAttribute("class", clsval);
  1710. }
  1711. }
  1712. },
  1713. add_class: function (element, name) {
  1714. if (!this.has_class(element, name))
  1715. {
  1716. if (typeof element.className != 'undefined')
  1717. element.className += " " + name;
  1718. else
  1719. {
  1720. var clsval = element.getAttribute("class");
  1721. clsval = clsval ? clsval + " " + name : name;
  1722. element.setAttribute("class", clsval);
  1723. }
  1724. }
  1725. },
  1726. // HTML elements that can be used with class="incremental"
  1727. // note that you can also put the class on containers like
  1728. // up, ol, dl, and div to make their contents appear
  1729. // incrementally. Upper case is used since this is what
  1730. // browsers report for HTML node names (text/html).
  1731. incremental_elements: null,
  1732. okay_for_incremental: function (name) {
  1733. if (!this.incremental_elements)
  1734. {
  1735. var inclist = new Array();
  1736. inclist["p"] = true;
  1737. inclist["pre"] = true;
  1738. inclist["li"] = true;
  1739. inclist["blockquote"] = true;
  1740. inclist["dt"] = true;
  1741. inclist["dd"] = true;
  1742. inclist["h2"] = true;
  1743. inclist["h3"] = true;
  1744. inclist["h4"] = true;
  1745. inclist["h5"] = true;
  1746. inclist["h6"] = true;
  1747. inclist["span"] = true;
  1748. inclist["address"] = true;
  1749. inclist["table"] = true;
  1750. inclist["tr"] = true;
  1751. inclist["th"] = true;
  1752. inclist["td"] = true;
  1753. inclist["img"] = true;
  1754. inclist["object"] = true;
  1755. this.incremental_elements = inclist;
  1756. }
  1757. return this.incremental_elements[name.toLowerCase()];
  1758. },
  1759. next_incremental_item: function (node) {
  1760. var br = this.is_xhtml ? "br" : "BR";
  1761. var slide = w3c_slidy.slides[w3c_slidy.slide_number];
  1762. for (;;)
  1763. {
  1764. node = w3c_slidy.next_node(slide, node);
  1765. if (node == null || node.parentNode == null)
  1766. break;
  1767. if (node.nodeType == 1) // ELEMENT
  1768. {
  1769. if (node.nodeName == br)
  1770. continue;
  1771. if (w3c_slidy.has_class(node, "incremental")
  1772. && w3c_slidy.okay_for_incremental(node.nodeName))
  1773. return node;
  1774. if (w3c_slidy.has_class(node.parentNode, "incremental")
  1775. && !w3c_slidy.has_class(node, "non-incremental"))
  1776. return node;
  1777. }
  1778. }
  1779. return node;
  1780. },
  1781. previous_incremental_item: function (node) {
  1782. var br = this.is_xhtml ? "br" : "BR";
  1783. var slide = w3c_slidy.slides[w3c_slidy.slide_number];
  1784. for (;;)
  1785. {
  1786. node = w3c_slidy.previous_node(slide, node);
  1787. if (node == null || node.parentNode == null)
  1788. break;
  1789. if (node.nodeType == 1)
  1790. {
  1791. if (node.nodeName == br)
  1792. continue;
  1793. if (w3c_slidy.has_class(node, "incremental")
  1794. && w3c_slidy.okay_for_incremental(node.nodeName))
  1795. return node;
  1796. if (w3c_slidy.has_class(node.parentNode, "incremental")
  1797. && !w3c_slidy.has_class(node, "non-incremental"))
  1798. return node;
  1799. }
  1800. }
  1801. return node;
  1802. },
  1803. // set visibility for all elements on current slide with
  1804. // a parent element with attribute class="incremental"
  1805. set_visibility_all_incremental: function (value) {
  1806. var node = this.next_incremental_item(null);
  1807. if (value == "hidden")
  1808. {
  1809. while (node)
  1810. {
  1811. w3c_slidy.add_class(node, "invisible");
  1812. node = w3c_slidy.next_incremental_item(node);
  1813. }
  1814. }
  1815. else // value == "visible"
  1816. {
  1817. while (node)
  1818. {
  1819. w3c_slidy.remove_class(node, "invisible");
  1820. node = w3c_slidy.next_incremental_item(node);
  1821. }
  1822. }
  1823. },
  1824. // reveal the next hidden item on the slide
  1825. // node is null or the node that was last revealed
  1826. reveal_next_item: function (node) {
  1827. node = w3c_slidy.next_incremental_item(node);
  1828. if (node && node.nodeType == 1) // an element
  1829. w3c_slidy.remove_class(node, "invisible");
  1830. return node;
  1831. },
  1832. // exact inverse of revealNextItem(node)
  1833. hide_previous_item: function (node) {
  1834. if (node && node.nodeType == 1) // an element
  1835. w3c_slidy.add_class(node, "invisible");
  1836. return this.previous_incremental_item(node);
  1837. },
  1838. // left to right traversal of root's content
  1839. next_node: function (root, node) {
  1840. if (node == null)
  1841. return root.firstChild;
  1842. if (node.firstChild)
  1843. return node.firstChild;
  1844. if (node.nextSibling)
  1845. return node.nextSibling;
  1846. for (;;)
  1847. {
  1848. node = node.parentNode;
  1849. if (!node || node == root)
  1850. break;
  1851. if (node && node.nextSibling)
  1852. return node.nextSibling;
  1853. }
  1854. return null;
  1855. },
  1856. // right to left traversal of root's content
  1857. previous_node: function (root, node) {
  1858. if (node == null)
  1859. {
  1860. node = root.lastChild;
  1861. if (node)
  1862. {
  1863. while (node.lastChild)
  1864. node = node.lastChild;
  1865. }
  1866. return node;
  1867. }
  1868. if (node.previousSibling)
  1869. {
  1870. node = node.previousSibling;
  1871. while (node.lastChild)
  1872. node = node.lastChild;
  1873. return node;
  1874. }
  1875. if (node.parentNode != root)
  1876. return node.parentNode;
  1877. return null;
  1878. },
  1879. previous_sibling_element: function (el) {
  1880. el = el.previousSibling;
  1881. while (el && el.nodeType != 1)
  1882. el = el.previousSibling;
  1883. return el;
  1884. },
  1885. next_sibling_element: function (el) {
  1886. el = el.nextSibling;
  1887. while (el && el.nodeType != 1)
  1888. el = el.nextSibling;
  1889. return el;
  1890. },
  1891. first_child_element: function (el) {
  1892. var node;
  1893. for (node = el.firstChild; node; node = node.nextSibling)
  1894. {
  1895. if (node.nodeType == 1)
  1896. break;
  1897. }
  1898. return node;
  1899. },
  1900. first_tag: function (element, tag) {
  1901. var node;
  1902. if (!this.is_xhtml)
  1903. tag = tag.toUpperCase();
  1904. for (node = element.firstChild; node; node = node.nextSibling)
  1905. {
  1906. if (node.nodeType == 1 && node.nodeName == tag)
  1907. break;
  1908. }
  1909. return node;
  1910. },
  1911. hide_selection: function () {
  1912. if (window.getSelection) // Firefox, Chromium, Safari, Opera
  1913. {
  1914. var selection = window.getSelection();
  1915. if (selection.rangeCount > 0)
  1916. {
  1917. var range = selection.getRangeAt(0);
  1918. range.collapse (false);
  1919. }
  1920. }
  1921. else // Internet Explorer
  1922. {
  1923. var textRange = document.selection.createRange ();
  1924. textRange.collapse (false);
  1925. }
  1926. },
  1927. get_selected_text: function () {
  1928. try
  1929. {
  1930. if (window.getSelection)
  1931. return window.getSelection().toString();
  1932. if (document.getSelection)
  1933. return document.getSelection().toString();
  1934. if (document.selection)
  1935. return document.selection.createRange().text;
  1936. }
  1937. catch (e)
  1938. {
  1939. }
  1940. return "";
  1941. },
  1942. // make note of length of selected text
  1943. // as this evaluates to zero in click event
  1944. mouse_button_up: function (e) {
  1945. w3c_slidy.selected_text_len = w3c_slidy.get_selected_text().length;
  1946. },
  1947. // right mouse button click is reserved for context menus
  1948. // it is more reliable to detect rightclick than leftclick
  1949. mouse_button_click: function (e) {
  1950. var rightclick = false;
  1951. var leftclick = false;
  1952. var middleclick = false;
  1953. var target;
  1954. if (!e)
  1955. var e = window.event;
  1956. if (e.target)
  1957. target = e.target;
  1958. else if (e.srcElement)
  1959. target = e.srcElement;
  1960. // work around Safari bug
  1961. if (target.nodeType == 3)
  1962. target = target.parentNode;
  1963. if (e.which) // all browsers except IE
  1964. {
  1965. leftclick = (e.which == 1);
  1966. middleclick = (e.which == 2);
  1967. rightclick = (e.which == 3);
  1968. }
  1969. else if (e.button)
  1970. {
  1971. // Konqueror gives 1 for left, 4 for middle
  1972. // IE6 gives 0 for left and not 1 as I expected
  1973. if (e.button == 4)
  1974. middleclick = true;
  1975. // all browsers agree on 2 for right button
  1976. rightclick = (e.button == 2);
  1977. }
  1978. else
  1979. leftclick = true;
  1980. if (w3c_slidy.selected_text_len > 0)
  1981. {
  1982. w3c_slidy.stop_propagation(e);
  1983. e.cancel = true;
  1984. e.returnValue = false;
  1985. return false;
  1986. }
  1987. // dismiss table of contents
  1988. w3c_slidy.hide_table_of_contents(false);
  1989. // check if target is something that probably want's clicks
  1990. // e.g. a, embed, object, input, textarea, select, option
  1991. var tag = target.nodeName.toLowerCase();
  1992. if (w3c_slidy.mouse_click_enabled && leftclick &&
  1993. !w3c_slidy.special_element(target) &&
  1994. !target.onclick)
  1995. {
  1996. w3c_slidy.next_slide(true);
  1997. w3c_slidy.stop_propagation(e);
  1998. e.cancel = true;
  1999. e.returnValue = false;
  2000. return false;
  2001. }
  2002. return true;
  2003. },
  2004. special_element: function (e) {
  2005. var tag = e.nodeName.toLowerCase();
  2006. return e.onkeydown ||
  2007. e.onclick ||
  2008. tag == "a" ||
  2009. tag == "embed" ||
  2010. tag == "object" ||
  2011. tag == "video" ||
  2012. tag == "audio" ||
  2013. tag == "input" ||
  2014. tag == "textarea" ||
  2015. tag == "select" ||
  2016. tag == "option";
  2017. },
  2018. slidy_chrome: function (el) {
  2019. while (el)
  2020. {
  2021. if (el == w3c_slidy.toc ||
  2022. el == w3c_slidy.toolbar ||
  2023. w3c_slidy.has_class(el, "outline"))
  2024. return true;
  2025. el = el.parentNode;
  2026. }
  2027. return false;
  2028. },
  2029. get_key: function (e)
  2030. {
  2031. var key;
  2032. // kludge around NS/IE differences
  2033. if (typeof window.event != "undefined")
  2034. key = window.event.keyCode;
  2035. else if (e.which)
  2036. key = e.which;
  2037. return key;
  2038. },
  2039. get_target: function (e) {
  2040. var target;
  2041. if (!e)
  2042. e = window.event;
  2043. if (e.target)
  2044. target = e.target;
  2045. else if (e.srcElement)
  2046. target = e.srcElement;
  2047. if (target.nodeType != 1)
  2048. target = target.parentNode;
  2049. return target;
  2050. },
  2051. // does display property provide correct defaults?
  2052. is_block: function (elem) {
  2053. var tag = elem.nodeName.toLowerCase();
  2054. return tag == "ol" || tag == "ul" || tag == "p" ||
  2055. tag == "li" || tag == "table" || tag == "pre" ||
  2056. tag == "h1" || tag == "h2" || tag == "h3" ||
  2057. tag == "h4" || tag == "h5" || tag == "h6" ||
  2058. tag == "blockquote" || tag == "address";
  2059. },
  2060. add_listener: function (element, event, handler) {
  2061. if (window.addEventListener)
  2062. element.addEventListener(event, handler, false);
  2063. else
  2064. element.attachEvent("on"+event, handler);
  2065. },
  2066. // used to prevent event propagation from field controls
  2067. stop_propagation: function (event) {
  2068. event = event ? event : window.event;
  2069. event.cancelBubble = true; // for IE
  2070. if (event.stopPropagation)
  2071. event.stopPropagation();
  2072. return true;
  2073. },
  2074. cancel: function (event) {
  2075. if (event)
  2076. {
  2077. event.cancel = true;
  2078. event.returnValue = false;
  2079. if (event.preventDefault)
  2080. event.preventDefault();
  2081. }
  2082. w3c_slidy.key_wanted = false;
  2083. return false;
  2084. },
  2085. // for each language define an associative array
  2086. // and also the help text which is longer
  2087. strings_es: {
  2088. "slide":"pág.",
  2089. "help?":"Ayuda",
  2090. "contents?":"Índice",
  2091. "table of contents":"tabla de contenidos",
  2092. "Table of Contents":"Tabla de Contenidos",
  2093. "restart presentation":"Reiniciar presentación",
  2094. "restart?":"Inicio"
  2095. },
  2096. help_es:
  2097. "Utilice el ratón, barra espaciadora, teclas Izda/Dcha, " +
  2098. "o Re pág y Av pág. Use S y B para cambiar el tamaño de fuente.",
  2099. strings_ca: {
  2100. "slide":"pàg..",
  2101. "help?":"Ajuda",
  2102. "contents?":"Índex",
  2103. "table of contents":"taula de continguts",
  2104. "Table of Contents":"Taula de Continguts",
  2105. "restart presentation":"Reiniciar presentació",
  2106. "restart?":"Inici"
  2107. },
  2108. help_ca:
  2109. "Utilitzi el ratolí, barra espaiadora, tecles Esq./Dta. " +
  2110. "o Re pàg y Av pàg. Usi S i B per canviar grandària de font.",
  2111. strings_cs: {
  2112. "slide":"snímek",
  2113. "help?":"nápověda",
  2114. "contents?":"obsah",
  2115. "table of contents":"obsah prezentace",
  2116. "Table of Contents":"Obsah prezentace",
  2117. "restart presentation":"znovu spustit prezentaci",
  2118. "restart?":"restart"
  2119. },
  2120. help_cs:
  2121. "Prezentaci můžete procházet pomocí kliknutí myši, mezerníku, " +
  2122. "šipek vlevo a vpravo nebo kláves PageUp a PageDown. Písmo se " +
  2123. "dá zvětšit a zmenšit pomocí kláves B a S.",
  2124. strings_nl: {
  2125. "slide":"pagina",
  2126. "help?":"Help?",
  2127. "contents?":"Inhoud?",
  2128. "table of contents":"inhoudsopgave",
  2129. "Table of Contents":"Inhoudsopgave",
  2130. "restart presentation":"herstart presentatie",
  2131. "restart?":"Herstart?"
  2132. },
  2133. help_nl:
  2134. "Navigeer d.m.v. het muis, spatiebar, Links/Rechts toetsen, " +
  2135. "of PgUp en PgDn. Gebruik S en B om de karaktergrootte te veranderen.",
  2136. strings_de: {
  2137. "slide":"Seite",
  2138. "help?":"Hilfe",
  2139. "contents?":"Übersicht",
  2140. "table of contents":"Inhaltsverzeichnis",
  2141. "Table of Contents":"Inhaltsverzeichnis",
  2142. "restart presentation":"Präsentation neu starten",
  2143. "restart?":"Neustart"
  2144. },
  2145. help_de:
  2146. "Benutzen Sie die Maus, Leerschlag, die Cursortasten links/rechts oder " +
  2147. "Page up/Page Down zum Wechseln der Seiten und S und B für die Schriftgrösse.",
  2148. strings_pl: {
  2149. "slide":"slajd",
  2150. "help?":"pomoc?",
  2151. "contents?":"spis treści?",
  2152. "table of contents":"spis treści",
  2153. "Table of Contents":"Spis Treści",
  2154. "restart presentation":"Restartuj prezentację",
  2155. "restart?":"restart?"
  2156. },
  2157. help_pl:
  2158. "Zmieniaj slajdy klikając myszą, naciskając spację, strzałki lewo/prawo" +
  2159. "lub PgUp / PgDn. Użyj klawiszy S i B, aby zmienić rozmiar czczionki.",
  2160. strings_fr: {
  2161. "slide":"page",
  2162. "help?":"Aide",
  2163. "contents?":"Index",
  2164. "table of contents":"table des matières",
  2165. "Table of Contents":"Table des matières",
  2166. "restart presentation":"Recommencer l'exposé",
  2167. "restart?":"Début"
  2168. },
  2169. help_fr:
  2170. "Naviguez avec la souris, la barre d'espace, les flèches " +
  2171. "gauche/droite ou les touches Pg Up, Pg Dn. Utilisez " +
  2172. "les touches S et B pour modifier la taille de la police.",
  2173. strings_hu: {
  2174. "slide":"oldal",
  2175. "help?":"segítség",
  2176. "contents?":"tartalom",
  2177. "table of contents":"tartalomjegyzék",
  2178. "Table of Contents":"Tartalomjegyzék",
  2179. "restart presentation":"bemutató újraindítása",
  2180. "restart?":"újraindítás"
  2181. },
  2182. help_hu:
  2183. "Az oldalak közti lépkedéshez kattintson az egérrel, vagy " +
  2184. "használja a szóköz, a bal, vagy a jobb nyíl, illetve a Page Down, " +
  2185. "Page Up billentyűket. Az S és a B billentyűkkel változtathatja " +
  2186. "a szöveg méretét.",
  2187. strings_it: {
  2188. "slide":"pag.",
  2189. "help?":"Aiuto",
  2190. "contents?":"Indice",
  2191. "table of contents":"indice",
  2192. "Table of Contents":"Indice",
  2193. "restart presentation":"Ricominciare la presentazione",
  2194. "restart?":"Inizio"
  2195. },
  2196. help_it:
  2197. "Navigare con mouse, barra spazio, frecce sinistra/destra o " +
  2198. "PgUp e PgDn. Usare S e B per cambiare la dimensione dei caratteri.",
  2199. strings_el: {
  2200. "slide":"σελίδα",
  2201. "help?":"βοήθεια;",
  2202. "contents?":"περιεχόμενα;",
  2203. "table of contents":"πίνακας περιεχομένων",
  2204. "Table of Contents":"Πίνακας Περιεχομένων",
  2205. "restart presentation":"επανεκκίνηση παρουσίασης",
  2206. "restart?":"επανεκκίνηση;"
  2207. },
  2208. help_el:
  2209. "Πλοηγηθείτε με το κλίκ του ποντικιού, το space, τα βέλη αριστερά/δεξιά, " +
  2210. "ή Page Up και Page Down. Χρησιμοποιήστε τα πλήκτρα S και B για να αλλάξετε " +
  2211. "το μέγεθος της γραμματοσειράς.",
  2212. strings_ja: {
  2213. "slide":"スライド",
  2214. "help?":"ヘルプ",
  2215. "contents?":"目次",
  2216. "table of contents":"目次を表示",
  2217. "Table of Contents":"目次",
  2218. "restart presentation":"最初から再生",
  2219. "restart?":"最初から"
  2220. },
  2221. help_ja:
  2222. "マウス左クリック ・ スペース ・ 左右キー " +
  2223. "または Page Up ・ Page Downで操作, S ・ Bでフォントサイズ変更",
  2224. strings_zh: {
  2225. "slide":"幻灯片",
  2226. "help?":"帮助?",
  2227. "contents?":"内容?",
  2228. "table of contents":"目录",
  2229. "Table of Contents":"目录",
  2230. "restart presentation":"重新启动展示",
  2231. "restart?":"重新启动?"
  2232. },
  2233. help_zh:
  2234. "用鼠标点击, 空格条, 左右箭头, Pg Up 和 Pg Dn 导航. " +
  2235. "用 S, B 改变字体大小.",
  2236. strings_ru: {
  2237. "slide":"слайд",
  2238. "help?":"помощь?",
  2239. "contents?":"содержание?",
  2240. "table of contents":"оглавление",
  2241. "Table of Contents":"Оглавление",
  2242. "restart presentation":"перезапустить презентацию",
  2243. "restart?":"перезапуск?"
  2244. },
  2245. help_ru:
  2246. "Перемещайтесь кликая мышкой, используя клавишу пробел, стрелки" +
  2247. "влево/вправо или Pg Up и Pg Dn. Клавиши S и B меняют размер шрифта.",
  2248. strings_sv: {
  2249. "slide":"sida",
  2250. "help?":"hjälp",
  2251. "contents?":"innehåll",
  2252. "table of contents":"innehållsförteckning",
  2253. "Table of Contents":"Innehållsförteckning",
  2254. "restart presentation":"visa presentationen från början",
  2255. "restart?":"börja om"
  2256. },
  2257. help_sv:
  2258. "Bläddra med ett klick med vänstra musknappen, mellanslagstangenten, " +
  2259. "vänster- och högerpiltangenterna eller tangenterna Pg Up, Pg Dn. " +
  2260. "Använd tangenterna S och B för att ändra textens storlek.",
  2261. strings: { },
  2262. localize: function (src) {
  2263. if (src == "")
  2264. return src;
  2265. // try full language code, e.g. en-US
  2266. var s, lookup = w3c_slidy.strings[w3c_slidy.lang];
  2267. if (lookup)
  2268. {
  2269. s = lookup[src];
  2270. if (s)
  2271. return s;
  2272. }
  2273. // strip country code suffix, e.g.
  2274. // try en if undefined for en-US
  2275. var lg = w3c_slidy.lang.split("-");
  2276. if (lg.length > 1)
  2277. {
  2278. lookup = w3c_slidy.strings[lg[0]];
  2279. if (lookup)
  2280. {
  2281. s = lookup[src];
  2282. if (s)
  2283. return s;
  2284. }
  2285. }
  2286. // otherwise string as is
  2287. return src;
  2288. },
  2289. init_localization: function () {
  2290. var i18n = w3c_slidy;
  2291. var help_text = w3c_slidy.help_text;
  2292. // each such language array is declared in the localize array
  2293. // this is used as in w3c_slidy.localize("foo");
  2294. this.strings = {
  2295. "es":this.strings_es,
  2296. "ca":this.strings_ca,
  2297. "cs":this.strings_cs,
  2298. "nl":this.strings_nl,
  2299. "de":this.strings_de,
  2300. "pl":this.strings_pl,
  2301. "fr":this.strings_fr,
  2302. "hu":this.strings_hu,
  2303. "it":this.strings_it,
  2304. "el":this.strings_el,
  2305. "jp":this.strings_ja,
  2306. "zh":this.strings_zh,
  2307. "ru":this.strings_ru,
  2308. "sv":this.strings_sv
  2309. },
  2310. i18n.strings_es[help_text] = i18n.help_es;
  2311. i18n.strings_ca[help_text] = i18n.help_ca;
  2312. i18n.strings_cs[help_text] = i18n.help_cs;
  2313. i18n.strings_nl[help_text] = i18n.help_nl;
  2314. i18n.strings_de[help_text] = i18n.help_de;
  2315. i18n.strings_pl[help_text] = i18n.help_pl;
  2316. i18n.strings_fr[help_text] = i18n.help_fr;
  2317. i18n.strings_hu[help_text] = i18n.help_hu;
  2318. i18n.strings_it[help_text] = i18n.help_it;
  2319. i18n.strings_el[help_text] = i18n.help_el;
  2320. i18n.strings_ja[help_text] = i18n.help_ja;
  2321. i18n.strings_zh[help_text] = i18n.help_zh;
  2322. i18n.strings_ru[help_text] = i18n.help_ru;
  2323. i18n.strings_sv[help_text] = i18n.help_sv;
  2324. w3c_slidy.lang = document.body.parentNode.getAttribute("lang");
  2325. if (!w3c_slidy.lang)
  2326. w3c_slidy.lang = document.body.parentNode.getAttribute("xml:lang");
  2327. if (!w3c_slidy.lang)
  2328. w3c_slidy.lang = "en";
  2329. }
  2330. };
  2331. // hack for back button behavior
  2332. if (w3c_slidy.ie6 || w3c_slidy.ie7)
  2333. {
  2334. document.write("<iframe id='historyFrame' " +
  2335. "src='javascript:\"<html"+"></"+"html>\"' " +
  2336. "height='1' width='1' " +
  2337. "style='position:absolute;left:-800px'></iframe>");
  2338. }
  2339. // attach event listeners for initialization
  2340. w3c_slidy.set_up();
  2341. // hide the slides as soon as body element is available
  2342. // to reduce annoying screen mess before the onload event
  2343. setTimeout(w3c_slidy.hide_slides, 50);