import moose website
[gitmo/moose-htdocs.git] / PPW-2008 / takahashi.js
1 var Presentation = {
2     init : function(option){
3         this.size = 9;
4
5         this._offset  = 0;
6         this.canvas   = document.getElementById('canvas');
7         this.content  = document.getElementById('content');
8         this.textbox  = document.getElementById('textField');
9         this.deck     = document.getElementById('deck');
10         this.scroller = document.getElementById('scroller');
11
12         this.toolbar         = document.getElementById('canvasToolbar');
13         this.toolbarHeight   = this.toolbar.boxObject.height;
14         this.isToolbarHidden = true;
15         this.toolbar.setAttribute('style', 'margin-top:'+(0-this.toolbarHeight)+'px;margin-bottom:0px;');
16
17         if(option){
18             for(var i in option){this[i] = option[i]}
19         }
20
21         if (this.readParameter()) {
22             this.takahashi();
23         }
24
25         document.documentElement.focus();
26     },
27
28     takahashi : function(){
29         if (!document.title)
30             document.title = this.data[0].replace(/[\r\n]/g, ' ');
31
32         if(!this.data[this.offset]){
33             this.offset = this.data.length-1;
34         }
35         document.getElementById("current_page").value = this.offset+1;
36         document.getElementById("max_page").value     = this.data.length;
37
38         this.scroller.setAttribute('maxpos', this.data.length-1);
39         this.scroller.setAttribute('curpos', this.offset);
40
41         var broadcaster = document.getElementById('canBack');
42         if (!this.offset)
43             broadcaster.setAttribute('disabled', true);
44         else
45             broadcaster.removeAttribute('disabled');
46
47         var broadcaster = document.getElementById('canForward');
48         if (this.offset == this.data.length-1)
49             broadcaster.setAttribute('disabled', true);
50         else
51             broadcaster.removeAttribute('disabled');
52
53         this.canvas.setAttribute('rendering', true);
54
55         var text = this.data[this.offset].
56                 replace(/^[\r\n]+/g,"").replace(/[\r\n]+$/g,"").replace(/(\r\n|[\r\n])/g,"\n")
57                 .split('\n');
58         var range = document.createRange();
59         range.selectNodeContents(this.content);
60         range.deleteContents();
61         range.detach();
62
63         var line;
64         var newLine;
65         var uri;
66         var image_width;
67         var image_total_width  = 0;
68         var image_height;
69         var image_total_height = 0;
70         var image_src;
71         var code_listing = 0;
72
73
74         var labelId = 0;
75
76         for (var i = 0; i < text.length; i++)
77         {
78             this.content.appendChild(document.createElement('hbox'));
79             this.content.lastChild.setAttribute('align', 'center');
80             this.content.lastChild.setAttribute('pack', 'center');
81
82             line = text[i];
83             image_width  = 0;
84             image_height = 0;
85
86             if (line.match(/^ /)) {
87               code_listing = 1; 
88               this.content.lastChild.setAttribute('align', 'left');
89               this.content.lastChild.setAttribute('class', 'pre');
90               line = line.substring(1)
91             }
92
93             while (line.match(/^([^\{]+)?(\{\{ima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^\}]*\}\}|\{\{(([^\|]+)?\||)([^\}]+)\}\})(.+)?/))
94             {
95                 if (RegExp.$1) {
96                     this.content.lastChild.appendChild(document.createElement('description'));
97                     this.content.lastChild.lastChild.setAttribute('value', RegExp.$1);
98                 }
99                 newLine = line.substring((RegExp.$1+RegExp.$2).length);
100
101                 // Images
102                 if (/^([^\{]+)?\{\{ima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^\}]*\}\}/.test(line)) {
103                     this.content.lastChild.appendChild(document.createElement('image'));
104                     image_src = RegExp.$2;
105                     if (image_src.indexOf('http://') < 0 &&
106                         image_src.indexOf('https://') < 0)
107                         image_src = this.dataFolder+image_src;
108                     this.content.lastChild.lastChild.setAttribute('src', image_src);
109                     this.content.lastChild.lastChild.setAttribute('width', parseInt(RegExp.$3 || '0'));
110                     this.content.lastChild.lastChild.setAttribute('height', parseInt(RegExp.$4 || '0'));
111                     image_width  += parseInt(RegExp.$3 || '0');
112                     image_height = Math.max(image_height, parseInt(RegExp.$4 || '0'));
113                 }
114
115                 // Styles
116                 // else if (/^([^\{]+)?\{\{#([^\|]+)\|([^\}]+)\}\}/.test(line)) {
117                 else if (/^([^\{]+)?\{\{(#([^\|]+)?\|)([^\}]+)\}\}/.test(line)) {
118                     uri = RegExp.$4;
119                     this.content.lastChild.appendChild(document.createElement('description'));
120                     this.content.lastChild.lastChild.setAttribute('value', uri);
121                     this.content.lastChild.lastChild.setAttribute('class', RegExp.$3);
122                 }
123
124                 // Links
125                 else if (/^([^\{]+)?\{\{(([^\|]+)?\||)([^\}]+)\}\}/.test(line)) {
126                     uri = RegExp.$4;
127                     if (uri.indexOf('://') < 0)
128                         uri = this.dataFolder+uri;
129                     this.content.lastChild.appendChild(document.createElement('description'));
130                     this.content.lastChild.lastChild.setAttribute('value', RegExp.$3 || RegExp.$4);
131                     this.content.lastChild.lastChild.setAttribute('href', uri);
132                     this.content.lastChild.lastChild.setAttribute('tooltiptext', uri);
133                     this.content.lastChild.lastChild.setAttribute('statustext', uri);
134                     this.content.lastChild.lastChild.setAttribute('class', 'link-text');
135                 }
136
137                 line = newLine;
138             }
139
140             if (line) {
141                 this.content.lastChild.appendChild(document.createElement('description'));
142                 this.content.lastChild.lastChild.setAttribute('value', line);
143             }
144
145             image_total_width = Math.max(image_total_width, image_width);
146             image_total_height += image_height;
147         }
148
149         this.content.setAttribute('style', 'font-size:10px;');
150
151         if (this.content.boxObject.width) {
152             var canvas_w  = this.canvas.boxObject.width;
153             var canvas_h  = this.canvas.boxObject.height-image_total_height;
154
155             var content_w = this.content.boxObject.width;
156             var new_fs = Math.round((canvas_w/content_w) * this.size);
157
158             new_fs = new_fs - (new_fs % 32);
159             if (code_listing) { new_fs = 48;}
160
161             this.content.setAttribute('style', 'top: 0');
162             this.content.setAttribute('style', 'font-size:'+ new_fs + "px");
163
164             if (this.content.boxObject.width < image_total_width) {
165                 content_w = image_total_width;
166                 new_fs = Math.round((canvas_w/content_w) * this.size);
167                 this.content.setAttribute('style', 'font-size:'+ new_fs + "px");
168             }
169
170             var content_h = this.content.boxObject.height;
171             if(content_h >= canvas_h){
172                 content_h = this.content.boxObject.height;
173                 new_fs = Math.round((canvas_h/content_h) * new_fs);
174                 this.content.setAttribute('style', 'font-size:'+ new_fs + "px");
175             }
176         }
177
178
179
180         this.canvas.removeAttribute('rendering');
181     },
182
183     reload : function() {
184         if (this.dataPath != location.href) {
185             var path = this.dataPath;
186             if (location.href.match(/^https?:/)) {
187                 var request = new XMLHttpRequest();
188                 request.open('GET', path);
189                 request.onload = function() {
190                     Presentation.textbox.value = request.responseText;
191                     Presentation.data = Presentation.textbox.value.split('----');
192
193                     Presentation.takahashi();
194
195                     path = null;
196                     request = null;
197                 };
198                 request.send(null);
199             }
200             else {
201                 document.getElementById('dataLoader').setAttribute('src', 'about:blank');
202                 window.setTimeout(function() {
203                     document.getElementById('dataLoader').setAttribute('src', path);
204                     path = null;
205                 }, 10);
206             }
207         }
208         else
209             window.location.reload();
210     },
211
212     forward : function(){
213         this.offset++;
214         this.takahashi();
215     },
216     back : function(){
217         this.offset--;
218         if(this.offset < 0){this.offset = 0}
219         this.takahashi();
220     },
221     home : function(){
222         this.offset = 0;
223         this.takahashi();
224     },
225     end : function(){
226         this.offset = this.data.length-1;
227         this.takahashi();
228     },
229     showPage : function(aPageOffset){
230         this.offset = aPageOffset ? aPageOffset : 0 ;
231         this.takahashi();
232     },
233
234     addPage : function() {
235         if (this.textbox.value &&
236             !this.textbox.value.match(/(\r\n|[\r\n])$/))
237             this.textbox.value += '\n';
238         this.textbox.value += '----\n';
239         this.onEdit();
240     },
241
242     toggleEditMode : function(){
243         this.deck.selectedIndex = (this.deck.selectedIndex == 0) ? 1 : 0 ;
244     },
245     toggleEvaMode : function(){
246         var check = document.getElementById('toggleEva');
247         if (this.canvas.getAttribute('eva') == 'true') {
248             this.canvas.removeAttribute('eva');
249             check.checked = false;
250         }
251         else {
252             this.canvas.setAttribute('eva', true);
253             check.checked = true;
254         }
255     },
256
257     onPresentationClick : function(aEvent){
258         if (!this.isToolbarHidden)
259             this.showHideToolbar();
260
261         switch(aEvent.button)
262         {
263             case 0:
264                 var uri = aEvent.target.getAttribute('href');
265                 if (uri)
266                     window.open(uri);
267                 else {
268                     this.forward();
269                     document.documentElement.focus();
270                 }
271                 break;
272             case 2:
273                 this.back();
274                 document.documentElement.focus();
275                 break;
276             default:
277                 break;
278         }
279     },
280     onScrollerDragStart : function(){
281         this.scroller.dragging = true;
282     },
283     onScrollerDragMove : function(){
284         if (this.scroller.dragging)
285             this.showPage(parseInt(this.scroller.getAttribute('curpos')));
286     },
287     onScrollerDragDrop : function(){
288         if (this.scroller.dragging) {
289             this.showPage(parseInt(this.scroller.getAttribute('curpos')));
290         }
291          this.scroller.dragging = false;
292     },
293     onEdit : function() {
294         this.data = this.textbox.value.split('----');
295         this.takahashi();
296     },
297
298     onKeyPress : function(aEvent) {
299         switch(aEvent.keyCode)
300         {
301             case aEvent.DOM_VK_BACK_SPACE:
302                 if (this.isPresentationMode) {
303                     aEvent.preventBubble();
304                     aEvent.preventDefault();
305                     Presentation.back();
306                 }
307                 break;
308             default:
309                 break;
310         }
311     },
312
313
314     onToolbarArea   : false,
315     toolbarHeight   : 0,
316     toolbarDelay    : 300,
317     toolbarTimer    : null,
318     isToolbarHidden : false,
319     onMouseMoveOnCanvas : function(aEvent) {
320         if (this.scroller.dragging) return;
321
322         this.onToolbarArea = (aEvent.clientY < this.toolbarHeight);
323
324         if (this.isToolbarHidden == this.onToolbarArea) {
325             if (this.toolbarTimer) window.clearTimeout(this.toolbarTimer);
326             this.toolbarTimer = window.setTimeout('Presentation.onMouseMoveOnCanvasCallback()', this.toolbarDelay);
327         }
328     },
329     onMouseMoveOnCanvasCallback : function() {
330         if (this.isToolbarHidden == this.onToolbarArea)
331             this.showHideToolbar();
332     },
333
334     toolbarAnimationDelay : 100,
335     toolbarAnimationSteps : 5,
336     toolbarAnimationInfo  : null,
337     toolbarAnimationTimer : null,
338     showHideToolbar : function()
339     {
340         if (this.toolbarAnimationTimer) window.clearTimeout(this.toolbarAnimationTimer);
341
342         this.toolbarAnimationInfo = { count : 0 };
343         if (this.isToolbarHidden) {
344             this.toolbarAnimationInfo.start = 0;
345             this.toolbarAnimationInfo.end   = this.toolbarHeight;
346         }
347         else {
348             this.toolbarAnimationInfo.start = this.toolbarHeight;
349             this.toolbarAnimationInfo.end   = 0;
350         }
351         this.toolbarAnimationInfo.current = 0;
352
353         this.toolbar.setAttribute('style', 'margin-top:'+(0-(this.toolbarHeight-this.toolbarAnimationInfo.start))+'px; margin-bottom:'+(0-this.toolbarAnimationInfo.start)+'px;');
354
355         this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps);
356     },
357     animateToolbar : function()
358     {
359         this.toolbarAnimationInfo.current += parseInt(this.toolbarHeight/this.toolbarAnimationSteps);
360
361         var top, bottom;
362         if (this.toolbarAnimationInfo.start < this.toolbarAnimationInfo.end) {
363             top    = this.toolbarHeight-this.toolbarAnimationInfo.current;
364             bottom = this.toolbarAnimationInfo.current;
365         }
366         else {
367             top    = this.toolbarAnimationInfo.current;
368             bottom = this.toolbarHeight-this.toolbarAnimationInfo.current;
369         }
370
371         top    = Math.min(Math.max(top, 0), this.toolbarHeight);
372         bottom = Math.min(Math.max(bottom, 0), this.toolbarHeight);
373
374         this.toolbar.setAttribute('style', 'margin-top:'+(0-top)+'px; margin-bottom:'+(0-bottom)+'px');
375
376         if (this.toolbarAnimationInfo.count < this.toolbarAnimationSteps) {
377             this.toolbarAnimationInfo.count++;
378             this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps);
379         }
380         else
381             this.isToolbarHidden = !this.isToolbarHidden;
382     },
383
384
385
386     get offset(){
387         return this._offset;
388     },
389     set offset(aValue){
390         this._offset = parseInt(aValue || 0);
391         document.documentElement.setAttribute('lastoffset', this.offset);
392         return this.offset;
393     },
394
395     get data(){
396         if (!this._data) {
397              // Make sure you break the text into parts smaller than 4096
398              // characters, and name them as indicated. Tweak as required.
399              // (What a hack. A JS programmer should find a better way.)
400              // Luc St-Louis, and email is lucs@pobox.com.
401
402                  nodes = document.getElementById('builtinCode').childNodes;
403                  content = '';
404                 for (i in nodes) {
405                     if (nodes[i].nodeValue) {
406                     content = content + nodes[i].nodeValue;
407                     }
408                 }
409     
410                this._data = content.split("----");
411         }
412
413         return this._data;
414     },
415     set data(aValue){
416         this._data = aValue;
417         return aValue;
418     },
419
420
421     get isPresentationMode(){
422         return (this.deck.selectedIndex == 0);
423     },
424
425
426     get dataPath(){
427         if (!this._dataPath)
428             this.dataPath = location.href;
429         return this._dataPath;
430     },
431     set dataPath(aValue){
432         var oldDataPath = this._dataPath;
433         this._dataPath = aValue;
434         if (oldDataPath != aValue) {
435             this._dataFolder = this._dataPath.split('?')[0].replace(/[^\/]+$/, '');
436         }
437         return this._dataPath;
438     },
439
440     get dataFolder(){
441         if (!this._dataFolder)
442             this.dataPath = this.dataPath;
443         return this._dataFolder;
444     },
445     set dataFolder(aValue){
446         this._dataFolder = aValue;
447         return this._dataFolder;
448     },
449
450     readParameter : function() {
451         if (location.search) {
452             var param = location.search.replace(/^\?/, '');
453
454             if (param.match(/page=([0-9]+)/i))
455                 this.offset = parseInt(RegExp.$1)-1;
456
457             if (param.match(/edit=(1|true|yes)/i))
458                 this.toggleEditMode();
459
460             if (param.match(/eva=(1|true|yes)/i))
461                 this.toggleEvaMode();
462
463             if (param.match(/data=([^&;]+)/i)) {
464                 var path = unescape(RegExp.$1);
465                 this.dataPath = path;
466                 if (location.href.match(/^https?:/)) {
467                     var request = new XMLHttpRequest();
468                     request.open('GET', path);
469                     request.onload = function() {
470                         Presentation.textbox.value = request.responseText;
471                         Presentation.data = Presentation.textbox.value.split('----');
472
473                         Presentation.takahashi();
474                     };
475                     request.send(null);
476                 }
477                 else {
478                     document.getElementById('dataLoader').setAttribute('src', path);
479                 }
480                 return false;
481             }
482         }
483         return true;
484     },
485     onDataLoad : function() {
486         if (!window.frames[0].document.body.hasChildNodes()) return;
487         var data = window.frames[0].document.body.firstChild.innerHTML;
488         if (!data) return;
489
490         this.textbox.value = data;
491         this.data = this.textbox.value.split('----');
492
493         this.takahashi();
494     }
495 };
496
497 function init()
498 {
499     window.removeEventListener('load', init, false);
500
501     Presentation.init();
502 }
503 window.addEventListener('load', init, false);