/[takahashi]/takahashi.xul
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /takahashi.xul

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (show annotations)
Sat Jun 10 15:31:05 2006 UTC (17 years, 9 months ago) by dpavlin
File size: 62945 byte(s)
fix inserting elements at end of textarea
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!--
3 高橋メソッドなプレゼンツール in XUL リターンズ
4 made by Piro
5 http://piro.sakura.ne.jp/
6
7 based on
8 高橋メソッドなプレゼン作成ツール ver.2 made by mala
9 http://la.ma.la/blog/diary_200504080545.htm
10 もんたメソッドなプレゼン作成ツール made by mala
11 http://la.ma.la/blog/diary_200505310749.htm
12 -->
13
14 <!-- ***** BEGIN LICENSE BLOCK *****
15 - Version: MPL 1.1
16 -
17 - The contents of this file are subject to the Mozilla Public License Version
18 - 1.1 (the "License"); you may not use this file except in compliance with
19 - the License. You may obtain a copy of the License at
20 - http://www.mozilla.org/MPL/
21 -
22 - Software distributed under the License is distributed on an "AS IS" basis,
23 - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
24 - for the specific language governing rights and limitations under the
25 - License.
26 -
27 - The Original Code is the Takahashi-Method-based Presentation Tool
28 - in XUL/Returns.
29 -
30 - The Initial Developer of the Original Code is SHIMODA Hiroshi.
31 - Portions created by the Initial Developer are Copyright (C) 2005-2006
32 - the Initial Developer. All Rights Reserved.
33 -
34 - Contributor(s): SHIMODA Hiroshi <piro@p.club.ne.jp>
35 - dynamis <dynamis@mozilla-japan.org>
36 - matobaa <matobaa@lily.freemail.ne.jp>
37 -
38 - ***** END LICENSE BLOCK ***** -->
39
40
41 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
42 <?xml-stylesheet href="takahashi.css" type="text/css"?>
43
44 <page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
45 id="presentation"
46 xmlns:html="http:/www.w3.org/1999/xhtml"
47 orient="vertical"
48 onkeypress="Presentation.onKeyPress(event);">
49
50
51 <html:textarea id="builtinCode" style="visibility: collapse">
52 TITLE::高橋メソッドなプレゼンツール in XUL リターンズ
53 高橋メソッド
54 in XUL
55 [[EM:RETURNS]]
56 ----
57 HEADER::高橋メソッドなプレゼンツール in XUL リターンズ
58 CHAPTER::操作説明
59 操作
60 ----
61 HEADER::操作
62 基本的に
63 高橋メソッド
64 in XUL
65 と同じ
66 ----
67 ALIGN::left
68 Enterか
69 Page Downか
70 左クリック
71 で[次のページ]
72 ----
73 ALIGN::right
74 →でも
75 ↓でも
76 次のページ
77 ----
78 ALIGN::center
79 キーボード操作時は
80 次のページへ進む操作で
81 ラベルをめくれます
82 (めくっていない
83 ラベルがなければ
84 そのまま次のページへ)
85 ----
86 一度めくったラベルは
87 状態を保持するので
88 ----
89 ALIGN::right
90 前のページに戻して
91 「奥さん、いいですか!
92 ここですよここ!」
93 ができる
94 ----
95 Back Spaceか
96 Page Upか
97 右クリック
98 で[前のページ]
99 ----
100 ←でも
101 ↑でも
102 前のページ
103 ----
104 ALIGN::right
105 Homeで
106 最初の
107 ページ
108 ----
109 ALIGN::left
110 Endで
111 最後の
112 ページ
113 ----
114 Ctrl-R
115 で[リロード]
116 ----
117 Ctrl-Eで
118 [編集]モード
119 突入
120 ----
121 HEADER::
122 CHAPTER::編集機能
123 編集
124 ----
125 HEADER::編集
126 編集モード時は
127 Ctrl-Nで新しい
128 ページの追加
129 ----
130 HEADER::機能
131 部分
132 強調
133 ----
134 テキストを部分的に
135 [[EM:強調]]できる
136 [[PRE:
137 [[EM:強調テキスト]&#173;]
138 [[EM:強調テキスト:EM]&#173;]
139 ]]
140 ----
141 整形済み
142 テキスト
143 [[PRE:
144 [[PRE:整形済み]&#173;]
145 [[PRE:整形済み:PRE]&#173;]
146 ]]
147 ----
148 行内に[[PRE:preformatted text]]を
149 書ける(けどあんまり意味ない)
150 ----
151 複数行にまたがる整形済みテキスト
152 [[PRE:&lt;html&gt;
153 &lt;head&gt;
154 &lt;title&gt;サンプル&lt;/title&gt;
155 &lt;/head&gt;
156 &lt;body&gt;
157 &lt;p&gt;サンプル&lt;/p&gt;
158 &lt;/body&gt;
159 &lt;/html&gt;:PRE]]
160 ソースコードの例示などに使える
161 ----
162 リンク
163 [[PRE:
164 [[URI]&#173;]
165 [[ラベル|URI]&#173;]
166 ]]
167 ----
168 [[リンクも埋め込める|http://piro.sakura.ne.jp/]]
169 ラベル無しリンクも可能↓
170 [[http://piro.sakura.ne.jp/]]
171 ----
172 [[image src="takahashi.png" width="300" height="168"]]
173 ----
174 画像
175 ----
176 [[PRE:
177 [[IMAGE src="*" width="*" height="*"]&#173;]
178 [[IMG src="*" width="*" height="*"]&#173;]
179 ]]
180 ----
181 インライン[[image src="takahashi.png" width="300" height="168"]]で
182 [[image src="takahashi.png" width="300" height="168"]]
183 いくつでも
184 埋め込める
185 ----
186 リンクや
187 画像のパスの
188 相対指定は
189 ----
190 データファイルの
191 あるディレクトリ
192 もしくは
193 本体のある
194 ディレクトリを
195 基準として解釈
196 ----
197 カスタム
198 スタイル
199 ----
200 自分だけのカスタム
201 指定も可能
202 [[PRE:
203 [[#クラス名:文字列]&#173;]
204 ]]
205 このように↓解釈
206 [[PRE:
207 &lt;description
208 class="クラス名"
209 value="文字列"/&gt;
210 ]]
211 ----
212 複数行にまたがる
213 指定も可能
214 [[PRE:
215 [[#クラス名:
216 1行目
217 2行目
218 ]&#173;]
219 ]]
220 このように↓解釈
221 [[PRE:
222 &lt;vbox class="クラス名 block"&gt;
223 &lt;description value="1行目"/&gt;
224 &lt;description value="2行目"/&gt;
225 &lt;/vbox&gt;
226 ]]
227 ----
228 takahashi.css
229 に自分で好きな
230 スタイル指定を
231 追加しよう!
232 ----
233 [[装飾記号|http://homepage2.nifty.com/k_maeda/code/uni/uni44.html]]などの
234 [[Unicodeの記号文字|http://homepage2.nifty.com/k_maeda/code/unicode.html]]
235 と組み合わせると
236 色々できるかも?
237 ----
238 HEADER::ヘッダ
239 FOOTER::フッタ
240 ヘッダとフッタも
241 自由に指定できる
242 [[PRE:
243 &#173;HEADER::ヘッダ
244 &#173;FOOTER::フッタ
245 ]]
246 ----
247 HEADER::
248 FOOTER::
249 テキストの水平配置
250 (ページ単位)
251 [[PRE:
252 &#173;ALIGN::left
253 &#173;ALIGN::right
254 &#173;ALIGN::center
255 ]]
256 ----
257 テキストの水平配置
258 (以後のページすべて)
259 [[PRE:
260 &#173;GLOBAL-ALIGN::left
261 &#173;GLOBAL-ALIGN::right
262 &#173;GLOBAL-ALIGN::center
263 ]]
264 ----
265 HEADER::機能
266 FOOTER::
267 CHAPTER::起動パラメータ
268 起動
269 パラ
270 メータ
271 ----
272 ?page=[数値]
273 ----
274 表示ページを
275 指定して起動
276 ----
277 ?data=[パス]
278 ----
279 外部データ
280 ファイルを
281 読み込み
282 ----
283 ?edit=true
284 ----
285 編集モード
286 の状態で起動
287 ----
288 HEADER::
289 CHAPTER::このアプリケーションについて
290 ファイ
291 ル構成
292 ----
293 HEADER::ファイル構成
294 [[takahashi.xul]]
295 [[takahashi.css]]
296 [[monta-label.png]]
297 ----
298 HEADER::
299 ライセンスは
300 [MPL1.1]
301 ってことで
302 ----
303 ご自由に
304 お使い
305 下さい
306 ----
307 説明
308 おわり
309 ----
310 Let's Enjoy
311 Takahashi
312 Method
313 Life !!
314 </html:textarea>
315
316
317 <deck flex="1" id="deck">
318
319 <vbox flex="1"
320 onmouseup="Presentation.handleEvent(event);"
321 onmousedown="Presentation.handleEvent(event);"
322 onmousemove="Presentation.handleEvent(event);">
323 <toolbox id="canvasToolbar">
324 <toolbar>
325 <toolbarbutton oncommand="Presentation.home()" label="|&lt;&lt;"
326 observes="canBack"/>
327 <toolbarbutton oncommand="Presentation.back()" label="&lt;"
328 observes="canBack"/>
329 <toolbarbutton oncommand="Presentation.forward()" label="&gt;"
330 observes="canForward"/>
331 <toolbarbutton oncommand="Presentation.end()" label="&gt;&gt;|"
332 observes="canForward"/>
333 <toolbarseparator/>
334 <hbox align="center">
335 <textbox id="current_page" size="4"
336 oninput="if (this.value) Presentation.showPage(parseInt(this.value)-1);"/>
337 <toolbarbutton id="pages-list-button"
338 type="menu"
339 label="Select Page"
340 tooltiptext="Select Page"
341 class="dropmarker-button">
342 <menupopup id="pages-list"
343 onpopupshowing="if (event.target == this) Presentation.preventToShowHideToolbar = true;"
344 onpopuphiding="if (event.target == this) Presentation.preventToShowHideToolbar = false;"
345 oncommand="Presentation.showPage(parseInt(event.target.value));"/>
346 </toolbarbutton>
347 <description value="/"/>
348 <description id="max_page"/>
349 </hbox>
350 <toolbarseparator/>
351 <vbox flex="2">
352 <spacer flex="1"/>
353 <scrollbar id="scroller"
354 align="center" orient="horizontal"
355 oncommand="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));"
356 onclick="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));"
357 onmousedown="Presentation.onScrollerDragStart();"
358 onmousemove="Presentation.onScrollerDragMove();"
359 onmouseup="Presentation.onScrollerDragDrop();"/>
360 <spacer flex="1"/>
361 </vbox>
362 <toolbarseparator/>
363 <hbox>
364 <toolbarbutton label="timer"
365 oncommand="Presentation.setTimer();" />
366 </hbox>
367 <spacer flex="1"/>
368 <hbox>
369 <toolbarbutton label="auto"
370 id="autoButton"
371 type="checkbox"
372 autoCheck="false"
373 oncommand="Presentation.toggleAutoCruiseMode();" />
374 <toolbarbutton id="auto-interval-button"
375 type="menu"
376 label="Interval"
377 tooltiptext="Change Interval"
378 class="dropmarker-button">
379 <menupopup id="auto-interval-list"
380 onpopupshowing="
381 Presentation.preventToShowHideToolbar = true;
382 (this.getElementsByAttribute('value', Presentation.autoCruiseInterval)[0] || this.lastChild).setAttribute('checked', true);
383 "
384 onpopuphiding="Presentation.preventToShowHideToolbar = false;"
385 oncommand="Presentation.changeAutoCruiseInterval(parseInt(event.target.value));">
386 <menuitem type="radio" radiogroup="autocruise-interval"
387 label="1 sec" value="1000"/>
388 <menuitem type="radio" radiogroup="autocruise-interval"
389 label="2 sec" value="2000"/>
390 <menuitem type="radio" radiogroup="autocruise-interval"
391 label="3 sec" value="3000"/>
392 <menuitem type="radio" radiogroup="autocruise-interval"
393 label="4 sec" value="4000"/>
394 <menuitem type="radio" radiogroup="autocruise-interval"
395 label="5 sec" value="5000"/>
396 <menuseparator/>
397 <menuitem type="radio" radiogroup="autocruise-interval"
398 label="1 min" value="60000"/>
399 <menuitem type="radio" radiogroup="autocruise-interval"
400 label="2 min" value="120000"/>
401 <menuitem type="radio" radiogroup="autocruise-interval"
402 label="3 min" value="180000"/>
403 <menuitem type="radio" radiogroup="autocruise-interval"
404 label="4 min" value="240000"/>
405 <menuitem type="radio" radiogroup="autocruise-interval"
406 label="5 min" value="300000"/>
407 <menuseparator/>
408 <menuitem type="radio" radiogroup="autocruise-interval"
409 label="Custom"
410 oncommand="
411 var current = Presentation.autoCruiseInterval;
412 var val = parseInt(prompt('input interval (sec)', parseInt(current/1000)));
413 if (isNaN(val)) {
414 event.preventBubble();
415 return;
416 }
417 else
418 val = val * 1000;
419 this.value = val;
420 "/>
421 </menupopup>
422 </toolbarbutton>
423 </hbox>
424 <toolbarbutton label="Pen"
425 id="penButton"
426 type="checkbox"
427 autoCheck="false"
428 oncommand="StrokablePresentationService.toggleCheck();"/>
429 <toolbarseparator/>
430 <toolbarbutton id="toggleEva" label="Eva"
431 type="checkbox"
432 autoCheck="false"
433 oncommand="Presentation.toggleEvaMode();"/>
434 <toolbarseparator/>
435 <toolbarbutton label="Edit"
436 oncommand="Presentation.toggleEditMode();"/>
437 <toolbarbutton oncommand="Presentation.reload();" label="Reload"/>
438 </toolbar>
439 </toolbox>
440 <vbox flex="1" id="canvas">
441 <stack flex="1">
442 <vbox flex="1">
443 <hbox id="headerBox" flex="1">
444 <label id="header"/>
445 <spacer flex="1"/>
446 </hbox>
447 <spacer flex="19"/>
448 <hbox id="footerBox" flex="1">
449 <spacer flex="1"/>
450 <label id="footer"/>
451 </hbox>
452 </vbox>
453 <vbox flex="1"
454 onclick="Presentation.onPresentationClick(event);">
455 <spacer flex="1"/>
456 <hbox flex="1" id="contentBox">
457 <spacer flex="1"/>
458 <vbox id="content"/>
459 <spacer flex="1"/>
460 </hbox>
461 <spacer flex="1"/>
462 </vbox>
463 </stack>
464 </vbox>
465 <hbox id="indicatorBar"
466 onclick="Presentation.onIndicatorBarClick(event);">
467 <stack flex="1">
468 <vbox>
469 <progressmeter id="remainingPageIndicator"
470 type="determined" value="0"
471 flex="1"/>
472 <progressmeter id="remainingTimeIndicator"
473 type="determined" value="0"
474 flex="1"
475 collapsed="true"/>
476 </vbox>
477 <hbox flex="1">
478 <label value="Next:"/>
479 <description id="nextPage" flex="1" crop="end"/>
480 </hbox>
481 </stack>
482 </hbox>
483 </vbox>
484
485
486 <vbox flex="1" id="edit">
487 <toolbox>
488 <toolbar>
489 <menubar flex="1">
490 <menu label="File">
491 <menupopup>
492 <menuitem label="Save"
493 key="key_save"
494 oncommand="Presentation.output()"/>
495 <menuitem label="Reload"
496 key="key_reload"
497 oncommand="Presentation.reload()"/>
498 </menupopup>
499 </menu>
500 <menu label="Insert">
501 <menupopup>
502 <menuitem label="New Page"
503 key="key_insert_newpage"
504 oncommand="Presentation.insert('page')"/>
505 <menuseparator/>
506 <menuitem label="Header"
507 oncommand="Presentation.insert('header')"/>
508 <menuitem label="Footer"
509 oncommand="Presentation.insert('footer')"/>
510 <menuseparator/>
511 <menuitem label="Link"
512 oncommand="Presentation.insert('link')"/>
513 <menuitem label="Emphasis"
514 oncommand="Presentation.insert('em')"/>
515 <menuitem label="Preformatted"
516 oncommand="Presentation.insert('pre')"/>
517 <menuitem label="Monta"
518 oncommand="Presentation.insert('monta')"/>
519 <menuitem label="Image"
520 oncommand="Presentation.insert('img')"/>
521 </menupopup>
522 </menu>
523 </menubar>
524 <toolbarseparator/>
525 <toolbarbutton label="View"
526 oncommand="Presentation.toggleEditMode();"/>
527 <toolbarbutton oncommand="Presentation.reload();" label="Reload"/>
528 </toolbar>
529 </toolbox>
530 <textbox id="textField" flex="1" multiline="true"
531 oninput="Presentation.onEdit()"/>
532 </vbox>
533
534 </deck>
535
536
537 <broadcasterset>
538 <broadcaster id="canBack"/>
539 <broadcaster id="canForward"/>
540 </broadcasterset>
541
542 <commandset>
543 <command id="cmd_forward"
544 oncommand="if (Presentation.isPresentationMode) Presentation.forward();"/>
545 <command id="cmd_forwardStep"
546 oncommand="if (Presentation.isPresentationMode) Presentation.forwardStep();"/>
547 <command id="cmd_back"
548 oncommand="if (Presentation.isPresentationMode) Presentation.back();"/>
549 <command id="cmd_home"
550 oncommand="if (Presentation.isPresentationMode) Presentation.home();"/>
551 <command id="cmd_end"
552 oncommand="if (Presentation.isPresentationMode) Presentation.end();"/>
553 </commandset>
554 <keyset>
555 <key keycode="VK_ENTER" command="cmd_forwardStep"/>
556 <key keycode="VK_RETURN" command="cmd_forwardStep"/>
557 <key keycode="VK_PAGE_DOWN" command="cmd_forwardStep"/>
558 <key keycode="VK_RIGHT" command="cmd_forwardStep"/>
559 <key keycode="VK_DOWN" command="cmd_forwardStep"/>
560 <!--key keycode="VK_BACK_SPACE" command="cmd_back"/-->
561 <key keycode="VK_PAGE_UP" command="cmd_back"/>
562 <key keycode="VK_UP" command="cmd_back"/>
563 <key keycode="VK_LEFT" command="cmd_back"/>
564 <key keycode="VK_HOME" command="cmd_home"/>
565 <key keycode="VK_END" command="cmd_end"/>
566
567 <key id="key_insert_newpage"
568 key="n" modifiers="accel" oncommand="Presentation.insert('page');"/>
569
570 <key id="key_save"
571 key="s" modifiers="accel" oncommand="Presentation.output();"/>
572 <key id="key_reload"
573 key="r" modifiers="accel" oncommand="Presentation.reload();"/>
574
575 <key key="e" modifiers="accel" oncommand="Presentation.toggleEditMode();"/>
576 <key key="e" modifiers="accel,shift" oncommand="Presentation.toggleEvaMode();"/>
577 </keyset>
578
579
580 <script type="application/x-javascript"><![CDATA[
581
582 var Presentation = {
583
584 size : 9,
585 montaLabelImage : 'monta-label.png',
586
587 phraseOpenParen : '[',
588 phraseCloseParen : ']',
589 makePhraseRegExp : function(aPattern, aFlags)
590 {
591 return new RegExp(
592 aPattern.replace(/%o(pen)?/gi, '\\'+this.phraseOpenParen)
593 .replace(/%c(lose)?/gi, '\\'+this.phraseCloseParen),
594 aFlags
595 );
596 },
597
598 dragStartDelta : 8,
599
600
601 initialized : false,
602
603 preventToShowHideToolbar : false,
604
605 showMontaKeywordTimeout : 100,
606 autoCruiseInterval : 2000,
607 timerUpdatingInterval : 30000,
608 standByMontaLabels : [],
609 shownMontaLabels : [],
610
611 init : function(option){
612 if (this.initialized) {
613 this.startPresentation();
614 return;
615 }
616 this.initialized = true;
617
618
619 this._offset = 0;
620 this.canvas = document.getElementById('canvas');
621 this.content = document.getElementById('content');
622 this.header = document.getElementById('header');
623 this.footer = document.getElementById('footer');
624 this.next = document.getElementById('nextPage');
625
626 this.indicatorBar = document.getElementById('indicatorBar');
627 this.remainder = document.getElementById('remainingPageIndicator');
628 this.timer = document.getElementById('remainingTimeIndicator');
629
630 this.list = document.getElementById('pages-list');
631 this.textbox = document.getElementById('textField');
632 this.deck = document.getElementById('deck');
633 this.scroller = document.getElementById('scroller');
634
635 this.toolbar = document.getElementById('canvasToolbar');
636 this.toolbarHeight = this.toolbar.boxObject.height;
637 this.isToolbarHidden = true;
638 this.toolbar.setAttribute('style', 'margin-top:'+(0-this.toolbarHeight)+'px;margin-bottom:0px;');
639
640 this.preloadImage(this.montaLabelImage);
641
642 window.addEventListener('resize', this, false);
643 window.addEventListener('contextmenu', this, false);
644
645 if(option){
646 for(var i in option){this[i] = option[i]}
647 }
648
649 if (this.readParameter()) {
650 this.startPresentation();
651 }
652
653 document.documentElement.focus();
654 },
655
656 startPresentation : function()
657 {
658 if (this.data.length)
659 document.title = this.data[0].title || this.data[0].header || this.data[0].text.join(' ');
660
661 this.takahashi();
662 },
663
664 takahashi : function() {
665 if(!this.data[this.offset]){
666 this.offset = this.data.length-1;
667 }
668 document.getElementById("current_page").value = this.offset+1;
669 document.getElementById("max_page").value = this.data.length;
670
671 this.scroller.setAttribute('maxpos', this.data.length-1);
672 this.scroller.setAttribute('curpos', this.offset);
673
674 var broadcaster = document.getElementById('canBack');
675 if (!this.offset)
676 broadcaster.setAttribute('disabled', true);
677 else
678 broadcaster.removeAttribute('disabled');
679
680 var broadcaster = document.getElementById('canForward');
681 if (this.offset == this.data.length-1)
682 broadcaster.setAttribute('disabled', true);
683 else
684 broadcaster.removeAttribute('disabled');
685
686 this.canvas.setAttribute('rendering', true);
687
688
689
690 this.header.removeAttribute('style');
691 this.footer.removeAttribute('style');
692 this.content.removeAttribute('style');
693
694 this.standByMontaLabels = [];
695 this.clickableNodes = [];
696
697
698 if ('title' in this.data[this.offset])
699 document.title = this.data[this.offset].title;
700
701 this.header.setAttribute('style', 'font-size:10px;');
702 this.header.value = this.data[this.offset].header;
703 this.footer.setAttribute('style', 'font-size:10px;');
704 this.footer.value = this.data[this.offset].footer;
705
706 var text = this.data[this.offset].text;
707 var range = document.createRange();
708 range.selectNodeContents(this.content);
709 range.deleteContents();
710 range.detach();
711
712 var line;
713 var newLine;
714 var uri;
715 var image_width;
716 var image_total_width = 0;
717 var image_height;
718 var image_total_height = 0;
719 var image_src;
720
721 var labelId = 0;
722 var lineRegExp = this.makePhraseRegExp('^([^%O]+)?(%O%Oem:((.+?)(:em)?%C%C)?|%O%Opre:((.+?)(:pre)?%C%C)?|%O%O\#[^:]+:((.+?)%C%C)?|%O%Oima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^%C]*%C%C|%O%O(([^\|]+)?\\||)([^%C]+)%C%C|%O([^%C]+)%C)(.+)?', 'i');
723
724 var emRegExp = this.makePhraseRegExp('^([^%O]+)?%O%Oem:(.+?)(:em)?%C%C', 'i');
725 var emStartRegExp = this.makePhraseRegExp('^([^%O]+)?%O%Oem:(.*)', 'i');
726 var emEndRegExp = this.makePhraseRegExp('^(.*?)((:em)?%C%C)', 'i');
727
728 var preRegExp = this.makePhraseRegExp('^([^%O]+)?%O%Opre:(.+?)(:pre)?%C%C', 'i');
729 var preStartRegExp = this.makePhraseRegExp('^([^%O]+)?%O%Opre:(.*)', 'i');
730 var preEndRegExp = this.makePhraseRegExp('^(.*?)((:pre)?%C%C)', 'i');
731
732 var styleRegExp = this.makePhraseRegExp('^([^%O]+)?%O%O\\#([^:]+):(.+?)%C%C', '');
733 var styleStartRegExp = this.makePhraseRegExp('^([^%O]+)?%O%O\\#([^:]+):(.*)', '');
734 var styleEndRegExp = this.makePhraseRegExp('^(.*?)(%C%C)', '');
735
736 var imagesRegExp = this.makePhraseRegExp('^([^%O]+)?%O%Oima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^%C]*%C%C', 'i');
737
738 var linksRegExp = this.makePhraseRegExp('^([^%O]+)?%O%O(([^|]+)?\\||)([^%C]+)%C%C', '');
739
740 var wikiRegExp = this.makePhraseRegExp('^([^%O]+)?%O([0-9]*)([#!])?([:\/\*_-])([^%C]+)[:\/\*_-]%C', '');
741
742 var montaRegExp = this.makePhraseRegExp('^([^%O]+)?%O([^%C]+)%C', '');
743
744 var inBlock = false,
745 blockClass = '',
746 blockContents = [];
747
748 var fragment = document.createDocumentFragment();
749
750 for (var i = 0, max = text.length; i < max; i++)
751 {
752 fragment.appendChild(document.createElement('hbox'));
753 fragment.lastChild.setAttribute('align', 'center');
754 fragment.lastChild.setAttribute('pack', this.data[this.offset].align);
755
756 line = text[i];
757 image_width = 0;
758 image_height = 0;
759 if (!line) line = ' ';
760
761 if (inBlock) {
762 if (blockClass == 'preformatted-text' &&
763 preEndRegExp.test(line)) {
764 inBlock = false;
765 blockContents.push(RegExp.$1);
766 line = line.substring((RegExp.$1+RegExp.$2).length);
767
768 fragment.lastChild.appendChild(document.createElement('description'));
769 fragment.lastChild.lastChild.setAttribute('class', 'preformatted-text block');
770 fragment.lastChild.lastChild.appendChild(document.createTextNode(
771 blockContents.join('\n')
772 .replace(/^[\r\n\s]+/, '')
773 .replace(/[\r\n\s]+$/, '')
774 .replace(/&amp;/g, '&')
775 .replace(/&quot;/g, '"')
776 .replace(/&gt;/g, '>')
777 .replace(/&lt;/g, '<')
778 ));
779
780 blockClass = '';
781 blockContents = [];
782 }
783 else if (emEndRegExp.test(line) || styleEndRegExp.test(line)) {
784 inBlock = false;
785 blockContents.push(RegExp.$1);
786 line = line.substring((RegExp.$1+RegExp.$2).length);
787
788 fragment.lastChild.appendChild(document.createElement('vbox'));
789 fragment.lastChild.lastChild.setAttribute('class', blockClass+' block');
790 fragment.lastChild.lastChild.setAttribute('align', this.data[this.offset].align);
791 blockContents = blockContents.join('\n')
792 .replace(/^[\r\n\s]+/, '')
793 .replace(/[\r\n\s]+$/, '')
794 .split('\n');
795 for (var j = 0, jmax = blockContents.length; j < jmax; j++)
796 {
797 fragment.lastChild.lastChild.appendChild(document.createElement('description'));
798 fragment.lastChild.lastChild.lastChild.setAttribute('value', blockContents[j]);
799 }
800
801 blockClass = '';
802 blockContents = [];
803 }
804 else {
805 blockContents.push(line);
806 continue;
807 }
808 }
809
810 while (line.match(lineRegExp))
811 {
812 if (RegExp.$1) {
813 fragment.lastChild.appendChild(document.createElement('description'));
814 fragment.lastChild.lastChild.setAttribute('value', RegExp.$1);
815 }
816 newLine = line.substring((RegExp.$1+RegExp.$2).length);
817
818 // Preformatted Text
819 if (preRegExp.test(line)) {
820 fragment.lastChild.appendChild(document.createElement('description'));
821 fragment.lastChild.lastChild.setAttribute('value', RegExp.$2);
822 fragment.lastChild.lastChild.setAttribute('class', 'preformatted-text');
823 }
824 else if (preStartRegExp.test(line)) {
825 inBlock = true;
826 blockClass = 'preformatted-text';
827 blockContents = [RegExp.$2];
828 newLine = '';
829 }
830
831 // Emphasis
832 else if (emRegExp.test(line)) {
833 fragment.lastChild.appendChild(document.createElement('description'));
834 fragment.lastChild.lastChild.setAttribute('value', RegExp.$2);
835 fragment.lastChild.lastChild.setAttribute('class', 'em-text');
836 }
837 else if (emStartRegExp.test(line)) {
838 inBlock = true;
839 blockClass = 'em-text';
840 blockContents = [RegExp.$2];
841 newLine = '';
842 }
843
844 // User-defined Styles
845 else if (styleRegExp.test(line)) {
846 fragment.lastChild.appendChild(document.createElement('description'));
847 fragment.lastChild.lastChild.setAttribute('value', RegExp.$3);
848 fragment.lastChild.lastChild.setAttribute('class', RegExp.$2);
849 }
850 else if (styleStartRegExp.test(line)) {
851 inBlock = true;
852 blockClass = RegExp.$2;
853 blockContents = [RegExp.$3];
854 newLine = '';
855 }
856
857 // Images
858 else if (imagesRegExp.test(line)) {
859 fragment.lastChild.appendChild(document.createElement('image'));
860 image_src = RegExp.$2;
861 if (image_src.indexOf('http://') < 0 &&
862 image_src.indexOf('https://') < 0)
863 image_src = this.dataFolder+image_src;
864 fragment.lastChild.lastChild.setAttribute('src', image_src);
865 fragment.lastChild.lastChild.setAttribute('width', parseInt(RegExp.$3 || '0'));
866 fragment.lastChild.lastChild.setAttribute('height', parseInt(RegExp.$4 || '0'));
867 image_width += parseInt(RegExp.$3 || '0');
868 image_height = Math.max(image_height, parseInt(RegExp.$4 || '0'));
869 }
870
871 // Links
872 else if (linksRegExp.test(line)) {
873 uri = RegExp.$4;
874 if (uri.indexOf('://') < 0)
875 uri = this.dataFolder+uri;
876 fragment.lastChild.appendChild(document.createElement('description'));
877 fragment.lastChild.lastChild.setAttribute('value', RegExp.$3 || RegExp.$4);
878 fragment.lastChild.lastChild.setAttribute('href', uri);
879 fragment.lastChild.lastChild.setAttribute('tooltiptext', uri);
880 fragment.lastChild.lastChild.setAttribute('statustext', uri);
881 fragment.lastChild.lastChild.setAttribute('class', 'link-text');
882
883 this.clickableNodes.push(fragment.lastChild.lastChild);
884 }
885
886 // modify font size and wiki-style
887 else if (wikiRegExp.test(line)) {
888 fragment.lastChild.appendChild(document.createElement('description'));
889 fragment.lastChild.lastChild.setAttribute('value', RegExp.$5);
890 var style = 'font-size:'+ ( RegExp.$2 || 100 ) +'%';
891 if (RegExp.$4 == '*') {
892 style += '; font-weight: bold;';
893 } else if (RegExp.$4 == '/') {
894 style += '; font-style: italic;';
895 } else if (RegExp.$4 == '_') {
896 style += '; text-decoration: underline;';
897 } else if (RegExp.$4 == '-') {
898 style += '; text-decoration: line-through;';
899 }
900 fragment.lastChild.lastChild.setAttribute('style', style);
901 if (RegExp.$3 == '!') fragment.lastChild.lastChild.setAttribute('class', 'em-text');
902 else if (RegExp.$3 == '#') fragment.lastChild.lastChild.setAttribute('class', 'preformatted-text');
903 }
904
905 // Monta
906 else if (montaRegExp.test(line)) {
907 fragment.lastChild.appendChild(document.createElement('stack'));
908
909 fragment.lastChild.lastChild.appendChild(document.createElement('description'));
910 fragment.lastChild.lastChild.lastChild.setAttribute('value', RegExp.$2);
911 fragment.lastChild.lastChild.lastChild.setAttribute('class', 'monta-text');
912
913 fragment.lastChild.lastChild.appendChild(document.createElement('spacer'));
914 fragment.lastChild.lastChild.lastChild.setAttribute('flex', 1);
915 fragment.lastChild.lastChild.lastChild.setAttribute('class', 'monta-label');
916
917 fragment.lastChild.lastChild.lastChild.setAttribute('label-id', 'label-' + (++labelId));
918
919 if (!this.shownMontaLabels[this.offset] || !this.shownMontaLabels[this.offset]['label-'+labelId]) {
920 fragment.lastChild.lastChild.lastChild.setAttribute('monta-hidden', 'true');
921 this.standByMontaLabels[this.standByMontaLabels.length] = fragment.lastChild.lastChild.lastChild;
922 }
923 else {
924 fragment.lastChild.lastChild.lastChild.setAttribute('monta-hidden', 'false');
925 }
926
927 this.clickableNodes.push(fragment.lastChild.lastChild.lastChild);
928 }
929
930 line = newLine;
931 }
932
933 if (line) {
934 fragment.lastChild.appendChild(document.createElement('description'));
935 fragment.lastChild.lastChild.setAttribute('value', line);
936 }
937
938 image_total_width = Math.max(image_total_width, image_width);
939 image_total_height += image_height;
940 }
941
942 this.content.setAttribute('style', 'font-size:10px;');
943 this.content.appendChild(fragment);
944
945 this.clickableNodes.push(this.content);
946
947
948 this.fitToCanvas(this.header, this.header.parentNode, 0, 0);
949 this.fitToCanvas(this.footer, this.footer.parentNode, 0, 0);
950 this.fitToCanvas(
951 this.content,
952 this.canvas,
953 image_total_width,
954 image_total_height
955 +(this.header.boxObject.height*2)
956 // +(this.footer.boxObject.height*2)
957 );
958
959
960 var checkedItems = this.list.getElementsByAttribute('checked', 'true');
961 max = checkedItems.length;
962 for (i = 0; i < max; i++)
963 checkedItems[i].removeAttribute('checked');
964
965 this.list.getElementsByAttribute('value', this.offset)[0].setAttribute('checked', true);
966
967 this.canvas.removeAttribute('rendering');
968 this.setHash('page', 'page'+(this.offset+1));
969
970 this.next.value = (this.offset <= this.data.length-2) ? (this.data[this.offset+1].plain.join('') || this.data[this.offset+1].text.join('')).replace(/\s+/g, ' ') : '(no page)' ;
971 this.remainder.setAttribute('value', this.offset == 0 ? 0 : parseInt(((this.offset)/(this.data.length-1))*100));
972
973 var event = document.createEvent('Events');
974 event.initEvent('PresentationRedraw', false, true);
975 this.canvas.dispatchEvent(event);
976 },
977 fitToCanvas : function(aContent, aCanvas, aOffsetWidth, aOffsetHeight)
978 {
979 aContent.removeAttribute('style');
980 aContent.setAttribute('style', 'font-size:10px;');
981
982 if (!aContent.boxObject.width) return;
983
984 var canvas_w = aCanvas.boxObject.width;
985 var canvas_h = aCanvas.boxObject.height-aOffsetHeight;
986
987 var content_w = aContent.boxObject.width;
988 var new_fs = Math.round((canvas_w/content_w) * this.size);
989 aContent.setAttribute('style', 'font-size:'+ new_fs + "px");
990
991 if (aContent.boxObject.width < aOffsetWidth) {
992 content_w = aOffsetWidth;
993 new_fs = Math.round((canvas_w/content_w) * this.size);
994 aContent.setAttribute('style', 'font-size:'+ new_fs + "px");
995 }
996
997 var content_h = aContent.boxObject.height;
998 if(content_h >= canvas_h){
999 state='height';
1000 content_h = aContent.boxObject.height;
1001 new_fs = Math.round((canvas_h/content_h) * new_fs);
1002 aContent.setAttribute('style', 'font-size:'+ new_fs + "px");
1003 }
1004 },
1005
1006 reload : function() {
1007 var file = String(location.href).replace(/#.+$/, '');
1008 if (this.dataPath != file) {
1009 var path = this.dataPath;
1010 var request = new XMLHttpRequest();
1011 request.open('GET', path + '?rand=' + Math.random() );
1012 request.onload = function() {
1013 Presentation.textbox.value = request.responseText;
1014 Presentation.data = Presentation.textbox.value;
1015 Presentation.init();
1016
1017 path = null;
1018 request = null;
1019 };
1020 request.send(null);
1021 }
1022 else
1023 window.location.reload();
1024 },
1025
1026 forward : function(){
1027 this.offset++;
1028 this.takahashi();
1029 },
1030 forwardStep : function(){
1031 if (this.standByMontaLabels.length > 0) {
1032 while (this.standByMontaLabels.length &&
1033 this.standByMontaLabels[0].getAttribute('monta-hidden') != 'true')
1034 this.standByMontaLabels.splice(0, 1);
1035
1036 if (this.standByMontaLabels.length) {
1037 this.showMontaKeyword(this.standByMontaLabels[0]);
1038 this.standByMontaLabels.splice(0, 1);
1039 }
1040 }
1041 else
1042 this.forward();
1043 },
1044 back : function(){
1045 this.offset--;
1046 if(this.offset < 0){this.offset = 0}
1047 this.takahashi();
1048 },
1049 home : function(){
1050 this.offset = 0;
1051 this.takahashi();
1052 },
1053 end : function(){
1054 this.offset = this.data.length-1;
1055 this.takahashi();
1056 },
1057 showPage : function(aPageOffset){
1058 this.offset = aPageOffset ? aPageOffset : 0 ;
1059 this.takahashi();
1060 },
1061
1062 insert : function(aType) {
1063 switch (aType)
1064 {
1065 case 'page':
1066 this.insertTextFor('\n----\n', this.textbox, 6);
1067 break;
1068 case 'header':
1069 this.insertTextFor('\nHEADER::\n', this.textbox, 9);
1070 break;
1071 case 'footer':
1072 this.insertTextFor('\nFOOTER::\n', this.textbox, 9);
1073 break;
1074
1075 case 'em':
1076 case 'emphasis':
1077 this.insertTextFor(this.phraseOpenParen+this.phraseOpenParen+'EM:'+this.phraseCloseParen+this.phraseCloseParen, this.textbox, 5);
1078 break;
1079 case 'pre':
1080 case 'preformatted':
1081 this.insertTextFor(this.phraseOpenParen+this.phraseOpenParen+'PRE:'+this.phraseCloseParen+this.phraseCloseParen, this.textbox, 6);
1082 break;
1083 case 'monta':
1084 this.insertTextFor(this.phraseOpenParen+this.phraseCloseParen, this.textbox, 1);
1085 break;
1086 case 'link':
1087 this.insertTextFor(this.phraseOpenParen+this.phraseOpenParen+'|http://'+this.phraseCloseParen+this.phraseCloseParen, this.textbox, 2);
1088 break;
1089 case 'img':
1090 case 'image':
1091 this.insertTextFor(this.phraseOpenParen+this.phraseOpenParen+'image src="" width="" height=""'+this.phraseCloseParen+this.phraseCloseParen, this.textbox, 13);
1092 break;
1093
1094 default:
1095 return;
1096 }
1097 this.onEdit();
1098 },
1099 insertTextFor : function(aString, aNode, aPosOffset)
1100 {
1101 var pos = aNode.selectionStart;
1102 var sel_len = aNode.selectionEnd - aNode.selectionStart;
1103 var value = aNode.value;
1104 if (! aPosOffset) aPosOffset = 0;
1105 aNode.value = [
1106 value.substring(0, pos),
1107 aString.substring(0,aPosOffset),
1108 value.substring(pos, pos + sel_len),
1109 aString.substring(aPosOffset, aString.length),
1110 value.substring(pos + sel_len, value.length)
1111 ].join('');
1112 aNode.selectionStart = pos + (aPosOffset || 0);
1113 aNode.selectionEnd = aNode.selectionStart + sel_len;
1114 },
1115
1116
1117 output : function()
1118 {
1119 location.href = 'data:application/octet-stream,'+encodeURIComponent(this.textbox.value);
1120 },
1121
1122
1123 toggleEditMode : function(){
1124 this.deck.selectedIndex = this.deck.selectedIndex == 0 ? 1 : 0 ;
1125 this.setHash('edit', this.deck.selectedIndex == 0 ? '' : 'edit' );
1126 },
1127 toggleEvaMode : function(){
1128 var check = document.getElementById('toggleEva');
1129 if (this.canvas.getAttribute('eva') == 'true') {
1130 this.canvas.removeAttribute('eva');
1131 check.checked = false;
1132 }
1133 else {
1134 this.canvas.setAttribute('eva', true);
1135 check.checked = true;
1136 }
1137 this.setHash('eva', check.checked ? 'eva' : '' );
1138 },
1139
1140
1141
1142 toggleAutoCruiseMode : function()
1143 {
1144 var autoCruise = document.getElementById('autoButton');
1145 if(!autoCruise.checked)
1146 this.startAutoCruise();
1147 else
1148 autoCruise.checked = false;
1149 },
1150 startAutoCruise : function()
1151 {
1152 var autoCruise = document.getElementById('autoButton');
1153 autoCruise.checked = true;
1154
1155 if (this.autoCruiseTimer) {
1156 window.clearTimeout(this.autoCruiseTimer);
1157 }
1158 this.autoCruiseTimer = window.setTimeout(this.autoCruise, this.autoCruiseInterval);
1159 },
1160
1161 changeAutoCruiseInterval : function(aInterval)
1162 {
1163 this.autoCruiseInterval = aInterval;
1164 this.startAutoCruise();
1165 },
1166
1167 autoCruise : function()
1168 {
1169 var autoCruise = document.getElementById('autoButton');
1170 if (!autoCruise.checked) return;
1171
1172 if(Presentation.offset == Presentation.data.length-1) {
1173 Presentation.home();
1174 }
1175 else {
1176 Presentation.forwardStep();
1177 }
1178 Presentation.autoCruiseTimer = window.setTimeout(arguments.callee, Presentation.autoCruiseInterval);
1179 },
1180 autoCruiseTimer : null,
1181
1182
1183
1184 setHash : function(aKey, aValue)
1185 {
1186 aKey = String(aKey).toLowerCase();
1187 var hashArray = String(location.hash).replace(/^#/, '').toLowerCase().split(',');
1188
1189 for (var i = hashArray.length-1; i > -1; i--)
1190 if (!hashArray[i] || hashArray[i].indexOf(aKey) == 0)
1191 hashArray.splice(i, 1);
1192
1193 if (aValue) hashArray.push(aValue);
1194 hashArray.sort();
1195
1196 location.hash = hashArray.length ? hashArray.join(',') : '' ;
1197 },
1198
1199
1200 showMontaKeyword : function(aNode) {
1201 if (aNode.getAttribute('monta-hidden') != 'true') return;
1202
1203 aNode.setAttribute('monta-hidden', 'progress');
1204
1205 window.setTimeout(this.showMontaKeywordCallback, 0, {
1206 position : -100,
1207 node : aNode,
1208 interval : this.showMontaKeywordTimeout/10
1209 });
1210 },
1211 showMontaKeywordCallback : function(aInfo) {
1212 if (aInfo.position >= aInfo.node.boxObject.width) {
1213 aInfo.node.setAttribute('monta-hidden', 'false');
1214 if (!Presentation.shownMontaLabels[Presentation.offset])
1215 Presentation.shownMontaLabels[Presentation.offset] = [];
1216 Presentation.shownMontaLabels[Presentation.offset][aInfo.node.getAttribute('label-id')] = true;
1217 return;
1218 }
1219
1220 aInfo.position += (aInfo.node.boxObject.width/10);
1221 aInfo.node.setAttribute('style', 'background-position: '+aInfo.position+'px 0 !important;');
1222 window.setTimeout(arguments.callee, aInfo.interval, aInfo);
1223 },
1224
1225
1226
1227 onPresentationClick : function(aEvent)
1228 {
1229 if (!this.isToolbarHidden)
1230 this.showHideToolbar();
1231
1232 switch(aEvent.button)
1233 {
1234 case 0:
1235 switch (aEvent.target.getAttribute('class'))
1236 {
1237 case 'link-text':
1238 var uri = aEvent.target.getAttribute('href');
1239 if (uri) {
1240 window.open(uri);
1241 return;
1242 }
1243 break;
1244
1245 case 'monta-label':
1246 if (aEvent.target.getAttribute('monta-hidden') == 'true') {
1247 this.showMontaKeyword(aEvent.target);
1248 aEvent.preventBubble();
1249 return;
1250 }
1251
1252 default:
1253 break;
1254 }
1255 this.forward();
1256 document.documentElement.focus();
1257 break;
1258 case 2:
1259 this.back();
1260 document.documentElement.focus();
1261 break;
1262 default:
1263 break;
1264 }
1265 },
1266
1267 onScrollerDragStart : function(){
1268 this.scroller.dragging = true;
1269 },
1270 onScrollerDragMove : function(){
1271 if (this.scroller.dragging)
1272 this.showPage(parseInt(this.scroller.getAttribute('curpos')));
1273 },
1274 onScrollerDragDrop : function(){
1275 this.onScrollerDragMove();
1276 this.scroller.dragging = false;
1277 },
1278
1279 onIndicatorBarClick : function(aEvent)
1280 {
1281 var bar = this.indicatorBar;
1282 this.showPage(Math.round((aEvent.screenX - bar.boxObject.screenX) / bar.boxObject.width * this.data.length));
1283 },
1284 onIndicatorBarDragStart : function()
1285 {
1286 this.indicatorBar.dragging = true;
1287 },
1288 onIndicatorBarDragMove : function(aEvent)
1289 {
1290 var bar = this.indicatorBar;
1291 this.showPage(Math.round((aEvent.screenX - bar.boxObject.screenX) / bar.boxObject.width * this.data.length));
1292 },
1293 onIndicatorBarDragEnd : function(aEvent)
1294 {
1295 this.onIndicatorBarDragMove(aEvent);
1296 this.indicatorBar.dragging = false;
1297 },
1298
1299 onEdit : function() {
1300 this.data = this.textbox.value;
1301 this.init();
1302 },
1303
1304 onKeyPress : function(aEvent) {
1305 switch(aEvent.keyCode)
1306 {
1307 case aEvent.DOM_VK_BACK_SPACE:
1308 if (this.isPresentationMode) {
1309 aEvent.preventBubble();
1310 aEvent.preventDefault();
1311 Presentation.back();
1312 }
1313 break;
1314 default:
1315 break;
1316 }
1317 },
1318
1319
1320
1321 handleEvent : function(aEvent)
1322 {
1323 switch (aEvent.type)
1324 {
1325 default:
1326 break;
1327
1328 case 'resize':
1329 this.takahashi(); // redrwa
1330 break;
1331
1332 case 'contextmenu':
1333 aEvent.stopPropagation();
1334 aEvent.preventCapture();
1335 aEvent.preventDefault();
1336 aEvent.preventBubble();
1337 break;
1338
1339
1340 case 'mouseup':
1341 this.dragStartX = -1;
1342 this.dragStartY = -1;
1343 if (this.indicatorBar.dragging)
1344 this.onIndicatorBarDragEnd(aEvent);
1345 break;
1346
1347 case 'mousedown':
1348 if (this.dragStartX < 0) {
1349 this.dragStartX = aEvent.clientX;
1350 this.dragStartY = aEvent.clientY;
1351 }
1352 var box = this.indicatorBar.boxObject;
1353 if (!(aEvent.screenX < box.screenX ||
1354 aEvent.screenY < box.screenY ||
1355 aEvent.screenX > box.screenX+box.width ||
1356 aEvent.screenY > box.screenY+box.height))
1357 this.onIndicatorBarDragStart();
1358 break;
1359
1360 case 'mousemove':
1361 this.checkShowHideToolbar(aEvent);
1362 if (this.indicatorBar.dragging) {
1363 this.onIndicatorBarDragMove(aEvent);
1364 return;
1365 }
1366 if (this.dragStartX > -1) {
1367 if (Math.abs(this.dragStartX-aEvent.clientX) > Math.abs(this.dragStartDelta) ||
1368 Math.abs(this.dragStartY-aEvent.clientY) > Math.abs(this.dragStartDelta)) {
1369 var event = document.createEvent('Events');
1370 event.initEvent('StartDragOnCanvas', false, true);
1371 this.canvas.dispatchEvent(event);
1372 }
1373 }
1374 break;
1375
1376
1377 }
1378 },
1379 dragStartX : -1,
1380 dragStartY : -1,
1381
1382
1383
1384 onToolbarArea : false,
1385 toolbarHeight : 0,
1386 toolbarDelay : 300,
1387 toolbarTimer : null,
1388 isToolbarHidden : false,
1389 checkShowHideToolbar : function(aEvent) {
1390 if (this.scroller.dragging || this.preventToShowHideToolbar) return;
1391
1392 this.onToolbarArea = (aEvent.clientY < this.toolbarHeight);
1393
1394 if (this.isToolbarHidden == this.onToolbarArea) {
1395 if (this.toolbarTimer) window.clearTimeout(this.toolbarTimer);
1396 this.toolbarTimer = window.setTimeout('Presentation.checkShowHideToolbarCallback()', this.toolbarDelay);
1397 }
1398 },
1399 checkShowHideToolbarCallback : function() {
1400 if (this.isToolbarHidden == this.onToolbarArea)
1401 this.showHideToolbar();
1402 },
1403
1404 toolbarAnimationDelay : 100,
1405 toolbarAnimationSteps : 5,
1406 toolbarAnimationInfo : null,
1407 toolbarAnimationTimer : null,
1408 showHideToolbar : function()
1409 {
1410 if (this.toolbarAnimationTimer) window.clearTimeout(this.toolbarAnimationTimer);
1411
1412 this.toolbarAnimationInfo = { count : 0 };
1413 if (this.isToolbarHidden) {
1414 this.toolbarAnimationInfo.start = 0;
1415 this.toolbarAnimationInfo.end = this.toolbarHeight;
1416 }
1417 else {
1418 this.toolbarAnimationInfo.start = this.toolbarHeight;
1419 this.toolbarAnimationInfo.end = 0;
1420 }
1421 this.toolbarAnimationInfo.current = 0;
1422
1423 this.toolbar.setAttribute('style', 'margin-top:'+(0-(this.toolbarHeight-this.toolbarAnimationInfo.start))+'px; margin-bottom:'+(0-this.toolbarAnimationInfo.start)+'px;');
1424
1425 this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps);
1426 },
1427 animateToolbar : function()
1428 {
1429 this.toolbarAnimationInfo.current += parseInt(this.toolbarHeight/this.toolbarAnimationSteps);
1430
1431 var top, bottom;
1432 if (this.toolbarAnimationInfo.start < this.toolbarAnimationInfo.end) {
1433 top = this.toolbarHeight-this.toolbarAnimationInfo.current;
1434 bottom = this.toolbarAnimationInfo.current;
1435 }
1436 else {
1437 top = this.toolbarAnimationInfo.current;
1438 bottom = this.toolbarHeight-this.toolbarAnimationInfo.current;
1439 }
1440
1441 top = Math.min(Math.max(top, 0), this.toolbarHeight);
1442 bottom = Math.min(Math.max(bottom, 0), this.toolbarHeight);
1443
1444 this.toolbar.setAttribute('style', 'margin-top:'+(0-top)+'px; margin-bottom:'+(0-bottom)+'px');
1445
1446 if (this.toolbarAnimationInfo.count < this.toolbarAnimationSteps) {
1447 this.toolbarAnimationInfo.count++;
1448 this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps);
1449 }
1450 else
1451 this.isToolbarHidden = !this.isToolbarHidden;
1452 },
1453
1454
1455
1456 get offset(){
1457 return this._offset;
1458 },
1459 set offset(aValue){
1460 this._offset = parseInt(aValue || 0);
1461 document.documentElement.setAttribute('lastoffset', this.offset);
1462 return this.offset;
1463 },
1464
1465 get data(){
1466 if (!this._data) {
1467 // mozilla splits very long text node into multiple text nodes whose length is less than 4096 bytes.
1468 // so, we must concat all the text nodes.
1469 this.textbox.value = "";
1470 for (var i = 0; i < document.getElementById('builtinCode').childNodes.length; i++) {
1471 this.textbox.value += document.getElementById('builtinCode').childNodes[i].nodeValue;
1472 }
1473
1474 this._data = this.textbox.value.split(/----+/);
1475 this.initData();
1476 }
1477
1478 return this._data;
1479 },
1480 set data(aValue){
1481 this._data = aValue.split(/----+/);
1482 this.initData();
1483 return aValue;
1484 },
1485 initData : function()
1486 {
1487 var range = document.createRange();
1488 range.selectNodeContents(this.list);
1489 range.deleteContents();
1490
1491
1492 var regexp = [
1493 /^[\r\n\s]+/g,
1494 /[\r\n\s]+$/g,
1495 /(\r\n|[\r\n])/g
1496 ];
1497
1498 var title;
1499 var titleRegExp = /^(TITLE::)([^\n]*)\n?/im;
1500 var header = '';
1501 var headerRegExp = /^(HEADER::)([^\n]*)\n?/im;
1502 var footer = '';
1503 var footerRegExp = /^(FOOTER::)([^\n]*)\n?/im;
1504 var chapter = '';
1505 var chapterRegExp = /^(CHAPTER::)([^\n]*)\n?/im;
1506 var lastChapter;
1507 var alignGlobal = 'center';
1508 var align;
1509 var alignRegExp = /^((GLOBAL-)?ALIGN::)(left|right|center|start|end)?\n?/im;
1510
1511 var imageMatchResults;
1512 var imagesRegExp = this.makePhraseRegExp('%O%Oima?ge? +src="[^"]+" +width="[0-9]+" +height="[0-9]+"[^%C]*%C%C', 'gi');
1513 var imagesRegExp2 = this.makePhraseRegExp('%O%Oima?ge? +src="([^"]+)"', 'i');
1514 var image_src;
1515
1516 var plainTextRegExp = this.makePhraseRegExp('(%O%O\#[^:]+:(.+)%C%C|%O%OEM:(.+)(:EM)?%C%C|%O%OPRE:(.+)(:PRE)?%C%C|%O%Oima?ge? +src="[^"]*"[^%C]+%C%C|%O%O([^\\|%C]+)(\\|[^%C]+)?%C%C|%O([^%O]+)%C)', 'gi');
1517
1518 var dataObj;
1519 var i, j,
1520 max = this._data.length;
1521 var fragment = document.createDocumentFragment();
1522 var popup;
1523 for (i = 0; i < max; i++)
1524 {
1525 image_src = null;
1526 align = null;
1527
1528 this._data[i] = this._data[i]
1529 .replace(regexp[0], '')
1530 .replace(regexp[1], '')
1531 .replace(regexp[2], '\n');
1532
1533 while (titleRegExp.test(this._data[i])) {
1534 this._data[i] = this._data[i].replace(titleRegExp, '');
1535 if (String(RegExp.$1).toUpperCase() == 'TITLE::')
1536 title = RegExp.$2 || '' ;
1537 }
1538
1539 while (headerRegExp.test(this._data[i])) {
1540 this._data[i] = this._data[i].replace(headerRegExp, '');
1541 if (String(RegExp.$1).toUpperCase() == 'HEADER::')
1542 header = RegExp.$2 || '' ;
1543 }
1544
1545 while (footerRegExp.test(this._data[i])) {
1546 this._data[i] = this._data[i].replace(footerRegExp, '');
1547 if (String(RegExp.$1).toUpperCase() == 'FOOTER::')
1548 footer = RegExp.$2 || '' ;
1549 }
1550
1551 while (chapterRegExp.test(this._data[i])) {
1552 this._data[i] = this._data[i].replace(chapterRegExp, '');
1553 if (String(RegExp.$1).toUpperCase() == 'CHAPTER::')
1554 chapter = RegExp.$2 || '' ;
1555 }
1556
1557 while (alignRegExp.test(this._data[i])) {
1558 this._data[i] = this._data[i].replace(alignRegExp, '');
1559
1560 align = (RegExp.$3 || '').toLowerCase();
1561 if (align == 'left')
1562 align = 'start';
1563 else if (align == 'right')
1564 align = 'end';
1565
1566 if (String(RegExp.$1).toUpperCase() == 'GLOBAL-ALIGN::') {
1567 alignGlobal = align;
1568 align = null;
1569 }
1570 }
1571
1572 imageMatchResults = this._data[i].match(imagesRegExp);
1573 if (imageMatchResults) {
1574 for (j = imageMatchResults.length-1; j > -1; j--)
1575 image_src = this.preloadImage(imageMatchResults[j].match(imagesRegExp2)[1]);
1576 }
1577
1578 this._data[i] = {
1579 header : header,
1580 footer : footer,
1581 text : this._data[i].split('\n'),
1582 image : image_src,
1583 align : align || alignGlobal
1584 };
1585 this._data[i].plain = this._data[i].text
1586 .join('\n')
1587 .replace(plainTextRegExp, '$2$3$5$7$9')
1588 .split('\n');
1589 if (title !== void(0))
1590 this._data[i].title = title;
1591
1592 this._data[i].chapter = chapter || title || '';
1593 if (lastChapter === void(0) ||
1594 lastChapter != this._data[i].chapter) {
1595 lastChapter = this._data[i].chapter;
1596
1597 if (popup && popup.childNodes.length == 1) {
1598 fragment.removeChild(fragment.lastChild);
1599 fragment.appendChild(popup.removeChild(popup.lastChild));
1600 }
1601
1602 popup = document.createElement('menupopup');
1603 fragment.appendChild(document.createElement('menu'));
1604 fragment.lastChild.setAttribute('label', this._data[i].chapter);
1605 fragment.lastChild.appendChild(popup);
1606 }
1607
1608 popup.appendChild(document.createElement('menuitem'));
1609 popup.lastChild.setAttribute('type', 'radio');
1610 popup.lastChild.setAttribute('radiogroup', 'pages');
1611 popup.lastChild.setAttribute('label', (i+1)+': '+(
1612 (this._data[i].plain.join('') || this._data[i].text.join(' ')).replace(/\s+/g, ' ')
1613 ));
1614 popup.lastChild.setAttribute('value', i);
1615
1616 // if (image_src) {
1617 // popup.lastChild.setAttribute('image', image_src);
1618 // popup.lastChild.setAttribute('class', 'menuitem-iconic');
1619 // }
1620 }
1621
1622 if (fragment.childNodes.length == 1) {
1623 range.selectNodeContents(fragment.firstChild.firstChild);
1624 fragment = range.extractContents();
1625 }
1626 this.list.appendChild(fragment);
1627
1628 range.detach();
1629
1630
1631 this.shownMontaLabels = [];
1632 },
1633
1634 preloadImage : function(aURI)
1635 {
1636 if (aURI in this.imageRequests) return;
1637
1638 if (aURI.indexOf('http://') < 0 &&
1639 aURI.indexOf('https://') < 0)
1640 aURI = this.dataFolder+aURI;
1641
1642 this.imageRequests[aURI] = new XMLHttpRequest();
1643 try {
1644 this.imageRequests[aURI].open('GET', aURI);
1645 this.imageRequests[aURI].onload = function() {
1646 Presentation.imageRequests[aURI] = null;
1647 };
1648 this.imageRequests[aURI].send(null);
1649 }
1650 catch(e) {
1651 this.imageRequests[aURI] = null;
1652 }
1653 return aURI;
1654 },
1655 imageRequests : {},
1656
1657
1658 get isPresentationMode(){
1659 return (this.deck.selectedIndex == 0);
1660 },
1661
1662
1663 get dataPath(){
1664 if (!this._dataPath)
1665 this.dataPath = String(location.href).replace(/#.+$/, '');
1666 return this._dataPath;
1667 },
1668 set dataPath(aValue){
1669 var oldDataPath = this._dataPath;
1670 this._dataPath = aValue;
1671 if (oldDataPath != aValue) {
1672 this._dataFolder = this._dataPath.split('?')[0].replace(/[^\/]+$/, '');
1673 }
1674 return this._dataPath;
1675 },
1676
1677 get dataFolder(){
1678 if (!this._dataFolder)
1679 this.dataPath = this.dataPath;
1680 return this._dataFolder;
1681 },
1682 set dataFolder(aValue){
1683 this._dataFolder = aValue;
1684 return this._dataFolder;
1685 },
1686
1687 readParameter : function() {
1688 if (location.search || location.hash) {
1689 var param = location.search.replace(/^\?/, '');
1690
1691 if (location.hash.match(/page([0-9]+)/i) ||
1692 param.match(/page=([0-9]+)/i))
1693 this.offset = parseInt(RegExp.$1)-1;
1694
1695 if (location.hash.match(/edit/i) ||
1696 param.match(/edit=(1|true|yes)/i))
1697 this.toggleEditMode();
1698
1699 if (location.hash.match(/eva/i) ||
1700 param.match(/eva=(1|true|yes)/i))
1701 this.toggleEvaMode();
1702
1703 if (location.hash.match(/timer(\d+)\-(\d+)/i))
1704 this.setTimer(RegExp.$1, RegExp.$2);
1705
1706 if (param.match(/(style|css)=([^&;]+)/i)) {
1707 var style = unescape(RegExp.$2);
1708 var pi = document.createProcessingInstruction('xml-stylesheet', 'href="'+style+'" type="text/css"');
1709 document.insertBefore(pi, document.documentElement);
1710 }
1711
1712 if (param.match(/data=([^&;]+)/i)) {
1713 var path = unescape(RegExp.$1);
1714 this.dataPath = path;
1715 var request = new XMLHttpRequest();
1716 request.open('GET', path);
1717 request.onload = function() {
1718 Presentation.textbox.value = request.responseText;
1719 Presentation.data = Presentation.textbox.value;
1720 Presentation.init();
1721 };
1722 request.send(null);
1723 return false;
1724 }
1725 }
1726 return true;
1727 },
1728
1729
1730
1731 resetTimer : function()
1732 {
1733 if (this.timerTimer) {
1734 window.clearInterval(this.timerTimer);
1735 this.timerTimer = null;
1736 }
1737 this.timer.setAttribute('value', 0);
1738 this.timer.setAttribute('collapsed', true);
1739 this.setHash('timer', '');
1740 },
1741 setTimer : function(aStart, aEnd)
1742 {
1743 var now = (new Date()).getTime();
1744 if (aStart === void(0) || aEnd === void(0)) {
1745 var rest = prompt('Remaining Time (minits)');
1746 if (rest == '') {
1747 this.resetTimer();
1748 return;
1749 }
1750 else {
1751 rest = Number(rest);
1752 if (!rest || isNaN(rest)) return;
1753 }
1754
1755 rest = Math.abs(rest);
1756 this.timerStart = now;
1757 this.timerEnd = this.timerStart + (rest * 60000);
1758 }
1759 else {
1760 aStart = Number(aStart);
1761 aEnd = Number(aEnd);
1762 if (isNaN(aStart) || isNaN(aEnd)) return;
1763
1764 this.timerStart = Math.min(aStart, aEnd);
1765 this.timerEnd = Math.max(aStart, aEnd);
1766
1767 if (this.timerStart >= now || this.timerEnd <= now) return;
1768 }
1769
1770 this.resetTimer();
1771
1772 this.timer.removeAttribute('collapsed');
1773 this.setHash('timer', 'timer'+this.timerStart+'-'+this.timerEnd);
1774
1775 if (now != this.timerStart)
1776 this.updateTimer(this);
1777
1778 window.setInterval(this.updateTimer, Math.min(this.timerUpdatingInterval, (this.timerEnd-this.timerStart)/(this.data.length*2)), this);
1779 },
1780 updateTimer : function(aThis)
1781 {
1782 var now = (new Date()).getTime();
1783 if (now >= aThis.timerEnd) {
1784 aThis.resetTimer();
1785 aThis.timer.setAttribute('value', 100);
1786 aThis.timer.removeAttribute('collapsed');
1787 aThis.setHash('timer', '');
1788 }
1789 else {
1790 var value = parseInt(((now - aThis.timerStart) / (aThis.timerEnd - aThis.timerStart)) * 100);
1791 aThis.timer.setAttribute('value', value);
1792 }
1793 },
1794 timerStart : 0,
1795 timerEnd : 0,
1796 timerTimer : null
1797
1798 };
1799
1800
1801
1802
1803
1804 var StrokeService = {
1805 className : 'stroke-dot',
1806 dragStartDelta : 8,
1807 lineColor : 'red',
1808 lineWidth : 3,
1809
1810 initialized : false,
1811
1812
1813 mode : null,
1814 canvas : null,
1815 canvasContext : null,
1816 startX : -1,
1817 startY : -1,
1818
1819 init : function(aCanvas)
1820 {
1821 this.initialized = true;
1822
1823 this.canvas = aCanvas;
1824
1825 var canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
1826 this.canvas.appendChild(canvas);
1827 if (!('getContext' in canvas) || !canvas.getContext) {
1828 this.canvas.removeChild(canvas);
1829 this.mode = 'box';
1830 }
1831 else {
1832 this.canvas = canvas;
1833 this.canvasContext = this.canvas.getContext('2d');
1834 this.mode = 'canvas';
1835 }
1836
1837 document.documentElement.addEventListener('PresentationRedraw', this, false);
1838 window.addEventListener('resize', this, false);
1839 this.canvas.addEventListener('mouseup', this, false);
1840 this.canvas.addEventListener('mousedown', this, false);
1841 this.canvas.addEventListener('mousemove', this, false);
1842
1843 this.canvas.addEventListener('click', this, false);
1844 this.canvas.addEventListener('dblclick', this, false);
1845
1846 this.clear();
1847 },
1848
1849 destroy : function()
1850 {
1851 document.documentElement.removeEventListener('PresentationRedraw', this, false);
1852 window.removeEventListener('resize', this, false);
1853 this.canvas.removeEventListener('mouseup', this, false);
1854 this.canvas.removeEventListener('mousedown', this, false);
1855 this.canvas.removeEventListener('mousemove', this, false);
1856 this.canvas.removeEventListener('click', this, false);
1857
1858 this.cliclableNodesManager = null;
1859 this.canvas = null;
1860
1861 this.initialized = false;
1862 },
1863
1864
1865
1866 handleEvent : function(aEvent)
1867 {
1868 switch(aEvent.type)
1869 {
1870 default:
1871 break;
1872
1873 case 'mouseup':
1874 this.finish(aEvent);
1875 this.startX = -1;
1876 this.startY = -1;
1877 window.setTimeout('StrokeService.preventToSendClickEvent = false', 10);
1878 break;
1879
1880 case 'mousedown':
1881 if (this.startX < 0) {
1882 this.startX = aEvent.clientX;
1883 this.startY = aEvent.clientY;
1884 }
1885 break;
1886
1887 case 'mousemove':
1888 if (this.startX > -1 && !this.active) {
1889 if (Math.abs(this.startX-aEvent.clientX) > Math.abs(this.dragStartDelta) ||
1890 Math.abs(this.startY-aEvent.clientY) > Math.abs(this.dragStartDelta)) {
1891 this.start(aEvent, this.startX, this.startY);
1892 this.preventToSendClickEvent = true;
1893 }
1894 }
1895 else
1896 this.trace(aEvent);
1897
1898 break;
1899
1900 case 'PresentationRedraw':
1901 case 'resize':
1902 this.clear();
1903 break;
1904
1905 case 'click':
1906 if (this.preventToSendClickEvent) {
1907 aEvent.stopPropagation();
1908 aEvent.preventCapture();
1909 aEvent.preventDefault();
1910 aEvent.preventBubble();
1911 this.preventToSendClickEvent = false;
1912 }
1913 else if (this.cliclableNodesManager && this.cliclableNodesManager.clickableNodes) {
1914 var nodes = this.cliclableNodesManager.clickableNodes;
1915 var max = nodes.length;
1916 var x, y, width, height
1917 for (var i = 0; i < max; i++)
1918 {
1919 if (nodes[i].boxObject) {
1920 x = nodes[i].boxObject.x;
1921 y = nodes[i].boxObject.y;
1922 width = nodes[i].boxObject.width;
1923 height = nodes[i].boxObject.height;
1924 }
1925 else {
1926 x = nodes[i].offsetLeft;
1927 y = nodes[i].offsetTop;
1928 width = nodes[i].offsetWidth;
1929 height = nodes[i].offsetHeight;
1930 }
1931 if (aEvent.clientX < x ||
1932 aEvent.clientX > x+width ||
1933 aEvent.clientY < y ||
1934 aEvent.clientY > y+height)
1935 continue;
1936
1937 var event = document.createEvent('MouseEvents');
1938 event.initMouseEvent(
1939 aEvent.type, aEvent.canBubble, aEvent.cancelable, aEvent.view,
1940 aEvent.detail,
1941 aEvent.screenX, aEvent.screenY, aEvent.clientX, aEvent.clientY,
1942 aEvent.ctrlKey, aEvent.altKey, aEvent.shiftKey, aEvent.metaKey,
1943 aEvent.button,
1944 aEvent.relatedTarget
1945 );
1946 nodes[i].dispatchEvent(event);
1947 break;
1948 }
1949 }
1950 break;
1951 }
1952 },
1953 preventToSendClickEvent : false,
1954
1955
1956
1957 start : function(aEvent, aX, aY)
1958 {
1959 this.active = true;
1960 this.trace(aEvent, aX, aY);
1961 },
1962
1963 finish : function(aEvent)
1964 {
1965 if (!this.active) return;
1966 this.trace(aEvent);
1967 this.finishStroke();
1968 },
1969
1970 trace : function(aEvent, aX, aY)
1971 {
1972 if (!this.active) return;
1973 this.addPoint((aX === void(0) ? aEvent.clientX : aX ), (aY === void(0) ? aEvent.clientY : aY ));
1974 },
1975
1976
1977 finishStroke : function()
1978 {
1979 this.active = false;
1980 this.lastX = -1;
1981 this.lastY = -1;
1982 },
1983
1984
1985 addPoint : function(aX, aY)
1986 {
1987 if (this.lastX != -1)
1988 this.drawLine(this.lastX, this.lastY, aX, aY);
1989 else
1990 this.drawDot(aX, aY);
1991
1992 this.lastX = aX;
1993 this.lastY = aY;
1994 },
1995
1996
1997
1998 clear : function()
1999 {
2000 this.active = false;
2001 this.lastX = -1;
2002 this.lastY = -1;
2003
2004 if (this.mode == 'canvas') {
2005 if (this.canvas.lastWindowWidth != window.innerWidth ||
2006 this.canvas.lastWindowHeight != window.innerHeight) {
2007 this.canvas.width = this.canvas.parentNode.boxObject.width-2;
2008 this.canvas.height = this.canvas.parentNode.boxObject.height-2;
2009
2010 this.canvas.lastWindowWidth = window.innerWidth;
2011 this.canvas.lastWindowHeight = window.innerHeight;
2012 }
2013 this.canvasContext.clearRect(0, 0, this.canvas.width, this.canvas.height);
2014 this.canvasContext.strokeStyle = this.lineColor;
2015 this.canvasContext.lineWidth = this.lineWidth;
2016 }
2017 else {
2018 var dotes = this.canvas.getElementsByAttribute('class', this.className);
2019 if (!dotes.length) return;
2020
2021 var range = document.createRange();
2022 range.selectNodeContents(this.canvas);
2023 range.setStartBefore(dotes[0]);
2024 range.setEndAfter(dotes[dotes.length-1]);
2025 range.deleteContents();
2026 range.detach();
2027 }
2028 },
2029
2030 drawDot : function(aX, aY, aParent)
2031 {
2032 if (this.mode == 'canvas') {
2033 this.canvasContext.strokeRect(aX, aY, 0, 0);
2034 this.canvasContext.stroke();
2035 }
2036 else {
2037 var dot = document.createElement('spacer');
2038 dot.setAttribute('style', 'left:'+aX+'px; top:'+aY+'px');
2039 dot.setAttribute('class', this.className);
2040 (aParent || this.canvas).appendChild(dot);
2041 }
2042 },
2043 drawLine : function(aX1, aY1, aX2, aY2)
2044 {
2045 if (aX1 == aX2 && aY1 == aY2) return;
2046
2047
2048 if (this.mode == 'canvas') {
2049 this.canvasContext.beginPath();
2050 this.canvasContext.moveTo(aX1, aY1);
2051 this.canvasContext.lineTo(aX2, aY2);
2052 /*
2053 this.canvasContext.bezierCurveTo(
2054 parseInt(aX1+((aX2-this.lastX)*0.3)), parseInt(aY1+((aY2-this.lastY)*0.3)),
2055 parseInt(aX1+((aX2-this.lastX)*0.6)), parseInt(aY1+((aY2-this.lastY)*0.6)),
2056 aX2, aY2
2057 );
2058 */
2059 this.canvasContext.closePath();
2060 this.canvasContext.stroke();
2061 }
2062 else {
2063 var x_move = aX2 - aX1;
2064 var y_move = aY2 - aY1;
2065 var x_diff = x_move < 0 ? 1 : -1;
2066 var y_diff = y_move < 0 ? 1 : -1;
2067
2068 var fragment = document.createDocumentFragment();
2069 if (Math.abs(x_move) >= Math.abs(y_move)) {
2070 for (var i = x_move; i != 0; i += x_diff)
2071 this.drawDot(aX2 - i, aY2 - Math.round(y_move * i / x_move), fragment);
2072 }
2073 else {
2074 for (var i = y_move; i != 0; i += y_diff)
2075 this.drawDot(aX2 - Math.round(x_move * i / y_move), aY2 - i, fragment);
2076 }
2077 this.canvas.appendChild(fragment);
2078 }
2079 }
2080 };
2081
2082
2083
2084
2085
2086 var StrokablePresentationService = {
2087
2088 id : 'stroke-canvas-box',
2089
2090 strokeService : null,
2091 cliclableNodesManager : null,
2092 canvasContainer : null,
2093 canvas : null,
2094
2095 autoStart : false,
2096
2097 init : function(aPresentation, aStrokeService)
2098 {
2099 this.cliclableNodesManager = aPresentation;
2100 this.strokeService = aStrokeService;
2101 this.canvasContainer = document.getElementById('canvas').firstChild;
2102 this.check = document.getElementById('penButton');
2103
2104 document.documentElement.addEventListener('StartDragOnCanvas', this, false);
2105 document.documentElement.addEventListener('PresentationRedraw', this, false);
2106 },
2107
2108 toggle : function(aEnable)
2109 {
2110 if (aEnable)
2111 this.start();
2112 else
2113 this.end();
2114 },
2115
2116 start : function()
2117 {
2118 if (!this.strokeService || !this.canvasContainer) return;
2119
2120 this.strokeService.cliclableNodesManager = this.cliclableNodesManager;
2121 var box = document.createElement('vbox');
2122 box.setAttribute('flex', 1);
2123 box.setAttribute('id', this.id);
2124 this.canvas = this.canvasContainer.appendChild(box);
2125 this.strokeService.init(this.canvas);
2126
2127 this.canvas.addEventListener('dblclick', this, false);
2128 },
2129
2130 end : function()
2131 {
2132 this.canvas.removeEventListener('dblclick', this, false);
2133
2134 this.strokeService.destroy();
2135 this.canvasContainer.removeChild(this.canvas);
2136 this.canvas = null;
2137 },
2138
2139 handleEvent : function(aEvent)
2140 {
2141 switch (aEvent.type)
2142 {
2143 default:
2144 break;
2145
2146 case 'StartDragOnCanvas':
2147 if (!this.check.checked) {
2148 this.toggleCheck();
2149 this.strokeService.startX = Presentation.dragStartX;
2150 this.strokeService.startY = Presentation.dragStartY;
2151
2152 this.autoStart = true;
2153 }
2154 break;
2155
2156 case 'PresentationRedraw':
2157 if (this.autoStart && this.check.checked) {
2158 this.autoStart = false;
2159 this.toggleCheck();
2160 }
2161 break;
2162
2163 case 'dblclick':
2164 if (this.canvas)
2165 this.end();
2166 break;
2167 }
2168 },
2169
2170 toggleCheck : function()
2171 {
2172 var enable = !this.check.checked;
2173 this.toggle(enable);
2174 this.check.checked = enable;
2175
2176 this.autoStart = false;
2177 }
2178
2179 };
2180
2181
2182
2183
2184 function init()
2185 {
2186 window.removeEventListener('load', init, false);
2187
2188 Presentation.init();
2189 StrokablePresentationService.init(Presentation, StrokeService);
2190 }
2191 window.addEventListener('load', init, false);
2192
2193
2194 ]]></script>
2195
2196 </page>

Properties

Name Value
svn:eol-style CRLF

  ViewVC Help
Powered by ViewVC 1.1.26