// TBT javascript extensions: rgareus 2008
// TBT javascript prototype: Jaromil 2007
// reference javascript typewriter documentation: F. Permadi 2002
// GNU GPL
function TBT() {
this.setRowCarriageReturn = setRowCarriageReturn;
this.setXhtml = setXhtml;
this.setSpeed = setSpeed;
this.startTyping = startTyping;
this.feed = feed;
var currentChar;
var destination;
var cur_x;
var cur_y;
var row;
var col;
var text;
var render_text;
var rowsize;
var colsize;
var recording;
var cr;
var cc;
var rowcr=0; // config option; do a CR (\r) when moving the cursor up/down
var xhtml=0; // html or xhtml
var speed=1; // time factor.
function setSpeed(s) {
if (s> 0.01 && s< 20) this.speed=s;
else speed=1.0;
}
function setXhtml(onoff) {
xhtml=onoff?true:false;
}
function setRowCarriageReturn(onoff) {
rowcr=onoff?true:false;
}
function startTyping(destinationParam, tbtrecord) {
currentChar = 0;
destination = destinationParam;
recording = tbtrecord;
// global text positions
row = 0;
col = 0;
// cursor positions
cur_x = 0;
cur_y = 0;
// length counters
rowsize = 0;
colsize = 0;
cr = 0;
cc = 0;
// text bidimensional array
text = new Array();
text[0] = new Array();
// text render buffer
render_text = "";
setTimeout(this.feed, speed*recording[currentChar][1] );
}
function feed() {
var dest = document.getElementById(destination);
if (dest) {
// && dest.innerHTML)
/* TODO: handle movement keys:
KEY_BACKSPACE 275, 127, 272
KEY_PAGE_UP 261 ; KEY_PAGE_DOWN 262
KEY_HOME 263 ; KEY_DELETE 275
port the abstract_console from slw in js
*/
// get the next char
switch( recording[currentChar][0] ) {
case 10: // NEWLINE
case 13: // RETURN
cur_y++; row++;
cur_x = 0; col = 0;
if(row >= text.length) {
text[row] = new Array();
}
break;
case 8: // standard ASCII BACKSPACE
case 127: // other low level BACKSPACE codes
case 272: // (APPLE BACKSPACE)
case 275: // (SOMETIMES!?)
if(col > 0) // delete if not at the beginning of line
text[row].splice(col-1,1);
if(cur_x > 0) {
cur_x--;
col--;
} else { // backspace at the beginning of a line
// move everything up one line
// TODO
}
break;
case 257: // UP
if(row <= 0) break;
cur_y--; row--;
if (rowcr) { col=0; cur_x=0; }
break;
case 258: // DOWN
if(row >= text.length) break;
cur_y++; row++;
if (rowcr) { col=0; cur_x=0; }
break;
case 259: // LEFT
if(cur_x <= 0) break;
cur_x--;
col--;
break;
case 260: // RIGHT
// if(cur_x >= text[row].length) break;
cur_x++;
col++;
break;
default:
if (!text[row]) text[row] = new Array();
text[row].splice(col,0,recording[currentChar][0]);
cur_x++; col++;
break;
}
// RENDER TEXT
render_text = "";
rowsize = text.length;
for(cr = 0; cr < rowsize; cr++) {
colsize = text[cr].length;
if(cur_y == cr) { // cursor row
for(cc = 0; cc < colsize; cc++) {
if(cur_x == cc) { // draw cursor
render_text += "";
render_text += String.fromCharCode( text[cr][cc] );
render_text += "";
} else // not yet on cursor
render_text += String.fromCharCode( text[cr][cc] );
}
// draw cursor at the end of line
if(cur_x >= colsize) render_text += "_";
} else // no need to draw the cursor
for(cc = 0; cc < colsize; cc++)
render_text += String.fromCharCode( text[cr][cc] );
// newline
render_text += xhtml?"
":"
";
}
// render_text += String.fromCharCode( recording[currentChar][0] );
dest.innerHTML = render_text;
// DOM compliant alternative:
// var textNode=document.createTextNode(text);
// dest.replaceChild(textNode, dest.childNodes[0]);
// go to the next entry
currentChar++;
if (currentChar >= recording.length) {
// end of record, restart after 5 seconds
currentChar=0;
render_text="";
// clear all text buffer
for(cr=0; cr < text.length; cr++)
delete text[cr];
delete text;
// end of text
} else {
// RECURSION IS TIME -jrml 31jan2007
setTimeout(feed, speed*recording[currentChar][1] );
}
}
}
};
//Setup VIM: ex: sw=4 ts=8 enc=utf-8 :