The photo gallery JavaScript includes code which generates the virtual "LCD" text panel. The version of the code shown here is for the panel as it is used on the information page. The code is slightly different from that used in the gallery but the basic text processing and display flow is the same. Note that there are a number of additional cosmetic tweaks for formatting in this window.
// (c) 2000-2002 D.Holmes // counters etc. for imgLoadChk() var t_total = 0; // thumbnail var f_total = 0; // fullsize var et_total = 0; // empty thumbnail var ef_total = 0; // empty fullsize var checkthumbN = 0; // how many thumbnails loaded so far var checkfullN = 0; // how many fullsized loaded so far var type = ""; // image type: t,f,et,ef - thumbnail, // fullsized, empty thumb or ful var num = 0; var checkfullid, checkthumbid; // image load checking timer var maxStrings = 9; // message text strings limit var rMax = 7; // lcd row var cLen = 30; // lcd column length in char var cellWidth = 11; // in pixels var cellHeight = 15; // " " // colour codes for font glyph image // selection and background colour var letterbg = "#001955"; // y2 & B if (colourcode == "b" || colourcode == "gB") letterbg = "#FFFFFF"; if (colourcode == "B2") letterbg = "#042999"; // timers (in milliseconds) var StartDelay = 4000; // initial slideshow delay var RepeatDelay = 6000; // formfeed delay used at end of // screenfull of text var StatusInterval = 1000; // repeatLoop() interval for // checking if we need to rerun // mainLoop() // "typing" speed timers - used to delay // image swapping of character glyph var typeNormal = true; var typeSpeed = 70; var crlfSpeed = (typeSpeed * 4); var highSpeed = 0; var commaPause = 6; var stopPause = 18; var delayPause = 0; // ASCII codes used to test for special char // in particular see putLine() which handles // actual character output to "lcd screen BELchar = 7; BSchar = 8; HTchar = 9; LFchar = 10; VTchar = 11; FFchar = 12; CRchar = 13; SPACE = 32; MagicTABs = true; TABwidth = 8; LowerASCII = 32; UpperASCII = 126; // Initialize tracking indices used to monitor // screen location etc. var rIndex = 0; var cIndex = 0; var sIndex = 0; var sCount = 1; var currString = ""; var printing = false; // test if currently printing var timerStatus = 0; // used to prevent start (-1) if there // wasn't a "stop" to clear timers (0) // timer IDs used to kill off all timers var putLineID; var formFeedID; var mainLoopID; var repeatIntervalID; var INformFeed = -1; // set in endofline() - cleared in // formfeed and tested & cleared in // startDisplay() // LCD clock display (clock is client's time var clockBlink = false; // flipper for ":" flash var nowTime; var clkIntervalID; var clockLen = 8; // Pre-cache the glyphs for (imgs = 32; imgs <= 126 ; imgs++) { eval("var " + imgprefix + imgs + " = new Image()\;"); } for (imgs = 32; imgs <= 126 ; imgs++) { eval(imgprefix + imgs + ".src = \"" + fileprefix + imgs + filesuffix + "\"\;"); } // Prep. display for restart after text run is complete // (other than clock which is independent) function endgame() { formFeed(); stopDisplay(); currString = "To replay this text, reload" +'\t'+ "the page or select the" +'\t'+ "checkbox shown on the right ->"; typeNormal = false; putLine(); document['lcd2c29'].src = imgdir + "r-arrow_t.gif"; return; } // Called by user clicking tic box of FORM; can happen at any time function replay() { formFeed(); stopDisplay(); sCount = 1; repeatIntervalID = setInterval("repeatLoop()",StatusInterval); document.forms[0].reset(); } // Clock sits on last row and runs independently function LCDclock() { var c = 0 var now = new Date(); var nowHour = now.getHours(); var nowMin = now.getMinutes(); var now12Hr if (now.getTimezoneOffset() == 0) { nowTime = ((nowHour < 10) ? "0" : "") + nowHour; nowTime += ((clockBlink) ? " " : ":") nowTime += ((nowMin < 10) ? "0" : "") + nowMin; nowTime += " GMT"; clockLen = 9; } else { now12Hr = ((nowHour > 12) ? nowHour - 12 : nowHour); nowTime = ((now12Hr < 10) ? " " : "") + now12Hr; nowTime += ((clockBlink) ? " " : ":") nowTime += ((nowMin < 10) ? "0" : "") + nowMin; nowTime += (nowHour >= 12) ? " pm" : " am"; clockLen = 8; } clockBlink = !clockBlink; while (c < clockLen) { target = "lcd" + rMax + "c" + (cLen - clockLen + c); source = fileprefix+nowTime.charCodeAt(c)+filesuffix; document[target].src = source; c++; } } // mainLoop() handles launching the printing of each string // of text as well as interpreting magic strings which // control operation function mainLoop() { printing = true; rIndex = 0; cIndex = 0; if (sCount > maxStrings) { sCount = 1; formFeedID = setTimeout("formFeed()",RepeatDelay); } else { currString = eval("Text" + sCount); if (currString == "xHALTx") { stopDisplay(); return; } else if (currString == "xCODEx") { stopDisplay(); endgame(); // run special routine return; } else if (currString == "xSKIPx") { printing = false; sCount++; return; } formFeed(); putLine(); sCount++; } } // Testing wrapper for mainLoop() function repeatLoop() { if (! printing) { printing = true; mainLoop(); } } // Run from HTML onload event handler function afterload() { // never use the last row for text; clock is there rMax-- ; clkIntervalID = setInterval("LCDclock()",2000); repeatIntervalID = setInterval("repeatLoop()",StatusInterval); } // Clears the entire display area to space chars function formFeed() { clearTimeout(putLineID); for (r = 0; r < rMax ; r++) { for (c = 0; c < cLen ; c++) { target = "lcd" + r + "c" + c; source = imgprefix + "32.src"; document[target].src = eval(source); } } target = "lcd" + "0" + "c" + "0"; source = cursorimg.src; document[target].src = source; rIndex = 0; cIndex = 0; INformFeed = -1; printing = false; } // Clears a single row function clearRow(row) { clearTimeout(putLineID); r = row; if (r < rMax) { for (c = 0; c < cLen ; c++) { target = "lcd" + r + "c" + c; source = imgprefix + "32.src"; document[target].src = eval(source); } } cIndex = 0; rIndex = r; } // Reset flags to show we're not printing and // typing speed is returned to normal function outputFinished() { printing = false; typeNormal = true; } // Kill all text activity // and reset modes function stopDisplay() { stillloading = false; clearTimeout(checkthumbid); clearTimeout(checkfullid); clearTimeout(mainLoopID); clearTimeout(repeatIntervalID); clearTimeout(formFeedID); clearTimeout(putLineID); timerStatus = 0; outputFinished(); } // Text processor - here is the actual parsing and output of the text // This function features: // - parsing of magic character conditions, // - typing speed mode (fast or normal) // - pausing for punctuation // - handling quoted or bracketed punctuation // - handling repeated punctuation ('...' etc.) // // The function works by outputing a character (image swapping within // the LCD TABLE drawn by drawTable() ) and then calling itself again // based on how it wants to deal with the next character based upon // what it just printed, what's next, where it is on the line etc. function putLine() { printing = true; clearTimeout(putLineID); var localstring = currString; var localrownum = rIndex; var localcolumn = cIndex; var localCode = 0; // if we still have some text left to deal with, // then get and test the next character in the string if (localstring.length > 0) { localCode = localstring.charCodeAt(); // handle any magic tokens we use and filter bad stuff if (isNaN(localCode)) localCode = NotAChar; if (localCode == LFchar) { endofLine(LFchar); } else if (localCode == CRchar) { endofLine(CRchar); } else if (localCode == HTchar && MagicTABs) { endofLine(HTchar); } else if (localCode == HTchar) { } else if ( localCode < LowerASCII || localCode > UpperASCII ) { localCode = NotAChar; } else { // and then output legitimate chars target = "lcd" + localrownum +"c"+ localcolumn; source = eval(imgprefix + localCode + ".src"); document[target].src = source; localcolumn++; // Now prep to handle what would happen next // making note of our current typing speed setting // handling cursor, punctuation pauses, line endings // etc. // NOTE that we also special-case repeating punctuation // and punctuation within quotes, brackets etc. with // the delayPause for example // Assuming we still have more line to the right... if (localcolumn <= cLen) { // display cursor only if typing at // normal speed and space to the right if (typeNormal && (localcolumn < cLen) ) { target = "lcd" + localrownum + "c" + localcolumn; source = cursorimg.src; document[target].src = source; } localstring = localstring.slice(1); currString = localstring; cIndex = localcolumn; // if we're in high-speed mode, just output if (!typeNormal) putLineID = setTimeout("putLine()",highSpeed); // else if char wasn't punctuation or // delayed (quoted, brackets etc.) // punctuation, then on to next else if (delayPause == 0 && (localCode > 63 || localCode == 32)) putLineID = setTimeout("putLine()",typeSpeed); // else if we delayed the punctuation // pause last time for closing // quotes, brackets etc. then we // need to insert a pause now // 44 comma, 58 colon - commaPause, // otherwise period pause else if (delayPause != 0) { if ( (delayPause == 44) || (delayPause == 58)) { putLineID = setTimeout("putLine()", (typeSpeed * commaPause)); } else { putLineID = setTimeout("putLine()", (typeSpeed * stopPause)); } delayPause = 0; } // else if not punct., do next else if ( localCode != 46 && localCode != 44 && localCode != 33 && localCode != 63 && localCode != 59 && localCode != 58) { putLineID = setTimeout("putLine()",typeSpeed); } // else if punct. followed by a closing quote, bracket etc. // then set delayPause and but don't delay YET // 46 period, 33 exclamation, 63 question else if ( ( (localCode == 46) || (localCode == 33) || (localCode == 63) ) && (localstring.length > 1) && ((localstring.charCodeAt(0) == 34) || (localstring.charCodeAt(0) == 39) || (localstring.charCodeAt(0) == 41) || (localstring.charCodeAt(0) == 93) || (localstring.charCodeAt(0) == 125) )) { delayPause = localCode; putLineID = setTimeout("putLine()",typeSpeed); } // deal with '...' etc. - no pause else if ( (localstring.length >= 1) && ((localstring.charCodeAt(0) == localCode) || (localstring.charCodeAt(0) != SPACE) && (localstring.charCodeAt(0) != HTchar) )) { putLineID = setTimeout("putLine()",typeSpeed); } // else pause for punct. else if ( (localCode == 44) || (localCode == 58) ) putLineID = setTimeout("putLine()",(typeSpeed * commaPause)); else { putLineID = setTimeout("putLine()",(typeSpeed * stopPause)); } // ... otherwise if no more line is // available deal with the line ending } else { endofLine(localCode); } } // otherwise localstring.length <= 0 // ... stop printing. } else { printing = false; typeNormal = true; } } // handle various "end of" events - end of line, end of display etc. function endofLine(ending) { // if we still have space to the right, output a space char (32) if (cIndex < cLen) { target = "lcd" + rIndex + "c" + cIndex; source = imgprefix + "32.src"; document[target].src = eval(source); } // if there are more rows, incr. and display cursor... if (rIndex < rMax) { rIndex++ cIndex=0; target = "lcd" + rIndex + "c" + cIndex; source = cursorimg.src; document[target].src = source; } else { // ... else formfeed rIndex=0; cIndex=0; currString = Text0; INformFeed = 0; formFeedID = setTimeout("formFeed()",4000); } // if a TAB got us here, eat it and keep going... // (TABs force a crlf) if (ending == HTchar) { currString = currString.slice(1); if (!typeNormal) putLineID = setTimeout("putLine()",highSpeed); else putLineID = setTimeout("putLine()",crlfSpeed); } else { //... else clear flags printing = false; typeNormal = false; } } // drawTable() creates the HTML code for the LCD panel display function drawTable() { var BGimg = cellbackground; var FGimg = fileprefix + "32" + filesuffix; var LCDtable = "<TABLE BGCOLOR=\"" + letterbg + "\" WIDTH=\"" + ((cellWidth * cLen) + 8) + "\" CELLPADDING=\"4\" CELLSPACING=\"0\" BORDER=\"0\">\n"; LCDtable += "<TR><TD>\n"; LCDtable += "<TABLE BACKGROUND=\"" + BGimg + "\" WIDTH=" + (cellWidth * cLen) + " CELLPADDING=0 CELLSPACING=0 BORDER=0>\n"; for (r = 0; r < rMax ; r++) { LCDtable += "<TR><TD NOWRAP>"; for (c = 0; c < cLen ; c++) { LCDtable += "<IMG \nNAME=\"lcd" + r + "c" + c + "\" SRC=\"" + FGimg + "\""; LCDtable += "WIDTH=\"" + cellWidth + "\" HEIGHT=\"" + cellHeight + "\">"; } LCDtable += "</TD></TR>\n"; } LCDtable += "</TABLE>\n"; LCDtable += "</TD></TR>\n"; LCDtable += "</TABLE>\n"; document.write(LCDtable); // this isn't technically polite... document.close(); }