Some fixes in the CSS for printout mode and correct selection of current theme in...
[hacks/simpleWebSlides.git] / simpleWebSlides.js
1 /*
2   Namespace object.
3 */
4
5 var SWS = SWS || {};
6
7
8
9 SWS.Utils = new function () {
10     var self = this;
11
12     self.isUndefined = function (o) { return typeof o == "undefined"; };
13     self.push2 = function (t, i, v) {
14         if ((typeof t[i]) == 'undefined') {
15             t[i] = new Array();
16         };
17         var l = t[i].length;
18         t[i][l] = v;
19     };
20
21     self.isEmpty = function (o) {
22         for(var _ in o) return false;
23         return true;
24     };
25
26     self.parseFrameSpec = function (s) {
27         var elems = s.split("_");
28         var result = {};
29         var min_last = 10000;
30         var max_value = -1;
31         for(var i = 0; i < elems.length; i++){
32             var bounds = elems[i].split("-");
33             if (bounds.length > 2 || bounds.length == 0) return {};
34             if (bounds.length == 1) bounds[1] = bounds[0];
35             var a = parseInt(bounds[0]);
36             var b = parseInt(bounds[1])
37             if (!isFinite(a) || !isFinite(b)) return {};
38             a = Math.min(a, 1000); // don't allow more than 1000 frames/slide
39             b = Math.min(b, 1000);
40             if (b > max_value) max_value = b;
41             for (var j = a; j <= b; j++)
42                 result[j] = true;
43         };
44         return result;
45     };
46
47     self.getParameterByName = function (name) {
48         name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
49         var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
50         results = regex.exec(location.search);
51         return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
52     }
53 };
54
55
56
57
58 SWS.Templates = new function () {
59     var self = this;
60     self.controlPanel = "<div id='sws-control-panel-canvas'><div id='sws-control-panel'>\
61 <div id='sws-control-panel-title-bar'>\
62 <a title='Toggle fullscreen' id='sws-control-panel-fullscreen' class='sws-symbol' onclick='SWS.Presentation.toggleFullScreen();'></a>\
63 <a title='Close panel' id='sws-control-panel-close' onclick='$(\"#sws-control-panel-canvas\").toggle();'>&#x2716;</a>\
64 </div>\
65 <div id='sws-control-panel-options'>\
66 <span title='Change the aspect ratio' class='sws-symbol' >&#x1f4bb;</span><select id='sws-aspect-select' onchange='SWS.Presentation.changeAspect();'>\
67 <option value='sws-aspect-4-3'>4:3</option>\
68 <option value='sws-aspect-16-9'>16:9</option>\
69 <option value='sws-aspect-16-10'>16:10</option>\
70 </select>\
71 <span title='Change the theme' class='sws-symbol'>&#x1f3a8;</span><select id='sws-theme-select' onchange='SWS.Presentation.changeTheme();'></select>\
72 <a onclick='SWS.Presentation.openPrint()' ><span title='Open Print-Out' class='sws-symbol'>&#59158;</span></a>\
73 </div>\
74 <div id='sws-control-panel-navigation'>\
75 <a title='First slide' class='sws-symbol' onclick='SWS.Presentation.goToSlide(SWS.Presentation.firstSlide());' >&#x23ee;</a>\
76 <a title='Previous slide' class='sws-symbol' onclick='SWS.Presentation.previousSlide();SWS.Presentation.refresh();'>&#x23ea;</a>\
77 <a title='Previous step' class='sws-symbol' style='-webkit-transform: scaleX(-1);' onclick='SWS.Presentation.previous();SWS.Presentation.refresh();'>&#x25b6;</a>\
78 <a title='Next step' class='sws-symbol' onclick='SWS.Presentation.next();SWS.Presentation.refresh();'>&#x25b6;</a>\
79 <a title='Next slide' class='sws-symbol' onclick='SWS.Presentation.nextSlide();SWS.Presentation.refresh();'>&#x23e9;</a>\
80 <a title='Last slide' class='sws-symbol' onclick='SWS.Presentation.goToSlide(SWS.Presentation.lastSlide());'>&#x23ed;</a>\
81 <br/>\
82 <span class='sws-symbol'>&#xe4ae;</span><input type='text' id='sws-control-panel-slide-input' oninput='SWS.Presentation.goToSlide($(\"#sws-control-panel-slide-input\").val()-1);'></input><span id='sws-control-panel-total-slides'></span>\
83 <input type='range' title='Navigate the presentation' id='sws-control-panel-navigation-bar' onchange='SWS.Presentation.navigate();' step='1'></input>\
84 </div>\
85 </div>\
86 </div>";
87     self.slideActivate = function (o) {
88         if (!(o.hasClass("sws-active-slide"))){
89             o.removeClass("sws-inactive-slide").addClass("sws-active-slide");
90         };
91     };
92
93     self.slideDeactivate = function (o) {
94         if (!(o.hasClass("sws-inactive-slide"))){
95             o.removeClass("sws-active-slide").addClass("sws-inactive-slide");
96         };
97     };
98
99     self.slideChange = function (from, to) {
100         var canvas = $(".sws-canvas");
101         self.slideDeactivate($(canvas[from]));
102         self.slideActivate($(canvas[to]));
103     };
104
105     self.objectActivate = function (o) {
106         if (!(o.hasClass("sws-active-object"))){
107             o.removeClass("sws-inactive-object").addClass("sws-active-object");
108             o.css('visibility','visible');
109             return true;
110         };
111         return false;
112     };
113
114     self.objectDeactivate = function (o) {
115         if (!(o.hasClass("sws-inactive-object"))){
116             o.addClass("sws-inactive-object").removeClass("sws-active-object");
117             return true;
118         };
119         return false;
120     };
121
122     self.updateFooter = function (o) {
123         var footer = o.find(".sws-footer");
124         if (footer.length && (footer.children("*").length == 0)) {
125             var i = SWS.Presentation.getCurrentSlide();
126             var cur = $( "<span class='sws-current-slide-number'>"
127                          + (i + 1)
128                          +"</span>");
129             var sep = $( "<span class='sws-slide-num-sep' />");
130             var tot = $( "<span class='sws-last-slide-number'>"
131                          + (SWS.Presentation.getNumSlides())
132                          +"</span>");
133             footer.append(cur).append(sep).append(tot);
134         };
135     };
136     self.updateHeader = function (o) {};
137 };
138 SWS.ConfigBuilder = function () {
139     var self = this;
140     self['sws-object-activate'] = SWS.Templates.objectActivate;
141     self['sws-object-deactivate'] = SWS.Templates.objectDeactivate;
142     self['sws-slide-change'] = SWS.Templates.slideChange;
143     self['sws-update-footer'] = SWS.Templates.updateFooter;
144     self['sws-update-header'] = SWS.Templates.updateHeader;
145 };
146
147 SWS.Defaults = new SWS.ConfigBuilder ();
148
149 SWS.Config = new SWS.ConfigBuilder ();
150
151
152 SWS.Effects = new function () {
153     var self = this;
154
155     self.objectDeactivateFadeOut = function (o) {
156         o.animate({'opacity': '0'}, 200,
157                   function () { SWS.Templates.objectDeactivate(o)});
158     };
159
160     self.objectActivateFadeIn = function (o) {
161
162         if (SWS.Templates.objectActivate(o)){
163             o.animate({'opacity': '1' }, 200);
164         };
165
166     };
167
168     self.slideChangeHorizontalFlip = function (from, to){
169         var f = SWS.Presentation.getSlide(from);
170         var t = SWS.Presentation.getSlide(to);
171         f.animate({ 'left': '50%', 'width': '0pt', 'opacity':'0' }, 150,
172                   function  () {
173                       SWS.Templates.slideDeactivate(f);
174                       f.css({'left':'0%', 'width': '100%'});
175                       t.css({ 'left': '50%', 'width': '0pt','opacity':'0' });
176                       SWS.Templates.slideActivate(t);
177                       t.animate({'left':'0%', 'width': '100%','opacity':'1'});
178                   });
179     };
180     self.slideChangeFadeOutIn = function (from, to) {
181         var f = SWS.Presentation.getSlide(from);
182         var t = SWS.Presentation.getSlide(to);
183         f.animate({ 'opacity': '0'}, 150,
184                   function () { SWS.Templates.slideDeactivate(f);
185                                 SWS.Templates.slideActivate(t);
186                                 t.css('opacity', '0');
187                                 t.animate({ 'opacity': '1'}, 150);
188                               });
189     };
190     self.slideChangeHorizontalSlide = function (from, to) {
191         var f = SWS.Presentation.getSlide(from);
192         var t = SWS.Presentation.getSlide(to);
193         if (from < to) {
194             t.css('left', '100%');
195             t.css('opacity', '1');
196             SWS.Templates.slideActivate(t);
197             f.animate({ 'left': '-100%' }, 250, function () { SWS.Templates.slideDeactivate(f);
198                                                               f.css('opacity', '0');
199                                                               t.animate({ 'left': '0%' }, 250);
200                                                             });
201         } else {
202             t.css('left', '-100%');
203             SWS.Templates.slideActivate(t);
204             f.animate({ 'left': '100%' }, 250, function () { SWS.Templates.slideDeactivate(f);
205                                                              f.css('opacity', '0');
206                                                            });
207             t.css('opacity', '1');
208             t.animate({ 'left': '0%' }, 250);
209         };
210     };
211
212
213     self.slideChangeVerticalSlide = function (from, to) {
214         var f = SWS.Presentation.getSlide(from);
215         var t = SWS.Presentation.getSlide(to);
216         if (from < to) {
217             t.css('top', '100%');
218             SWS.Templates.slideActivate(t);
219             f.animate({ 'top': '-100%' }, 250, function () { SWS.Templates.slideDeactivate(f); });
220             t.animate({ 'top': '0%' }, 250);
221         } else {
222             t.css('top', '-100%');
223             SWS.Templates.slideActivate(t);
224             f.animate({ 'top': '100%' }, 250, function () { SWS.Templates.slideDeactivate(f); });
225             t.animate({ 'top': '0%' }, 250);
226         };
227     };
228
229 };
230
231 SWS.Fullscreen = new function () {
232     var self = this;
233
234     if (SWS.Utils.isUndefined(document.fullScreen)) {
235         if (SWS.Utils.isUndefined(document.mozfullScreen)) {
236             self.status = function () { return document.webkitIsFullScreen; };
237             self.enter = function(e) {
238                 e.webkitRequestFullScreen();
239             };
240             self.exit = function () {
241                 document.webkitCancelFullScreen();
242             };
243
244         } else {
245             self.status = function () { return document.mozfullScreen; };
246             self.enter = function(e) {
247                 e.mozRequestFullScreen();
248             };
249             self.exit = function () {
250                 document.mozCancelFullScreen();
251             };
252
253         };
254     } else {
255             self.status = function () { return document.fullScreen; };
256             self.enter = function(e) {
257                 e.requestFullScreen();
258             };
259             self.exit = function () {
260                 document.cancelFullScreen();
261             };
262
263     };
264
265
266 };
267
268 SWS.Presentation = new function () {
269
270
271     var self = this;
272
273     //TODO move outside of the Presentation object
274
275
276     var _total_slides;
277     var _initialized = false;
278     var _disable_input_events = false;
279     var _print_mode = false;
280     var _slide_callbacks = new Array ();
281     var _total_steps = -1;
282     var _current_theme = "";
283
284     self.getNumSlides = function () { return _total_slides; };
285
286     self.getSlide = function(i) {
287         return $($(".sws-canvas")[i]);
288     };
289
290     self.registerCallback = function (i, f) {
291         if (_initialized) return;
292         //jQuery does not seem to work well
293         //on a partial DOM
294
295         var slide_num = $(".sws-slide").length - 1;
296
297         SWS.Utils.push2(_slide_callbacks, slide_num,{ 'fn': f, 'frame': i });
298
299     };
300
301     if (typeof(Storage)!=="undefined"){
302         self.getCurrentSlide = function () {
303             //unary + casts to integer
304             var i = +(sessionStorage.getItem("current_slide"));
305             if (!(i >= 0 && i < self.getNumSlides())){
306                 return 0;
307             } else {
308                 return i;
309             };
310         };
311
312         self.setCurrentSlide = function (i) {
313             sessionStorage.setItem("current_slide", i);
314         };
315
316     } else {
317         var _current_slide = 0;
318         self.getCurrentSlide = function () { return _current_slide; };
319         self.setCurrentSlide = function (i) { _current_slide = i; };
320
321     };
322     self.firstSlide = function () { return 0; };
323     self.lastSlide = function () { return self.getNumSlides() - 1; };
324     self.refresh = function () {
325         /* block upcoming input event until all animations are finished */
326         _disable_input_events = true;
327
328         var canvas = $(".sws-canvas");
329         var from_slide_num = canvas.index($(".sws-active-slide"));
330         var to_slide_num = self.getCurrentSlide();
331         var watch_slide_anim = false;
332         var to_slide = $(canvas[to_slide_num]);
333         var from_slide = $(canvas[from_slide_num]);
334         var slide_change = (from_slide_num != to_slide_num);
335
336
337         var info = to_slide.data("sws-frame-info");
338         SWS.Config['sws-update-header'](to_slide);
339         SWS.Config['sws-update-footer'](to_slide);
340
341         if (slide_change) {
342             //Launch a slide transition:
343             SWS.Config['sws-slide-change'](from_slide_num, to_slide_num);
344             watch_slide_anim = true;
345             for (var i = 0; i < info.callbacks.at_slide.length;i++){
346                 info.callbacks.at_slide[i](to_slide);
347             };
348         };
349
350
351         var cur = info.current;
352         var custom = info.custom;
353         var real_slide = to_slide.find(".sws-slide");
354
355         real_slide.find("*").andSelf().each(function (i){
356             var frameset = $(this).data("sws-frame-set") || {};
357             if (frameset[cur])
358                 SWS.Config['sws-object-activate']($(this));
359             else
360                 SWS.Config['sws-object-deactivate']($(this));
361         });
362
363         var callbacks;
364         if (callbacks = info.callbacks.at_frame[self.getCurrentFrame()]){
365             for (var k = 0; k < callbacks.length; k++)
366                 callbacks[k]($(to_slide));
367         };
368
369         var all = $(from_slide).add(to_slide);
370         all.find("*").addBack().promise().done(function() {
371             _disable_input_events = false;
372         });
373     };
374
375     self.nextSlide = function () {
376         self.setCurrentSlide(Math.min(self.getCurrentSlide()+1,
377                                       self.lastSlide()));
378         self.setCurrentFrame(self.firstFrame());
379     };
380
381     self.previousSlide = function () {
382         self.setCurrentSlide(Math.max(self.getCurrentSlide()-1,
383                                       self.firstSlide()));
384         self.setCurrentFrame(self.firstFrame());
385     };
386
387     self.getFrameInfo = function () {
388
389         var i = self.getCurrentSlide();
390         var canvas = $($(".sws-canvas")[i]);
391         var infos = canvas.data("sws-frame-info");
392         return infos;
393     };
394
395     self.getTotalSteps = function () {
396         if (_total_steps >= 0) return _total_steps;
397         _total_steps = 0;
398         $(".sws-canvas").each(function(i) {
399             var canvas = $($(".sws-canvas")[i]);
400             var infos = canvas.data("sws-frame-info");
401             console.log(infos);
402             _total_steps += infos.last + 1;
403         });
404         return _total_steps;
405     };
406
407     self.getCurrentFrame = function () { return self.getFrameInfo().current; };
408     self.setCurrentFrame = function (i) { self.getFrameInfo().current = i; };
409     self.firstFrame = function () { return 0; };
410     self.lastFrame = function () { return self.getFrameInfo().last; };
411
412     self.nextFrame = function () {
413         self.setCurrentFrame(Math.min(self.getCurrentFrame()+1,
414                                       self.lastFrame()));
415
416     };
417     self.previousFrame = function () {
418         self.setCurrentFrame(Math.max(self.getCurrentFrame()-1,
419                                        self.firstFrame()));
420     };
421
422     self.next = function () {
423         var i = self.getCurrentFrame();
424         if (i == self.lastFrame()) {
425             self.nextSlide();
426             self.setCurrentFrame(self.firstFrame());
427         } else
428             self.nextFrame();
429     };
430
431     self.previous = function () {
432         var i = self.getCurrentFrame();
433         if (i == self.firstFrame()){
434             self.previousSlide();
435             self.setCurrentFrame(self.lastFrame());
436         }
437         else
438             self.previousFrame();
439     };
440
441     self.goToSlide = function (s, f) {
442         if (SWS.Utils.isUndefined(f))
443             f = 0;
444         if (!(s >= self.firstSlide() && s <= self.lastSlide())) return;
445         self.setCurrentSlide(s);
446         if (!(f >= self.firstFrame() && f <= self.lastFrame())) f = 0;
447         self.setCurrentFrame(f);
448         self.refresh();
449     };
450
451     self.cycleStyle = function() {
452         var styles = $("head").children('link[rel$="stylesheet"][title]');
453         var j = styles.index(styles.filter(':not(:disabled)'));
454         styles[j].disabled = true;
455         if (++j == styles.length) j = 0;
456         styles[j].disabled = false;
457     };
458
459
460     self.printMode = function () {
461         _print_mode = true;
462         var progress = $("<div style='position:fixed;top:0pt;left:0pt;background:white;color:black;width:100%;height:100vh;z-index:200;' id='sws-print-progress'>Rendering presentation: <span id='sws-percent-progress'></span>%</div>");
463         $("body").append(progress);
464
465         $("html").removeClass("sws-display").addClass("sws-print");
466         self.goToSlide(0,0);
467         var steps = self.getTotalSteps();
468         var total_steps = steps;
469         var loop;
470         loop = function () {
471             if (steps >= 0) {
472                 //Crazy workaround for chromium
473                 ($("link.sws-theme[rel='stylesheet']")[0]).disabled = false;
474                 $(".sws-canvas").find("*").addBack().promise().done(function() {
475                     var percent = ((total_steps - steps) / total_steps) * 100;
476                     $("#sws-percent-progress").text(Math.round(percent));
477                     SWS.Config['sws-slide-change'] = SWS.Templates.slideChange;
478                     self.refresh();
479                     $($(".sws-canvas")[self.getCurrentSlide()]).css('opacity', 1 );
480                     self.next();
481                     steps--;
482                     loop();
483                     })
484             } else {
485                 $("#sws-percent-progress").text(100);
486                 progress.remove();
487             }
488         };
489         loop();
490
491     }
492
493     self.inputHandler = function (event) {
494         if (_disable_input_events || _print_mode ) return;
495         switch (event.which) {
496         case 36:/* Home */
497             self.setCurrentSlide(self.firstSlide());
498             break;
499
500         case 35:/* End */
501             self.setCurrentSlide(self.lastSlide());
502             break;
503
504         case 32: /* space */
505         case 34: /* PgDown */
506         case 39: /* -> */
507             if (self.getCurrentSlide() == self.lastSlide()
508                 && self.getCurrentFrame() == self.lastFrame()) return;
509             self.next();
510             break;
511         case 78: /* n */
512             self.nextSlide();
513             break;
514         case 8: /* backspace */
515         case 33: /* PgUp */
516         case 37: /* <-   */
517             self.previous();
518             break;
519         case 80: /* p */
520             self.previousSlide();
521             break;
522         case 83: /* s */
523             self.cycleStyle();
524             return;
525         case 67: /* c */
526             $("#sws-control-panel-canvas").toggle();
527         default:
528             return;
529         };
530         self.refresh();
531     };
532
533
534
535     function init_canvas(canvas, custom) {
536         var cur_frame = 0;
537         var last_frame = canvas.find(".sws-pause").length;
538         //Add all regular elements to the frame list
539         var slide = $(canvas.find(".sws-slide")[0]);
540
541         var callbacks = { at_slide : new Array(),
542                           at_frame : new Array() }
543
544         if (SWS.Utils.isUndefined(custom)) {
545             custom = new Array ();
546         };
547
548         for (var i = 0; i < custom.length; i++) {
549             if (isFinite(custom[i].frame)){
550                 var num = +(custom[i].frame);
551                 if (num > last_frame) last_frame = num;
552                 SWS.Utils.push2(callbacks.at_frame, num, custom[i].fn);
553             } else if (custom[i].frame == "slide")
554                 callbacks.at_slide.push(custom[i].fn);
555             else {
556                 var frame_set = SWS.Utils.parseFrameSpec(custom[i].frame);
557                 for(var f in frame_set){
558                     if (f > last_frame) last_frame = f;
559                     SWS.Utils.push2(callbacks.at_frame, +(f), custom[i].fn);
560                 };
561             }
562         };
563
564         var specials = null;
565
566         slide.find('*[class*="sws-onframe-"]').each(function(_){
567             var cls = $(this).attr('class');
568             var idx = cls.indexOf("sws-onframe-");
569             if (idx >= 0) {
570                 var end = cls.indexOf(" ", idx);
571                 end = (end == -1) ? cls.length : end;
572                 var spec = cls.substring(idx+12, end);
573                 var o = SWS.Utils.parseFrameSpec(spec);
574                 for(var f in o)
575                     if (f > last_frame) last_frame = f;
576                 $(this).find("*").andSelf().each(function(_){
577                     if (!SWS.Utils.isEmpty(o))
578                         $(this).data("sws-frame-set", o);
579                     if (specials)
580                         specials.add($(this));
581                     else
582                         specials = $(this);
583                 });
584             };
585         });
586
587         slide.find("*").andSelf().not(specials).each(function(i) {
588             if ($(this).hasClass("sws-pause"))  cur_frame++;
589             var o = {};
590             for (var j = cur_frame; j <= last_frame; j++)
591                 o[ j ] = true;
592             if (!SWS.Utils.isEmpty(o))
593                 $(this).data("sws-frame-set", o);
594         });
595
596         canvas.data("sws-frame-info", { current: 0,
597                                         last: (last_frame - 0), // force cast to integer
598                                         callbacks: callbacks
599                                       });
600
601     };
602
603     /* Forces redrawing the page without reloading */
604     self.redraw = function (f) {
605         if (SWS.Utils.isUndefined(f))
606             $("body").hide().show(400, function () {
607                 $("body").css("display","block");
608                 if (!SWS.Utils.isUndefined(f))
609                     f();
610             });
611     };
612     self.changeAspect = function() {
613         $("html").removeClass("sws-aspect-4-3")
614             .removeClass("sws-aspect-16-9")
615             .removeClass("sws-aspect-16-10")
616             .addClass($("#sws-aspect-select").val());
617         self.redraw();
618     };
619
620     self.getCurrentTheme = function () { 
621         var l = $("link.sws-theme[rel='stylesheet']")[0];
622         console.log(l);
623         if (l) {
624             return  l.title;
625         } else
626             return ""
627     };
628
629     self.changeTheme = function (name) {
630         var theme_name;
631         if (typeof name === 'undefined')
632             theme_name = $("#sws-theme-select").val()
633         else
634             theme_name = name;
635 //        if (self.getCurrentTheme() == theme_name) {
636   //          return;
637     //    };
638         _current_theme = theme_name;
639         $("link.sws-theme").each (function (i) {
640             var e = this;
641             var title =  e.title;
642             if (title == theme_name) {
643                 e.rel = "stylesheet";
644                 e.disabled = false;
645                 e.media="all";
646             } else {
647                 e.rel = "alternate stylesheet";
648                 e.disabled = true;
649                 e.media="all";
650             };
651         });
652         self.redraw();
653
654     };
655
656     self.openPrint = function () {
657         window.open ("?mode=print&theme=" + self.getCurrentTheme());
658     }
659     var _fullscreen_icon_on = "&#xe746;";
660     var _fullscreen_icon_off = "&#xe744;";
661
662     self.toggleFullScreen = function () {
663         if (SWS.Fullscreen.status()) {
664             SWS.Fullscreen.exit();
665             $("a#sws-control-panel-fullscreen")
666                 .html(_fullscreen_icon_off);
667
668
669
670         } else {
671             SWS.Fullscreen.enter($("body")[0]);
672             $("a#sws-control-panel-fullscreen")
673                 .html(_fullscreen_icon_on);
674         };
675     };
676     function _update_ui() {
677         var nav = $('#sws-control-panel-navigation-bar');
678         nav.val(SWS.Presentation.getCurrentSlide() + 1);
679         $('#sws-control-panel-slide-input').val(nav.val());
680     }
681     self.navigate = function () {
682         self.goToSlide($("#sws-control-panel-navigation-bar").val()-1);
683         _update_ui();
684     };
685
686
687     self.init = function () {
688
689
690         $("html").addClass("sws-display");
691         $(window).resize(self.redraw);
692
693
694         $(window).bind('storage', function (e) {
695             console.log(e);
696         });
697
698         _total_slides = $(".sws-slide").length;
699
700         $(document).keydown(self.inputHandler);
701
702
703         var cur = self.getCurrentSlide();
704         $(".sws-slide").each (function (i) {
705             var par = $(this).parent();
706
707             $(this).remove();
708             var canvas = $('<div class="sws-canvas"/>');
709
710             if (!($(this).hasClass("sws-option-noheader"))) {
711                 canvas.append($('<div class="sws-header"/><br/>'));
712             };
713
714             var inner = $('<div class="sws-inner-canvas"/>');
715             var content = $('<div class="sws-content"/>');
716             $(this).find('script[type="text/javascript"]').remove();
717             content.append($(this));
718             inner.append(content);
719             inner.append($('<span class="sws-vertical-align"> </span><br/>'));
720             canvas.append(inner);
721
722             if (!($(this).hasClass("sws-option-nofooter"))) {
723                 canvas.append($('<div class="sws-footer"/>'));
724             };
725
726             par.append(canvas);
727
728             if (i == cur) {
729                 canvas
730                     .addClass("sws-active-slide")
731                     .removeClass("sws-inactive-slide");
732             } else {
733                 canvas
734                     .addClass("sws-inactive-slide")
735                     .removeClass("sws-active-slide");
736             };
737             init_canvas(canvas,_slide_callbacks[i]);
738
739         });
740
741
742
743         // Initialize the control panel
744         $("body").append($(SWS.Templates.controlPanel));
745         // Fill the theme switcher
746         $("link.sws-theme").each (function (i) {
747             var e = $(this);
748             var opt = "<option value='";
749             opt += e.attr("title");
750             opt += "' ";
751             if (e.attr("rel") == "stylesheet") {
752                 opt+= "selected='selected'";
753             };
754             opt += ">" + e.attr("title") + "</option>";
755             $("#sws-theme-select").append($(opt));
756         });
757         // Set the fullscreen icon
758         if (SWS.Fullscreen.status()) {
759             $("a#sws-control-panel-fullscreen")
760                 .html(_fullscreen_icon_on);
761         } else {
762             $("a#sws-control-panel-fullscreen")
763                 .html(_fullscreen_icon_off);
764         };
765         // Put the navigation range at the correct position
766         var nav = $('#sws-control-panel-navigation-bar');
767         nav.attr("min", SWS.Presentation.firstSlide() + 1);
768         nav.attr("max", SWS.Presentation.lastSlide() + 1);
769         $('#sws-control-panel-total-slides').text('/' + SWS.Presentation.getNumSlides());
770         _update_ui();
771
772         _slide_callbacks = null; /* avoid a leak */
773
774         var passed_theme = SWS.Utils.getParameterByName("theme");
775         if (passed_theme == "")
776             self.changeTheme();
777         else
778             self.changeTheme(passed_theme);
779
780         if (SWS.Utils.getParameterByName("mode") == "print") {
781            self.printMode();
782         }
783         else
784             self.refresh();
785         _initialized = true;
786
787     };
788
789 };