comparison ui/slidy2/scripts/slidy.js @ 0:b0c6281822f5

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