Working template system.
[hacks/simpleWebSlides.git] / simpleWebSlides.js
1 /*
2   Namespace object.
3 */
4
5 var SWS = {};
6
7 /* Utility functions */
8 SWS.isUndefined = function (o) { return typeof o == "undefined"; };
9
10 /*
11   Representation of intervals of positive integers.
12
13 SWS.Interval = new function (init) {
14
15     var self = this;
16     self.data = new Array();
17     self.parseString(s) {
18         var elems = s.split("_");
19         for(var i = 0; i < elems.length; i++){
20             var bounds = elems[i].split("-");
21             if (bounds.length > 2) continue;
22             if (SWS.isUndefined(bounds[1])) bounds[1] = bounds[0];
23             if (!(isFinite(bounds[0]) && isFinite(bounds[1]))) continue;
24
25             self.add(+(bounds[0]), +(bounds[1]));
26         };
27
28     };
29     self.add(x, y) {
30         if (SWS.isUndefined(y) && isFinite(x)) self.add(x,x);
31
32
33
34
35     };
36 5B
37
38
39     };
40 };
41 */
42
43 SWS.Presentation = new function () {
44
45
46     var self = this;
47
48     var templates = {};
49
50     //TODO: clean-up;
51     var _total_slides;
52     var _defered_custom = new Array();
53     var _initialized = false;
54     var _animations_running = false;
55
56     //Utility functions
57
58
59
60     function push_following(t, i, v) {
61         if ((typeof t[i]) == 'undefined') {
62             t[i] = new Array();
63         };
64         var l = t[i].length;
65         if (l == 0 || !($.contains(t[i][l-1].get()[0], v.get()[0]))) {
66             t[i][l] = v;
67         };
68     };
69
70     function push(t, i, v) {
71         if ((typeof t[i]) == 'undefined') {
72             t[i] = new Array();
73         };
74         var l = t[i].length;
75             t[i][l] = v;
76     };
77
78
79     function init_canvas(canvas) {
80         var cur_frame = 0;
81         var last_frame = canvas.find(".sws-pause").length;
82         //Add all regular elements to the frame list
83         canvas.find("*").each(function(i) {
84             if ($(this).filter('*[class*="sws-onslide-"]').length) {
85             } else {
86                 if ($(this).hasClass("sws-pause"))  cur_frame++;
87                 var o = {};
88                 for (var j = cur_frame; j <= last_frame; j++)
89                     o[ "f" + j ] = true;
90                 $(this).data("sws-frame-set", o);
91             };
92         });
93
94         canvas.data("sws-frame-info", { current: 0,
95                                     last: last_frame,
96                                     custom: new Array() });
97
98     };
99
100
101     //Public methods
102     self.setTemplate = function (tn, fn) { templates[tn] = fn; };
103
104     self.getNumSlides = function () { return _total_slides; };
105
106
107     self.registerCustom = function (i, f) {
108         if (_initialized) return;
109         //jQuery does not seem to work well
110         //on partal doms
111
112         var scripts = document.getElementsByTagName("script");
113         var current = scripts[scripts.length-1];
114
115         var slide = $(current).parents(".sws-slide");
116         if (slide.length == 0) {
117             console.log("no parent ?");
118             return;
119         }
120         _defered_custom[_defered_custom.length] = { src: slide[0],
121                                                     fn: f,
122                                                     frame: i };
123         $(current).remove();
124
125     };
126
127     if (typeof(Storage)!=="undefined"){
128         self.getCurrentSlide = function () {
129             //unary + casts to integer
130             var i = +(sessionStorage.current_slide);
131             if (!(i >= 0 && i < self.getNumSlides())){
132                 return 0;
133             } else {
134                 return i;
135             };
136         };
137
138         self.setCurrentSlide = function (i) {
139             sessionStorage.current_slide = i;
140         };
141
142     } else {
143         var _current_slide = 0;
144         self.getCurrentSlide = function () { return current_slide; };
145         self.setCurrentSlide = function (i) { _current_slide = i; };
146
147     };
148     self.firstSlide = function () { return 0; };
149     self.lastSlide = function () { return self.getNumSlides() - 1; };
150
151     self.refresh = function () {
152         var to_slide = $(".sws-canvas")[self.getCurrentSlide()];
153         var from_slide = $(".sws-active-slide")[0];
154
155         if (!(to_slide === from_slide)) {
156             templates['sws-template-slide-deactivate'](
157                 $(from_slide),
158                 function (o){
159                     o.removeClass("sws-active-slide")
160                         .addClass("sws-inactive-slide");
161                     templates['sws-template-slide-activate'](
162                         $(to_slide).removeClass("sws-inactive-slide")
163                             .addClass("sws-active-slide"),
164                         function (_){
165                         });
166                 });
167
168         };
169         var info = $(to_slide).data("sws-frame-info");
170         var cur = info.current;
171         var custom = info.custom;
172
173         $(to_slide).find("*").each (function (i) {
174             var fcur = "f" + cur;
175             var frameset = $(this).data("sws-frame-set") || {};
176             if (frameset[fcur]) {
177                 if (!($(this).hasClass("sws-active-frame"))) {
178                     templates['sws-template-frame-activate'](
179                         $(this).removeClass("sws-inactive-frame")
180                             .addClass("sws-active-frame"),
181                         function (_){ });
182
183                 };
184
185             } else {
186                 if (!($(this).hasClass("sws-inactive-frame"))) {
187                     templates['sws-template-frame-deactivate'](
188                         $(this),
189                         function (o){
190                             o.removeClass("sws-active-frame")
191                                 .addClass("sws-inactive-frame");
192                         });
193
194                 };
195
196
197             };
198         });
199         _animation_running = true;
200         var callbacks;
201
202         if (callbacks = custom[self.getCurrentFrame()]){
203             for (var k = 0; k < callbacks.length; k++)
204                 callbacks[k]($(to_slide));
205         };
206
207         $(to_slide).find("*").promise().done(function() {
208             _animation_running = false;
209         });
210     };
211
212     self.nextSlide = function () {
213         self.setCurrentSlide(Math.min(self.getCurrentSlide()+1,
214                                        self.lastSlide()));
215     };
216
217     self.previousSlide = function () {
218         self.setCurrentSlide(Math.max(self.getCurrentSlide()-1,
219                                       self.firstSlide()));
220     };
221
222     self.getFrameInfo = function () {
223
224         var i = self.getCurrentSlide();
225         var canvas = $($(".sws-canvas")[i]);
226         var infos = canvas.data("sws-frame-info");
227         return infos;
228     };
229     self.getCurrentFrame = function () { return self.getFrameInfo().current; };
230     self.setCurrentFrame = function (i) { self.getFrameInfo().current = i; };
231     self.firstFrame = function () { return 0; };
232     self.lastFrame = function () { return self.getFrameInfo().last; };
233
234     self.nextFrame = function () {
235         self.setCurrentFrame(Math.min(self.getCurrentFrame()+1,
236                                       self.lastFrame()));
237
238     };
239     self.previousFrame = function () {
240         self.setCurrentFrame(Math.max(self.getCurrentFrame()-1,
241                                        self.firstFrame()));
242     };
243
244     self.next = function () {
245         var i = self.getCurrentFrame();
246         if (i == self.lastFrame())
247             self.nextSlide();
248         else
249             self.nextFrame();
250     };
251
252     self.previous = function () {
253         var i = self.getCurrentFrame();
254         if (i == self.firstFrame())
255             self.previousSlide();
256         else
257             self.previousFrame();
258     };
259
260     self.inputHandler = function (event) {
261         if (_animation_running) return;
262         switch (event.which) {
263         case 36:/* Home */
264             self.firstSlide();
265             break;
266
267         case 35:/* End */
268             self.lastSlide();
269             break;
270
271         case 32: /* space */
272         case 39: /* -> */
273         case 1: /* mouse button 1 */
274             self.next();
275             break;
276         case 34: /* PgDown */
277         case 78: /* n */
278             self.nextSlide();
279             break;
280         case 8: /* backspace */
281         case 37: /* <-   */
282             self.previous();
283             break;
284         case 33: /* PgUp */
285         case 80: /* p */
286             self.previousSlide();
287             break;
288         default:
289             return;
290         };
291         self.refresh();
292     };
293
294
295     function default_footer_template() {
296         var elem = '<div class="sws-footer"><span class="sws-current-slide-num">' + (i+1);
297         elem += '</span><span class="sws-slide-num-sep"/><span class="sws-total-slide-num">';
298         elem += self.getNumSlides() + '</span></div>';
299         return $(elem);
300     };
301
302     self.setTemplate('sws-template-footer', function (x) { });
303     self.setTemplate('sws-template-frame-activate', function (x, f) {f(x);});
304     self.setTemplate('sws-template-frame-deactivate', function (x, f) {f(x);});
305     self.setTemplate('sws-template-slide-activate',  function (x, f) {f(x);});
306     self.setTemplate('sws-template-slide-deactivate', function (x, f) {f(x);});
307
308
309
310     function init () {
311
312         _total_slides = $(".sws-slide").length;
313
314         $(document).keydown(self.inputHandler);
315         $(document).mousedown(self.inputHandler);
316
317         var cur = self.getCurrentSlide();
318         $(".sws-slide").each (function (i) {
319             if (!($(this).hasClass("sws-option-nofooter"))) {
320                 $(this).append(templates['sws-template-footer']());
321             };
322             var par = $(this).parent();
323             $(this).remove();
324             var canvas = $('<div class="sws-canvas"/>');
325             canvas.append($(this));
326             par.append(canvas);
327             if (i == cur) {
328                 canvas
329                     .addClass("sws-active-slide")
330                     .removeClass("sws-inacitve-slide");
331             } else {
332                 canvas
333                     .addClass("sws-inactive-slide")
334                     .removeClass("sws-active-slide");
335             };
336             init_canvas(canvas);
337
338         });
339         for (var i = 0; i < _defered_custom.length; i++){
340
341             var custom = _defered_custom[i];
342             var canvas = $(custom.src).parents(".sws-canvas");
343             if (canvas.length == 0) continue;
344             canvas = $(canvas[0]);
345
346             var info = canvas.data("sws-frame-info");
347
348             push(info.custom, custom.frame, custom.fn);
349         };
350         self.refresh();
351         _initialized = true;
352
353     };
354
355     self.init = function () {
356         $(document).ready(init);
357     };
358
359 };