source: stylesheets/lfs-xsl/docbook-xsl-1.78.1/slides/slidy/scripts/slidy.js@ 112db9d

7.5-systemd 7.6-systemd 7.7-systemd 7.8-systemd 7.9-systemd
Last change on this file since 112db9d was b1a51ac1, checked in by Krejzi <krejzi@…>, 11 years ago

Import new branch

git-svn-id: http://svn.linuxfromscratch.org/LFS/branches/systemd/BOOK@10389 4aa44e1e-78dd-0310-a6d2-fbcd4c07a689

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