Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
2052 lines (1786 sloc) 50.7 KB
<?xml version="1.0" encoding="UTF-8"?>
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is the Takahashi-Method-based Presentation Tool
- in XUL/Returns.
-
- The Initial Developer of the Original Code is SHIMODA Hiroshi.
- Portions created by the Initial Developer are Copyright (C) 2005
- the Initial Developer. All Rights Reserved.
-
- Contributor(s): SHIMODA Hiroshi <piro@p.club.ne.jp>
- dynamis <dynamis@mozilla-japan.org>
- matobaa <matobaa@lily.freemail.ne.jp>
-
- ***** END LICENSE BLOCK ***** -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!--<?xml-stylesheet href="./slideshow.css" type="text/css"?>-->
<?xml-stylesheet href="./takahashi.css" type="text/css"?>
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
id="presentation"
xmlns:html="http://www.w3.org/1999/xhtml"
orient="vertical"
onkeypress="Presentation.onKeyPress(event);">
<html:textarea id="builtinCode" style="visibility: collapse">
TITLE::Emacs + Perl
Emacs
----
Perl
----
two great things
that go great
together
----
[[image src="images/vi-emacs.png" width="640" height="355"]]
----
[[EM:OK:EM]]
let's focus on
Emacs
----
Some Background
----
Old
(started in 1976)
----
Has the
whipupitude
nature
----
Started life
as a set of macros
for another editor
----
Editor Macros
&#8595;
Emacs
----
Predates:
SVR0
BSD
SunOS
GNU/Linux
----
One of the
first
"windowing"
systems
----
Comes in both
GUI &amp; console
flavors
----
(XEmacs has nothing
to do with X Windows)
----
Multiple forks &amp; flavors
----
GNU Emacs
----
GNU Emacs
XEmacs
----
GNU Emacs
XEmacs
SXEmacs
----
GNU Emacs
XEmacs
SXEmacs
VILE
----
GNU Emacs
XEmacs
SXEmacs
VILE
MicroEMACS
----
GNU Emacs
XEmacs
SXEmacs
VILE
MicroEMACS
...
----
Stuff you can do
with Emacs
----
Edit text
----
Edit text
with
syntax highlighting
----
Compile code
----
"Compile"
can mean
"syntax check"
----
Chat on IRC
(multiple clients)
----
Send email
----
Read email
(multiple clients)
----
Read and post
to Usenet
----
Read and post
to Twitter
----
Read and post
to Identi.ca
----
Read and post
to Facebook
----
Browse the web
----
Run your REPL
----
Be psychoanalyzed
----
Interact with a debugger
----
Manage files
----
Play tetris
----
Debug code
running on a
remote server
----
Run as a daemon
----
Context-aware
input completion
(aka "Intellisense")
----
Integrate with
CVS
----
Integrate with
SVN
----
Integrate with
Perforce
----
Integrate with
git
----
Integrate with
darcs
----
Integrate with
Hg
----
Integrate with
your oddball RCS
of choice
----
Spell check
with ispell
----
Spell check
with aspell
----
Drive
grep
----
Drive
ack
----
Drive
make
----
Drive
$RANDOM_OTHER_PROGRAM
that outputs parsable
line numbers
----
Talk to your RDBMS
----
Keep your
diary
----
Keep your
calendar
----
Plan your
day
----
Plan your
week
----
Plan your
life
----
(Google org-mode
for lots more)
----
Write
outlines
----
Create
presentationss
----
Present
presentations
----
Edit files
on remote hosts
----
Edit files
as root
----
Edit files
on remote hosts
as root
----
(You still need
the passwords.)
----
Emulate
vi
----
Emulate
vim
----
[[EM:Run:EM]]
vim
----
Edit text
[[EM:like a mofo:EM]]
----
Getting it
----
Download it
----
http://www.emacswiki.org/emacs/CategoryPorts
----
http://www.emacswiki.org
click on 'Ports'
----
Build it
----
In *nix-ish
[[PRE:
./configure --prefix=/my/emacs-23.1
make
make install
:PRE]]
----
In Mac-ish
[[PRE:
./configure --with-ns
make
make install
open nextstep
:PRE]]
Emacs.app
&#8595;
Applications
----
Run at least
Emacs 23.1
----
"Pretest" alphas
have been very stable
(for me; YMMV)
----
[[EM:Full disclosure::EM]]
my emacs blew up
right after typing that
----
It's [[EM:alpha!:EM]]
----
Looks
----
out of the box:
[[image src="images/1.png" width="640" height="480"]]
----
my fresh emacs
[[image src="images/2.png" width="640" height="480"]]
----
(i'm sort of a
boring guy,
visually.)
----
Config
----
Startup file:
[[PRE:~/.emacs.d/init.el:PRE]]
----
The file
formerly
known as:
[[PRE:~/.emacs:PRE]]
----
Booster pack:
emacs starter kit
http://github.com/technomancy/emacs-starter-kit
----
emacs starter kit
[[PRE:
All the code you need to get started,
with an emphasis on dynamic languages.
:PRE]]
----
needs some Perl love
----
Paradox:
Need to be somewhat expert to help
By the time you're expert you want your own config
----
One thing you [[EM:must:EM]] do:
[[PRE:
(defalias 'perl-mode 'cperl-mode)
:PRE]]
----
Notable Perl-specific add-ons
----
jrock's cperl-mode
(Moosey!)
----
[[PRE:Stylish::REPL:PRE]]
(link down ATM)
&#x2639;
----
[[PRE:perl-find-library.el:PRE]]
----
[[PRE:pod-mode.el:PRE]]
----
[[PRE:prove.el:PRE]]
----
[[PRE:tt-mode.el:PRE]]
----
[[PRE:perlcritic.el:PRE]]
----
[[PRE:perltidy.el:PRE]]
----
[[PRE:flymake:PRE]]
----
[[PRE:Devel::PerlySense:PRE]]
----
My Emacs config
[[PRE:http://github.com/genehack/emacs:PRE]]
(including third party libs and apps)
----
Non-perl
functions of note
----
nxml
RELAX NG
[[EM:continuous:EM]] validation
----
macros
----
magit
----
dired
----
"Inferior" shells
----
I-do mode
----
Session support
----
YAsnippet
----
color-theme
----
browse-kill-ring
----
css-mode
----
the list goes on...
----
Questions?
john sj anderson
@genehack
----
&#x270C; &#x263A;
----
</html:textarea>
<deck flex="1" id="deck">
<vbox flex="1"
onmouseup="Presentation.handleEvent(event);"
onmousedown="Presentation.handleEvent(event);"
onmousemove="Presentation.handleEvent(event);">
<toolbox id="canvasToolbar">
<toolbar>
<toolbarbutton oncommand="Presentation.home()" label="|&lt;&lt;"
observes="canBack"/>
<toolbarbutton oncommand="Presentation.back()" label="&lt;"
observes="canBack"/>
<toolbarbutton oncommand="Presentation.forward()" label="&gt;"
observes="canForward"/>
<toolbarbutton oncommand="Presentation.end()" label="&gt;&gt;|"
observes="canForward"/>
<toolbarseparator/>
<hbox align="center">
<textbox id="current_page" size="4"
oninput="if (this.value) Presentation.showPage(parseInt(this.value)-1);"/>
<toolbarbutton id="pages-list-button"
type="menu"
label="Select Page"
tooltiptext="Select Page"
class="dropmarker-button">
<menupopup id="pages-list"
onpopupshowing="if (event.target == this) Presentation.preventToShowHideToolbar = true;"
onpopuphiding="if (event.target == this) Presentation.preventToShowHideToolbar = false;"
oncommand="Presentation.showPage(parseInt(event.target.value));"/>
</toolbarbutton>
<description value="/"/>
<description id="max_page"/>
</hbox>
<toolbarseparator/>
<vbox flex="2">
<spacer flex="1"/>
<scrollbar id="scroller"
align="center" orient="horizontal"
oncommand="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));"
onclick="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));"
onmousedown="Presentation.onScrollerDragStart();"
onmousemove="Presentation.onScrollerDragMove();"
onmouseup="Presentation.onScrollerDragDrop();"/>
<spacer flex="1"/>
</vbox>
<toolbarseparator/>
<spacer flex="1"/>
<hbox>
<toolbarbutton label="auto"
id="autoButton"
type="checkbox"
autoCheck="false"
oncommand="Presentation.toggleAutoCruiseMode();" />
<toolbarbutton id="auto-interval-button"
type="menu"
label="Interval"
tooltiptext="Change Interval"
class="dropmarker-button">
<menupopup id="auto-interval-list"
onpopupshowing="
Presentation.preventToShowHideToolbar = true;
(this.getElementsByAttribute('value', Presentation.autoCruiseInterval)[0] || this.lastChild).setAttribute('checked', true);
"
onpopuphiding="Presentation.preventToShowHideToolbar = false;"
oncommand="Presentation.changeAutoCruiseInterval(parseInt(event.target.value));">
<menuitem type="radio" radiogroup="autocruise-interval"
label="1 sec" value="1000"/>
<menuitem type="radio" radiogroup="autocruise-interval"
label="2 sec" value="2000"/>
<menuitem type="radio" radiogroup="autocruise-interval"
label="3 sec" value="3000"/>
<menuitem type="radio" radiogroup="autocruise-interval"
label="4 sec" value="4000"/>
<menuitem type="radio" radiogroup="autocruise-interval"
label="5 sec" value="5000"/>
<menuseparator/>
<menuitem type="radio" radiogroup="autocruise-interval"
label="1 min" value="60000"/>
<menuitem type="radio" radiogroup="autocruise-interval"
label="2 min" value="120000"/>
<menuitem type="radio" radiogroup="autocruise-interval"
label="3 min" value="180000"/>
<menuitem type="radio" radiogroup="autocruise-interval"
label="4 min" value="240000"/>
<menuitem type="radio" radiogroup="autocruise-interval"
label="5 min" value="300000"/>
<menuseparator/>
<menuitem type="radio" radiogroup="autocruise-interval"
label="Custom"
oncommand="
var current = Presentation.autoCruiseInterval;
var val = parseInt(prompt('input interval (sec)', parseInt(current/1000)));
if (isNaN(val)) {
event.preventBubble();
return;
}
else
val = val * 1000;
this.value = val;
"/>
</menupopup>
</toolbarbutton>
</hbox>
<toolbarbutton label="Pen"
id="penButton"
type="checkbox"
autoCheck="false"
oncommand="StrokablePresentationService.toggleCheck();"/>
<toolbarseparator/>
<toolbarbutton id="toggleEva" label="Eva"
type="checkbox"
autoCheck="false"
oncommand="Presentation.toggleEvaMode();"/>
<toolbarseparator/>
<toolbarbutton label="Edit"
oncommand="Presentation.toggleEditMode();"/>
<toolbarbutton oncommand="Presentation.reload();" label="Reload"/>
</toolbar>
</toolbox>
<vbox flex="1" id="canvas">
<stack flex="1">
<vbox flex="1">
<hbox id="headerBox" flex="1">
<label id="header"/>
<spacer flex="1"/>
<vbox>
<image id="logo"/>
<spacer flex="1"/>
</vbox>
</hbox>
<spacer flex="19"/>
<hbox id="footerBox" flex="1">
<spacer flex="1"/>
<label id="footer"/>
</hbox>
</vbox>
<vbox flex="1"
onclick="Presentation.onPresentationClick(event);">
<spacer flex="1"/>
<hbox flex="1" id="contentBox">
<spacer flex="1"/>
<vbox id="content"/>
<spacer flex="1"/>
</hbox>
<spacer flex="1"/>
</vbox>
</stack>
</vbox>
</vbox>
<vbox flex="1" id="edit">
<toolbox>
<toolbar>
<menubar flex="1">
<menu label="File">
<menupopup>
<menuitem label="Save"
key="key_save"
oncommand="Presentation.output()"/>
<menuitem label="Reload"
key="key_reload"
oncommand="Presentation.reload()"/>
</menupopup>
</menu>
<menu label="Insert">
<menupopup>
<menuitem label="New Page"
key="key_insert_newpage"
oncommand="Presentation.insert('page')"/>
<menuseparator/>
<menuitem label="Header"
oncommand="Presentation.insert('header')"/>
<menuitem label="Footer"
oncommand="Presentation.insert('footer')"/>
<menuseparator/>
<menuitem label="Link"
oncommand="Presentation.insert('link')"/>
<menuitem label="Emphasis"
oncommand="Presentation.insert('em')"/>
<menuitem label="Preformatted"
oncommand="Presentation.insert('pre')"/>
<menuitem label="Monta"
oncommand="Presentation.insert('monta')"/>
<menuitem label="Image"
oncommand="Presentation.insert('img')"/>
</menupopup>
</menu>
</menubar>
<toolbarseparator/>
<toolbarbutton label="View"
oncommand="Presentation.toggleEditMode();"/>
<toolbarbutton oncommand="Presentation.reload();" label="Reload"/>
</toolbar>
</toolbox>
<textbox id="textField" flex="1" multiline="true"
oninput="Presentation.onEdit()"/>
</vbox>
</deck>
<broadcasterset>
<broadcaster id="canBack"/>
<broadcaster id="canForward"/>
</broadcasterset>
<commandset>
<command id="cmd_forward"
oncommand="if (Presentation.isPresentationMode) Presentation.forward();"/>
<command id="cmd_forwardStep"
oncommand="if (Presentation.isPresentationMode) Presentation.forwardStep();"/>
<command id="cmd_back"
oncommand="if (Presentation.isPresentationMode) Presentation.back();"/>
<command id="cmd_home"
oncommand="if (Presentation.isPresentationMode) Presentation.home();"/>
<command id="cmd_end"
oncommand="if (Presentation.isPresentationMode) Presentation.end();"/>
</commandset>
<keyset>
<key keycode="VK_ENTER" command="cmd_forwardStep"/>
<key keycode="VK_RETURN" command="cmd_forwardStep"/>
<key keycode="SPACE" command="cmd_forwardStep"/>
<key keycode="VK_PAGE_DOWN" command="cmd_forwardStep"/>
<key keycode="VK_RIGHT" command="cmd_forwardStep"/>
<key keycode="VK_DOWN" command="cmd_forwardStep"/>
<!--key keycode="VK_BACK_SPACE" command="cmd_back"/-->
<key keycode="VK_PAGE_UP" command="cmd_back"/>
<key keycode="VK_UP" command="cmd_back"/>
<key keycode="VK_LEFT" command="cmd_back"/>
<key keycode="VK_HOME" command="cmd_home"/>
<key keycode="VK_END" command="cmd_end"/>
<key id="key_insert_newpage"
key="n" modifiers="accel" oncommand="Presentation.insert('page');"/>
<key id="key_save"
key="s" modifiers="accel" oncommand="Presentation.output();"/>
<key id="key_reload"
key="r" modifiers="accel" oncommand="Presentation.reload();"/>
<key key="e" modifiers="accel" oncommand="Presentation.toggleEditMode();"/>
<key key="e" modifiers="accel,shift" oncommand="Presentation.toggleEvaMode();"/>
</keyset>
<script type="application/x-javascript"><![CDATA[
var Presentation = {
size : 9,
montaLabelImage : 'monta-label.png',
dragStartDelta : 8,
initialized : false,
preventToShowHideToolbar : false,
showMontaKeywordTimeout : 100,
autoCruiseInterval : 2000,
standByMontaLabels : [],
shownMontaLabels : [],
init : function(option){
if (this.initialized) {
this.startPresentation();
return;
}
this.initialized = true;
this._offset = 0;
this.canvas = document.getElementById('canvas');
this.content = document.getElementById('content');
this.header = document.getElementById('header');
this.footer = document.getElementById('footer');
this.logo = document.getElementById('logo');
this.list = document.getElementById('pages-list');
this.textbox = document.getElementById('textField');
this.deck = document.getElementById('deck');
this.scroller = document.getElementById('scroller');
this.toolbar = document.getElementById('canvasToolbar');
this.toolbarHeight = this.toolbar.boxObject.height;
this.isToolbarHidden = true;
this.toolbar.setAttribute('style', 'margin-top:'+(0-this.toolbarHeight)+'px;margin-bottom:0px;');
this.preloadImage(this.montaLabelImage);
window.addEventListener('resize', this, false);
window.addEventListener('contextmenu', this, false);
if(option){
for(var i in option){this[i] = option[i]}
}
if (this.readParameter()) {
this.startPresentation();
}
document.documentElement.focus();
},
startPresentation : function()
{
if (this.data.length)
document.title = this.data[0].title || this.data[0].header || this.data[0].text.join(' ');
this.takahashi();
},
takahashi : function() {
if(!this.data[this.offset]){
this.offset = this.data.length-1;
}
document.getElementById("current_page").value = this.offset+1;
document.getElementById("max_page").value = this.data.length;
this.scroller.setAttribute('maxpos', this.data.length-1);
this.scroller.setAttribute('curpos', this.offset);
var broadcaster = document.getElementById('canBack');
if (!this.offset)
broadcaster.setAttribute('disabled', true);
else
broadcaster.removeAttribute('disabled');
var broadcaster = document.getElementById('canForward');
if (this.offset == this.data.length-1)
broadcaster.setAttribute('disabled', true);
else
broadcaster.removeAttribute('disabled');
this.canvas.setAttribute('rendering', true);
this.header.removeAttribute('style');
this.footer.removeAttribute('style');
this.content.removeAttribute('style');
this.standByMontaLabels = [];
this.clickableNodes = [];
if ('title' in this.data[this.offset])
document.title = this.data[this.offset].title;
this.header.setAttribute('style', 'font-size:10px;');
this.header.value = this.data[this.offset].header;
this.footer.setAttribute('style', 'font-size:10px;');
this.footer.value = this.data[this.offset].footer;
var text = this.data[this.offset].text;
var range = document.createRange();
range.selectNodeContents(this.content);
range.deleteContents();
range.detach();
var line;
var newLine;
var uri;
var image_width;
var image_total_width = 0;
var image_height;
var image_total_height = 0;
var image_src;
var labelId = 0;
var lineRegExp = /^([^\[]+)?(\[\[em:(.+?):em\]\]|\[\[pre:((.+?):pre\]\])?|\[\[ima?ge? +src="([^"]+)"\]\]|\[\[(([^\|]+)?\||)([^\]]+)\]\]|\[([^\]]+)\])(.+)?/i;
var emRegExp = /^([^\[]+)?\[\[em:(.+?):em\]\]/i;
var preRegExp = /^([^\[]+)?\[\[pre:(.+?):pre\]\]/i;
var preStartRegExp = /^([^\[]+)?\[\[pre:(.*)/i;
var preEndRegExp = /^(.*?)(:pre\]\])/i;
var imagesRegExp = /^([^\[]+)?\[\[ima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^\]]*\]\]/i;
var fullImagesRegExp = /^([^\[]+)?\[\[ima?ge? +src="([^"]+)"\]\]/i;
var linksRegExp = /^([^\[]+)?\[\[(([^\|]+)?\||)([^\]]+)\]\]/;
var montaRegExp = /^([^\[]+)?\[([^\]]+)\]/;
var inPreBlock = false;
var preContents = [];
var i,
max = text.length;
var fragment = document.createDocumentFragment();
for (i = 0; i < max; i++)
{
fragment.appendChild(document.createElement('hbox'));
fragment.lastChild.setAttribute('align', 'center');
fragment.lastChild.setAttribute('pack', 'center');
line = text[i];
image_width = 0;
image_height = 0;
if (inPreBlock) {
if (preEndRegExp.test(line)) {
inPreBlock = false;
preContents.push(RegExp.$1);
line = line.substring((RegExp.$1+RegExp.$2).length);
fragment.lastChild.appendChild(document.createElement('description'));
fragment.lastChild.lastChild.setAttribute('class', 'preformatted-text block');
fragment.lastChild.lastChild.appendChild(document.createTextNode(
preContents.join('\n')
.replace(/^[\r\n\s]+/, '')
.replace(/[\r\n\s]+$/, '')
.replace(/&amp;/g, '&')
.replace(/&quot;/g, '"')
.replace(/&gt;/g, '>')
.replace(/&lt;/g, '<')
));
}
else {
preContents.push(line);
continue;
}
}
while (line.match(lineRegExp))
{
if (RegExp.$1) {
fragment.lastChild.appendChild(document.createElement('description'));
fragment.lastChild.lastChild.setAttribute('value', RegExp.$1);
}
newLine = line.substring((RegExp.$1+RegExp.$2).length);
// Preformatted Text
if (preRegExp.test(line)) {
fragment.lastChild.appendChild(document.createElement('description'));
fragment.lastChild.lastChild.setAttribute('value', RegExp.$2);
fragment.lastChild.lastChild.setAttribute('class', 'preformatted-text');
}
else if (preStartRegExp.test(line)) {
inPreBlock = true;
preContents = [RegExp.$2];
newLine = '';
}
// Emphasis
else if (emRegExp.test(line)) {
fragment.lastChild.appendChild(document.createElement('description'));
fragment.lastChild.lastChild.setAttribute('value', RegExp.$2);
fragment.lastChild.lastChild.setAttribute('class', 'em-text');
}
// Images
else if (imagesRegExp.test(line)) {
fragment.lastChild.appendChild(document.createElement('image'));
image_src = RegExp.$2;
if (image_src.indexOf('http://') < 0 &&
image_src.indexOf('https://') < 0)
image_src = this.dataFolder+image_src;
fragment.lastChild.lastChild.setAttribute('src', image_src);
fragment.lastChild.lastChild.setAttribute('width', parseInt(RegExp.$3 || '0'));
fragment.lastChild.lastChild.setAttribute('height', parseInt(RegExp.$4 || '0'));
image_width += parseInt(RegExp.$3 || '0');
image_height = Math.max(image_height, parseInt(RegExp.$4 || '0'));
}
// Full Size Images
else if (fullImagesRegExp.test(line)) {
fragment.lastChild.appendChild(document.createElement('image'));
image_src = RegExp.$2;
if (image_src.indexOf('http://') < 0 &&
image_src.indexOf('https://') < 0)
image_src = this.dataFolder+image_src;
fragment.lastChild.lastChild.setAttribute('src', image_src);
fragment.lastChild.lastChild.setAttribute('flex', '100');
fragment.lastChild.lastChild.setAttribute('width', window.innerWidth);
fragment.lastChild.lastChild.setAttribute('height', window.innerHeight);
}
// Links
else if (linksRegExp.test(line)) {
uri = RegExp.$4;
if (uri.indexOf('://') < 0)
uri = this.dataFolder+uri;
fragment.lastChild.appendChild(document.createElement('description'));
fragment.lastChild.lastChild.setAttribute('value', RegExp.$3 || RegExp.$4);
fragment.lastChild.lastChild.setAttribute('href', uri);
fragment.lastChild.lastChild.setAttribute('tooltiptext', uri);
fragment.lastChild.lastChild.setAttribute('statustext', uri);
fragment.lastChild.lastChild.setAttribute('class', 'link-text');
this.clickableNodes.push(fragment.lastChild.lastChild);
}
// Monta
else if (montaRegExp.test(line)) {
fragment.lastChild.appendChild(document.createElement('stack'));
fragment.lastChild.lastChild.appendChild(document.createElement('description'));
fragment.lastChild.lastChild.lastChild.setAttribute('value', RegExp.$2);
fragment.lastChild.lastChild.lastChild.setAttribute('class', 'monta-text');
fragment.lastChild.lastChild.appendChild(document.createElement('spacer'));
fragment.lastChild.lastChild.lastChild.setAttribute('flex', 1);
fragment.lastChild.lastChild.lastChild.setAttribute('class', 'monta-label');
fragment.lastChild.lastChild.lastChild.setAttribute('label-id', 'label-' + (++labelId));
if (!this.shownMontaLabels[this.offset] || !this.shownMontaLabels[this.offset]['label-'+labelId]) {
fragment.lastChild.lastChild.lastChild.setAttribute('monta-hidden', 'true');
this.standByMontaLabels[this.standByMontaLabels.length] = fragment.lastChild.lastChild.lastChild;
}
else {
fragment.lastChild.lastChild.lastChild.setAttribute('monta-hidden', 'false');
}
this.clickableNodes.push(fragment.lastChild.lastChild.lastChild);
}
line = newLine;
}
if (line) {
fragment.lastChild.appendChild(document.createElement('description'));
fragment.lastChild.lastChild.setAttribute('value', line);
}
image_total_width = Math.max(image_total_width, image_width);
image_total_height += image_height;
}
this.content.setAttribute('style', 'font-size:10px;');
this.content.appendChild(fragment);
this.clickableNodes.push(this.content);
this.fitToCanvas(this.header, this.header.parentNode, 0, 0);
this.fitToCanvas(this.footer, this.footer.parentNode, 0, 0);
this.fitToCanvas(
this.content,
this.canvas,
image_total_width,
image_total_height
+(this.header.boxObject.height*2)
// +(this.footer.boxObject.height*2)
);
var checkedItems = this.list.getElementsByAttribute('checked', 'true');
max = checkedItems.length;
for (i = 0; i < max; i++)
checkedItems[i].removeAttribute('checked');
this.list.getElementsByAttribute('value', this.offset)[0].setAttribute('checked', true);
this.canvas.removeAttribute('rendering');
this.setHash('page', 'page'+(this.offset+1));
var event = document.createEvent('Events');
event.initEvent('PresentationRedraw', false, true);
this.canvas.dispatchEvent(event);
},
fitToCanvas : function(aContent, aCanvas, aOffsetWidth, aOffsetHeight)
{
aContent.removeAttribute('style');
aContent.setAttribute('style', 'font-size:10px;');
if (!aContent.boxObject.width) return;
var canvas_w = aCanvas.boxObject.width;
var canvas_h = aCanvas.boxObject.height-aOffsetHeight;
var content_w = aContent.boxObject.width;
var new_fs = Math.round((canvas_w/content_w) * this.size);
aContent.setAttribute('style', 'font-size:'+ new_fs + "px");
if (aContent.boxObject.width < aOffsetWidth) {
content_w = aOffsetWidth;
new_fs = Math.round((canvas_w/content_w) * this.size);
aContent.setAttribute('style', 'font-size:'+ new_fs + "px");
}
var content_h = aContent.boxObject.height;
if(content_h >= canvas_h){
state='height';
content_h = aContent.boxObject.height;
new_fs = Math.round((canvas_h/content_h) * new_fs);
aContent.setAttribute('style', 'font-size:'+ new_fs + "px");
}
},
reload : function() {
var file = String(location.href).replace(/#.+$/, '');
if (this.dataPath != file) {
var path = this.dataPath;
var request = new XMLHttpRequest();
request.open('GET', path);
request.onload = function() {
Presentation.textbox.value = request.responseText;
Presentation.data = Presentation.textbox.value;
Presentation.init();
path = null;
request = null;
};
request.send(null);
}
else
window.location.reload();
},
forward : function(){
this.offset++;
this.takahashi();
},
forwardStep : function(){
if (this.standByMontaLabels.length > 0) {
while (this.standByMontaLabels.length &&
this.standByMontaLabels[0].getAttribute('monta-hidden') != 'true')
this.standByMontaLabels.splice(0, 1);
if (this.standByMontaLabels.length) {
this.showMontaKeyword(this.standByMontaLabels[0]);
this.standByMontaLabels.splice(0, 1);
}
}
else
this.forward();
},
back : function(){
this.offset--;
if(this.offset < 0){this.offset = 0}
this.takahashi();
},
home : function(){
this.offset = 0;
this.takahashi();
},
end : function(){
this.offset = this.data.length-1;
this.takahashi();
},
showPage : function(aPageOffset){
this.offset = aPageOffset ? aPageOffset : 0 ;
this.takahashi();
},
insert : function(aType) {
switch (aType)
{
case 'page':
this.insertTextFor('\n----\n', this.textbox, 6);
break;
case 'header':
this.insertTextFor('\nHEADER::\n', this.textbox, 9);
break;
case 'footer':
this.insertTextFor('\nFOOTER::\n', this.textbox, 9);
break;
case 'em':
case 'emphasis':
this.insertTextFor('[[EM::EM]]', this.textbox, 5);
break;
case 'pre':
case 'preformatted':
this.insertTextFor('[[PRE::PRE]]', this.textbox, 6);
break;
case 'monta':
this.insertTextFor('[]', this.textbox, 1);
break;
case 'link':
this.insertTextFor('[[|http://]]', this.textbox, 2);
break;
case 'img':
case 'image':
this.insertTextFor('[[image src="" width="" height=""]]', this.textbox, 13);
break;
default:
return;
}
this.onEdit();
},
insertTextFor : function(aString, aNode, aPosOffset)
{
var pos = aNode.selectionStart;
var value = aNode.value;
aNode.value = [value.substring(0, pos), aString, value.substring(pos, value.length)].join('');
aNode.selectionEnd = aNode.selectionStart = pos + (aPosOffset || 0);
},
output : function()
{
location.href = 'data:application/octet-stream,'+encodeURIComponent(this.textbox.value);
},
toggleEditMode : function(){
this.deck.selectedIndex = this.deck.selectedIndex == 0 ? 1 : 0 ;
this.setHash('edit', this.deck.selectedIndex == 0 ? '' : 'edit' );
},
toggleEvaMode : function(){
var check = document.getElementById('toggleEva');
if (this.canvas.getAttribute('eva') == 'true') {
this.canvas.removeAttribute('eva');
this.logo.removeAttribute('eva');
check.checked = false;
}
else {
this.canvas.setAttribute('eva', true);
this.logo.setAttribute('eva',true);
check.checked = true;
}
this.setHash('eva', check.checked ? 'eva' : '' );
},
toggleAutoCruiseMode : function()
{
var autoCruise = document.getElementById('autoButton');
if(!autoCruise.checked)
this.startAutoCruise();
else
autoCruise.checked = false;
},
startAutoCruise : function()
{
var autoCruise = document.getElementById('autoButton');
autoCruise.checked = true;
if (this.autoCruiseTimer) {
window.clearTimeout(this.autoCruiseTimer);
}
this.autoCruiseTimer = window.setTimeout(this.autoCruise, this.autoCruiseInterval);
},
changeAutoCruiseInterval : function(aInterval)
{
this.autoCruiseInterval = aInterval;
this.startAutoCruise();
},
autoCruise : function()
{
var autoCruise = document.getElementById('autoButton');
if (!autoCruise.checked) return;
if(Presentation.offset == Presentation.data.length-1) {
Presentation.home();
}
else {
Presentation.forwardStep();
}
Presentation.autoCruiseTimer = window.setTimeout(arguments.callee, Presentation.autoCruiseInterval);
},
autoCruiseTimer : null,
setHash : function(aKey, aValue)
{
aKey = String(aKey).toLowerCase();
var hashArray = String(location.hash).replace(/^#/, '').toLowerCase().split(',');
for (var i = hashArray.length-1; i > -1; i--)
if (!hashArray[i] || hashArray[i].indexOf(aKey) == 0)
hashArray.splice(i, 1);
if (aValue) hashArray.push(aValue);
hashArray.sort();
location.hash = hashArray.length ? hashArray.join(',') : '' ;
},
showMontaKeyword : function(aNode) {
if (aNode.getAttribute('monta-hidden') != 'true') return;
aNode.setAttribute('monta-hidden', 'progress');
window.setTimeout(this.showMontaKeywordCallback, 0, {
position : -100,
node : aNode,
interval : this.showMontaKeywordTimeout/10
});
},
showMontaKeywordCallback : function(aInfo) {
if (aInfo.position >= aInfo.node.boxObject.width) {
aInfo.node.setAttribute('monta-hidden', 'false');
if (!Presentation.shownMontaLabels[Presentation.offset])
Presentation.shownMontaLabels[Presentation.offset] = [];
Presentation.shownMontaLabels[Presentation.offset][aInfo.node.getAttribute('label-id')] = true;
return;
}
aInfo.position += (aInfo.node.boxObject.width/10);
aInfo.node.setAttribute('style', 'background-position: '+aInfo.position+'px 0 !important;');
window.setTimeout(arguments.callee, aInfo.interval, aInfo);
},
onPresentationClick : function(aEvent)
{
if (!this.isToolbarHidden)
this.showHideToolbar();
switch(aEvent.button)
{
case 0:
switch (aEvent.target.getAttribute('class'))
{
case 'link-text':
var uri = aEvent.target.getAttribute('href');
if (uri) {
window.open(uri);
return;
}
break;
case 'monta-label':
if (aEvent.target.getAttribute('monta-hidden') == 'true') {
this.showMontaKeyword(aEvent.target);
aEvent.preventBubble();
return;
}
default:
break;
}
this.forward();
document.documentElement.focus();
break;
case 2:
this.back();
document.documentElement.focus();
break;
default:
break;
}
},
onScrollerDragStart : function(){
this.scroller.dragging = true;
},
onScrollerDragMove : function(){
if (this.scroller.dragging)
this.showPage(parseInt(this.scroller.getAttribute('curpos')));
},
onScrollerDragDrop : function(){
if (this.scroller.dragging) {
this.showPage(parseInt(this.scroller.getAttribute('curpos')));
}
this.scroller.dragging = false;
},
onEdit : function() {
this.data = this.textbox.value;
this.init();
},
onKeyPress : function(aEvent) {
switch(aEvent.keyCode)
{
case aEvent.DOM_VK_BACK_SPACE:
if (this.isPresentationMode) {
aEvent.preventBubble();
aEvent.preventDefault();
Presentation.back();
}
break;
default:
break;
}
},
handleEvent : function(aEvent)
{
switch (aEvent.type)
{
default:
break;
case 'resize':
this.takahashi(); // redrwa
break;
case 'contextmenu':
aEvent.stopPropagation();
aEvent.preventCapture();
aEvent.preventDefault();
aEvent.preventBubble();
break;
case 'mouseup':
this.dragStartX = -1;
this.dragStartY = -1;
break;
case 'mousedown':
if (this.dragStartX < 0) {
this.dragStartX = aEvent.clientX;
this.dragStartY = aEvent.clientY;
}
break;
case 'mousemove':
this.checkShowHideToolbar(aEvent);
if (this.dragStartX > -1) {
if (Math.abs(this.dragStartX-aEvent.clientX) > Math.abs(this.dragStartDelta) ||
Math.abs(this.dragStartY-aEvent.clientY) > Math.abs(this.dragStartDelta)) {
var event = document.createEvent('Events');
event.initEvent('StartDragOnCanvas', false, true);
this.canvas.dispatchEvent(event);
}
}
break;
}
},
dragStartX : -1,
dragStartY : -1,
onToolbarArea : false,
toolbarHeight : 0,
toolbarDelay : 300,
toolbarTimer : null,
isToolbarHidden : false,
checkShowHideToolbar : function(aEvent) {
if (this.scroller.dragging || this.preventToShowHideToolbar) return;
this.onToolbarArea = (aEvent.clientY < this.toolbarHeight);
if (this.isToolbarHidden == this.onToolbarArea) {
if (this.toolbarTimer) window.clearTimeout(this.toolbarTimer);
this.toolbarTimer = window.setTimeout('Presentation.checkShowHideToolbarCallback()', this.toolbarDelay);
}
},
checkShowHideToolbarCallback : function() {
if (this.isToolbarHidden == this.onToolbarArea)
this.showHideToolbar();
},
toolbarAnimationDelay : 100,
toolbarAnimationSteps : 5,
toolbarAnimationInfo : null,
toolbarAnimationTimer : null,
showHideToolbar : function()
{
if (this.toolbarAnimationTimer) window.clearTimeout(this.toolbarAnimationTimer);
this.toolbarAnimationInfo = { count : 0 };
if (this.isToolbarHidden) {
this.toolbarAnimationInfo.start = 0;
this.toolbarAnimationInfo.end = this.toolbarHeight;
}
else {
this.toolbarAnimationInfo.start = this.toolbarHeight;
this.toolbarAnimationInfo.end = 0;
}
this.toolbarAnimationInfo.current = 0;
this.toolbar.setAttribute('style', 'margin-top:'+(0-(this.toolbarHeight-this.toolbarAnimationInfo.start))+'px; margin-bottom:'+(0-this.toolbarAnimationInfo.start)+'px;');
this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps);
},
animateToolbar : function()
{
this.toolbarAnimationInfo.current += parseInt(this.toolbarHeight/this.toolbarAnimationSteps);
var top, bottom;
if (this.toolbarAnimationInfo.start < this.toolbarAnimationInfo.end) {
top = this.toolbarHeight-this.toolbarAnimationInfo.current;
bottom = this.toolbarAnimationInfo.current;
}
else {
top = this.toolbarAnimationInfo.current;
bottom = this.toolbarHeight-this.toolbarAnimationInfo.current;
}
top = Math.min(Math.max(top, 0), this.toolbarHeight);
bottom = Math.min(Math.max(bottom, 0), this.toolbarHeight);
this.toolbar.setAttribute('style', 'margin-top:'+(0-top)+'px; margin-bottom:'+(0-bottom)+'px');
if (this.toolbarAnimationInfo.count < this.toolbarAnimationSteps) {
this.toolbarAnimationInfo.count++;
this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps);
}
else
this.isToolbarHidden = !this.isToolbarHidden;
},
get offset(){
return this._offset;
},
set offset(aValue){
this._offset = parseInt(aValue || 0);
document.documentElement.setAttribute('lastoffset', this.offset);
return this.offset;
},
get data(){
if (!this._data) {
// mozilla splits very long text node into multiple text nodes whose length is less than 4096 bytes.
// so, we must concat all the text nodes.
this.textbox.value = "";
for (var i = 0; i < document.getElementById('builtinCode').childNodes.length; i++) {
this.textbox.value += document.getElementById('builtinCode').childNodes[i].nodeValue;
}
this._data = this.textbox.value.split(/----+/);
this.initData();
}
return this._data;
},
set data(aValue){
this._data = aValue.split(/----+/);
this.initData();
return aValue;
},
initData : function()
{
var range = document.createRange();
range.selectNodeContents(this.list);
range.deleteContents();
var regexp = [
/^[\r\n\s]+/g,
/[\r\n\s]+$/g,
/(\r\n|[\r\n])/g
];
var title;
var titleRegExp = /\b(TITLE::)([^\n]*)\n?/i;
var header = '';
var headerRegExp = /\b(HEADER::)([^\n]*)\n?/i;
var footer = '';
var footerRegExp = /\b(FOOTER::)([^\n]*)\n?/i;
var chapter = '';
var chapterRegExp = /\b(CHAPTER::)([^\n]*)\n?/i;
var lastChapter;
var imageMatchResults;
var imagesRegExp = /\[\[ima?ge? +src="[^"]+" +width="[0-9]+" +height="[0-9]+"[^\]]*\]\]/gi;
var imagesRegExp2 = /\[\[ima?ge? +src="([^"]+)"/i;
var image_src;
var plainTextRegExp = /(\[\[EM:(.+):EM\]\]|\[\[PRE:(.+):PRE\]\]|\[\[ima?ge? +src="[^"]*"[^\]]+\]\]|\[\[([^\|\]]+)(\|[^\]]+)?\]\]|\[([^\[]+)\])/gi;
var dataObj;
var i, j,
max = this._data.length;
var fragment = document.createDocumentFragment();
var popup;
for (i = 0; i < max; i++)
{
image_src = null;
this._data[i] = this._data[i]
.replace(regexp[0], '')
.replace(regexp[1], '')
.replace(regexp[2], '\n');
this._data[i] = this._data[i].replace(titleRegExp, '')
if (String(RegExp.$1).toUpperCase() == 'TITLE::')
title = RegExp.$2 || '' ;
this._data[i] = this._data[i].replace(headerRegExp, '')
if (String(RegExp.$1).toUpperCase() == 'HEADER::')
header = RegExp.$2 || '' ;
this._data[i] = this._data[i].replace(footerRegExp, '')
if (String(RegExp.$1).toUpperCase() == 'FOOTER::')
footer = RegExp.$2 || '' ;
this._data[i] = this._data[i].replace(chapterRegExp, '')
if (String(RegExp.$1).toUpperCase() == 'CHAPTER::')
chapter = RegExp.$2 || '' ;
imageMatchResults = this._data[i].match(imagesRegExp);
if (imageMatchResults) {
for (j = imageMatchResults.length-1; j > -1; j--)
image_src = this.preloadImage(imageMatchResults[j].match(imagesRegExp2)[1]);
}
this._data[i] = {
header : header,
footer : footer,
text : this._data[i].split('\n'),
image : image_src
};
this._data[i].plain = this._data[i].text
.join('\n')
.replace(plainTextRegExp, '$2$3$4$6')
.split('\n');
if (title !== void(0))
this._data[i].title = title;
this._data[i].chapter = chapter || title || '';
if (lastChapter === void(0) ||
lastChapter != this._data[i].chapter) {
lastChapter = this._data[i].chapter;
if (popup && popup.childNodes.length == 1) {
fragment.removeChild(fragment.lastChild);
fragment.appendChild(popup.removeChild(popup.lastChild));
}
popup = document.createElement('menupopup');
fragment.appendChild(document.createElement('menu'));
fragment.lastChild.setAttribute('label', this._data[i].chapter);
fragment.lastChild.appendChild(popup);
}
popup.appendChild(document.createElement('menuitem'));
popup.lastChild.setAttribute('type', 'radio');
popup.lastChild.setAttribute('radiogroup', 'pages');
popup.lastChild.setAttribute('label', (i+1)+': '+(
(this._data[i].plain.join('') ?
this._data[i].plain.join(' ') :
this._data[i].text.join(' ')
).replace(/\s\s+/g, ' ')
));
popup.lastChild.setAttribute('value', i);
// if (image_src) {
// popup.lastChild.setAttribute('image', image_src);
// popup.lastChild.setAttribute('class', 'menuitem-iconic');
// }
}
if (fragment.childNodes.length == 1) {
range.selectNodeContents(fragment.firstChild.firstChild);
fragment = range.extractContents();
}
this.list.appendChild(fragment);
range.detach();
this.shownMontaLabels = [];
},
preloadImage : function(aURI)
{
if (aURI in this.imageRequests) return;
if (aURI.indexOf('http://') < 0 &&
aURI.indexOf('https://') < 0)
aURI = this.dataFolder+aURI;
this.imageRequests[aURI] = new XMLHttpRequest();
try {
this.imageRequests[aURI].open('GET', aURI);
this.imageRequests[aURI].onload = function() {
Presentation.imageRequests[aURI] = null;
};
this.imageRequests[aURI].send(null);
}
catch(e) {
this.imageRequests[aURI] = null;
}
return aURI;
},
imageRequests : {},
get isPresentationMode(){
return (this.deck.selectedIndex == 0);
},
get dataPath(){
if (!this._dataPath)
this.dataPath = String(location.href).replace(/#.+$/, '');
return this._dataPath;
},
set dataPath(aValue){
var oldDataPath = this._dataPath;
this._dataPath = aValue;
if (oldDataPath != aValue) {
this._dataFolder = this._dataPath.split('?')[0].replace(/[^\/]+$/, '');
}
return this._dataPath;
},
get dataFolder(){
if (!this._dataFolder)
this.dataPath = this.dataPath;
return this._dataFolder;
},
set dataFolder(aValue){
this._dataFolder = aValue;
return this._dataFolder;
},
readParameter : function() {
if (location.search || location.hash) {
var param = location.search.replace(/^\?/, '');
if (location.hash.match(/page([0-9]+)/i) ||
param.match(/page=([0-9]+)/i))
this.offset = parseInt(RegExp.$1)-1;
if (location.hash.match(/edit/i) ||
param.match(/edit=(1|true|yes)/i))
this.toggleEditMode();
if (location.hash.match(/eva/i) ||
param.match(/eva=(1|true|yes)/i))
this.toggleEvaMode();
if (param.match(/data=([^&;]+)/i)) {
var path = unescape(RegExp.$1);
this.dataPath = path;
var request = new XMLHttpRequest();
request.open('GET', path);
request.onload = function() {
Presentation.textbox.value = request.responseText;
Presentation.data = Presentation.textbox.value;
Presentation.init();
};
request.send(null);
return false;
}
}
return true;
}
};
var StrokeService = {
className : 'stroke-dot',
dragStartDelta : 8,
lineColor : 'red',
lineWidth : 3,
initialized : false,
mode : null,
canvas : null,
canvasContext : null,
startX : -1,
startY : -1,
init : function(aCanvas)
{
this.initialized = true;
this.canvas = aCanvas;
var canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
this.canvas.appendChild(canvas);
if (!('getContext' in canvas) || !canvas.getContext) {
this.canvas.removeChild(canvas);
this.mode = 'box';
}
else {
this.canvas = canvas;
this.canvasContext = this.canvas.getContext('2d');
this.mode = 'canvas';
}
document.documentElement.addEventListener('PresentationRedraw', this, false);
window.addEventListener('resize', this, false);
this.canvas.addEventListener('mouseup', this, false);
this.canvas.addEventListener('mousedown', this, false);
this.canvas.addEventListener('mousemove', this, false);
this.canvas.addEventListener('click', this, false);
this.clear();
},
destroy : function()
{
document.documentElement.removeEventListener('PresentationRedraw', this, false);
window.removeEventListener('resize', this, false);
this.canvas.removeEventListener('mouseup', this, false);
this.canvas.removeEventListener('mousedown', this, false);
this.canvas.removeEventListener('mousemove', this, false);
this.canvas.removeEventListener('click', this, false);
this.cliclableNodesManager = null;
this.canvas = null;
this.initialized = false;
},
handleEvent : function(aEvent)
{
switch(aEvent.type)
{
default:
break;
case 'mouseup':
this.finish(aEvent);
this.startX = -1;
this.startY = -1;
window.setTimeout('StrokeService.preventToSendClickEvent = false', 10);
break;
case 'mousedown':
if (this.startX < 0) {
this.startX = aEvent.clientX;
this.startY = aEvent.clientY;
}
break;
case 'mousemove':
if (this.startX > -1 && !this.active) {
if (Math.abs(this.startX-aEvent.clientX) > Math.abs(this.dragStartDelta) ||
Math.abs(this.startY-aEvent.clientY) > Math.abs(this.dragStartDelta)) {
this.start(aEvent, this.startX, this.startY);
this.preventToSendClickEvent = true;
}
}
else
this.trace(aEvent);
break;
case 'PresentationRedraw':
case 'resize':
this.clear();
break;
case 'click':
if (this.preventToSendClickEvent) {
aEvent.stopPropagation();
aEvent.preventCapture();
aEvent.preventDefault();
aEvent.preventBubble();
this.preventToSendClickEvent = false;
}
else if (this.cliclableNodesManager && this.cliclableNodesManager.clickableNodes) {
var nodes = this.cliclableNodesManager.clickableNodes;
var max = nodes.length;
var x, y, width, height
for (var i = 0; i < max; i++)
{
if (nodes[i].boxObject) {
x = nodes[i].boxObject.x;
y = nodes[i].boxObject.y;
width = nodes[i].boxObject.width;
height = nodes[i].boxObject.height;
}
else {
x = nodes[i].offsetLeft;
y = nodes[i].offsetTop;
width = nodes[i].offsetWidth;
height = nodes[i].offsetHeight;
}
if (aEvent.clientX < x ||
aEvent.clientX > x+width ||
aEvent.clientY < y ||
aEvent.clientY > y+height)
continue;
var event = document.createEvent('MouseEvents');
event.initMouseEvent(
aEvent.type, aEvent.canBubble, aEvent.cancelable, aEvent.view,
aEvent.detail,
aEvent.screenX, aEvent.screenY, aEvent.clientX, aEvent.clientY,
aEvent.ctrlKey, aEvent.altKey, aEvent.shiftKey, aEvent.metaKey,
aEvent.button,
aEvent.relatedTarget
);
nodes[i].dispatchEvent(event);
break;
}
}
break;
}
},
preventToSendClickEvent : false,
start : function(aEvent, aX, aY)
{
this.active = true;
this.trace(aEvent, aX, aY);
},
finish : function(aEvent)
{
if (!this.active) return;
this.trace(aEvent);
this.finishStroke();
},
trace : function(aEvent, aX, aY)
{
if (!this.active) return;
this.addPoint((aX === void(0) ? aEvent.clientX : aX ), (aY === void(0) ? aEvent.clientY : aY ));
},
finishStroke : function()
{
this.active = false;
this.lastX = -1;
this.lastY = -1;
},
addPoint : function(aX, aY)
{
if (this.lastX != -1)
this.drawLine(this.lastX, this.lastY, aX, aY);
else
this.drawDot(aX, aY);
this.lastX = aX;
this.lastY = aY;
},
clear : function()
{
this.active = false;
this.lastX = -1;
this.lastY = -1;
if (this.mode == 'canvas') {
if (this.canvas.lastWindowWidth != window.innerWidth ||
this.canvas.lastWindowHeight != window.innerHeight) {
this.canvas.width = this.canvas.parentNode.boxObject.width-2;
this.canvas.height = this.canvas.parentNode.boxObject.height-2;
this.canvas.lastWindowWidth = window.innerWidth;
this.canvas.lastWindowHeight = window.innerHeight;
}
this.canvasContext.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.canvasContext.strokeStyle = this.lineColor;
this.canvasContext.lineWidth = this.lineWidth;
}
else {
var dotes = this.canvas.getElementsByAttribute('class', this.className);
if (!dotes.length) return;
var range = document.createRange();
range.selectNodeContents(this.canvas);
range.setStartBefore(dotes[0]);
range.setEndAfter(dotes[dotes.length-1]);
range.deleteContents();
range.detach();
}
},
drawDot : function(aX, aY, aParent)
{
if (this.mode == 'canvas') {
this.canvasContext.strokeRect(aX, aY, 0, 0);
this.canvasContext.stroke();
}
else {
var dot = document.createElement('spacer');
dot.setAttribute('style', 'left:'+aX+'px; top:'+aY+'px');
dot.setAttribute('class', this.className);
(aParent || this.canvas).appendChild(dot);
}
},
drawLine : function(aX1, aY1, aX2, aY2)
{
if (aX1 == aX2 && aY1 == aY2) return;
if (this.mode == 'canvas') {
this.canvasContext.beginPath();
this.canvasContext.moveTo(aX1, aY1);
this.canvasContext.lineTo(aX2, aY2);
/*
this.canvasContext.bezierCurveTo(
parseInt(aX1+((aX2-this.lastX)*0.3)), parseInt(aY1+((aY2-this.lastY)*0.3)),
parseInt(aX1+((aX2-this.lastX)*0.6)), parseInt(aY1+((aY2-this.lastY)*0.6)),
aX2, aY2
);
*/
this.canvasContext.closePath();
this.canvasContext.stroke();
}
else {
var x_move = aX2 - aX1;
var y_move = aY2 - aY1;
var x_diff = x_move < 0 ? 1 : -1;
var y_diff = y_move < 0 ? 1 : -1;
var fragment = document.createDocumentFragment();
if (Math.abs(x_move) >= Math.abs(y_move)) {
for (var i = x_move; i != 0; i += x_diff)
this.drawDot(aX2 - i, aY2 - Math.round(y_move * i / x_move), fragment);
}
else {
for (var i = y_move; i != 0; i += y_diff)
this.drawDot(aX2 - Math.round(x_move * i / y_move), aY2 - i, fragment);
}
this.canvas.appendChild(fragment);
}
}
};
var StrokablePresentationService = {
id : 'stroke-canvas-box',
strokeService : null,
cliclableNodesManager : null,
canvasContainer : null,
canvas : null,
autoStart : false,
init : function(aPresentation, aStrokeService)
{
this.cliclableNodesManager = aPresentation;
this.strokeService = aStrokeService;
this.canvasContainer = document.getElementById('canvas').firstChild;
this.check = document.getElementById('penButton');
document.documentElement.addEventListener('StartDragOnCanvas', this, false);
document.documentElement.addEventListener('PresentationRedraw', this, false);
},
toggle : function(aEnable)
{
if (aEnable)
this.start();
else
this.end();
},
start : function()
{
if (!this.strokeService || !this.canvasContainer) return;
this.strokeService.cliclableNodesManager = this.cliclableNodesManager;
var box = document.createElement('vbox');
box.setAttribute('flex', 1);
box.setAttribute('id', this.id);
this.canvas = this.canvasContainer.appendChild(box);
this.strokeService.init(this.canvas);
},
end : function()
{
this.strokeService.destroy();
this.canvasContainer.removeChild(this.canvas);
this.canvas = null;
},
handleEvent : function(aEvent)
{
switch (aEvent.type)
{
default:
break;
case 'StartDragOnCanvas':
if (!this.check.checked) {
this.toggleCheck();
this.strokeService.startX = Presentation.dragStartX;
this.strokeService.startY = Presentation.dragStartY;
this.autoStart = true;
}
break;
case 'PresentationRedraw':
if (this.autoStart && this.check.checked) {
this.autoStart = false;
this.toggleCheck();
}
break;
}
},
toggleCheck : function()
{
var enable = !this.check.checked;
this.toggle(enable);
this.check.checked = enable;
this.autoStart = false;
}
};
function init()
{
window.removeEventListener('load', init, false);
Presentation.init();
StrokablePresentationService.init(Presentation, StrokeService);
}
window.addEventListener('load', init, false);
]]></script>
</page>