reptile7's JavaScript blog
Thursday, July 03, 2014
 
Parsing for Colorables
Blog Entry #326

Welcome back to our analysis of the Java Goodies Rainbow Text script.

The rest of the morefun( ) function

Having stored the value of the myarea textarea field in a mystring variable and opened a new mywin window in our last episode, we are now ready to
(a) color the text characters of the mystring string,
(b) further mark up the resulting text as necessary, and finally
(c) display our handiwork in the new window.
These operations are iteratively effected via a while loop whose i counter moves us through the length of the mystring string.

var i = 0;
while (i != mystring.length) { ... }


The loop first gets the 0th mystring character and assigns it to an a variable.

a = mystring.substring(i, i + 1);

What happens next depends on whether a is a < (left angle bracket) character, a space character, or a normal text character to be colored: these possibilities are respectively addressed by the three branches of an if...else if...else construct.

If it's a tag

if (a == "<") { z = i; while (a != ">") { z++; a = mystring.substring(z, z + 1); } a = mystring.substring(i, z + 1); mywin.document.writeln(a); i = z + 1; }

If a is a <, then the script assumes that it has hit the beginning of an <element> tag. The script uses a z index and a while loop to walk a through the tag until a reaches the tag's concluding > character, at which point the script extracts the tag and writes it to the page. The clause's last statement advances i to the mystring position one past the >.

An analogous tag extraction is carried out by the Java Goodies Multi-Colored Text script: see the Tag encounter section of Blog Entry #307 for its deconstruction.

If it's a space

else if (a == " " || a == "" || a == "  ") { mywin.document.write(a); i++; }

If a is a " " - a space generated by a space bar - then a is written to the page and i is moved to the next mystring position.

I have no idea what the a == "" and a == "  " tests are about. Are they for flagging newlines perhaps? With the browsers on my iMac, a newline does not go through the else if gate but is handled by the code in the next subsection.

The "" and "  " strings were what they seemed to be - an empty string and two spaces, respectively - when I probed them with the String object's charCodeAt( ) method: "".charCodeAt( ) returned NaN whereas "  ".charCodeAt(0) and "  ".charCodeAt(1) both returned 32.

I was originally going to replace the three else if subconditions with a single /^\s*$/.test(a) test.
• In a RegExp pattern, \s matches any white space character.
• The test( ) method of the RegExp object is detailed here.
However, the Multi-Colored Text script doesn't deal with spaces separately but rather 'colors' them along with the rest of the text, and I am now inclined to throw out the else if clause altogether.

If it's normal text

else { if (b > 13) { b = 0; } c = myColor[b]; mywin.document.write(a.fontcolor(c)); b++; i++; }

If a is neither a < nor a space, then the b variable is plugged into the myColor array to give a corresponding six-digit hexadecimal RGB color, which is assigned to a c variable. The c color is applied to a via a fontcolor( ) command and the colored a is written to the page. Subsequently b and i are incremented; when b reaches 14 it is reset to 0 in the next iteration. It follows that the a characters are colored according to a myColor[0], myColor[1], myColor[2], ... myColor[13], myColor[0], myColor[1], ... cycle as the while (i != mystring.length) loop iterates.

Note that b is not reset to 0 if morefun( ) is re-called; consequently, if the user closes the mywin window and clicks the button to open another mywin window, the new mystring display will have a different color pattern (unless mystring contains 14n colorable characters: n = 1, 2, ...).

The fontcolor( ) operation wraps a in a <font color=c></font> element. If you're not happy about that - the font element is currently deprecated and will be entirely obsolete in HTML5 - and would rather place a in a span element and color it with the CSS color property, then the command you want is:

mywin.document.write("<span style='color:" + c + ";'>" + a + "<\/span>");

Post-color

The while (i != mystring.length) loop runs until i equals mystring.length, at which point control passes to an if statement that appends </body> and </html> tags to the mywin document if the status of the isHTML checkbox is false.

if (document.myform.isHTML.status == false) { mywin.document.writeln("</body>"); mywin.document.writeln("</html>"); }

As noted last time, the above if condition returns false - the document.myform.isHTML.status operand returns undefined, which is not converted to false for a == comparison - so the browser moves to morefun( )'s final command:

mywin.document.close( );

According to the W3C, document.close( ) closes a document stream opened by document.open( ) and forces rendering. In practice, Netscape 2-4 does need the preceding command to reliably display the colored mystring string in the mywin window* but modern browsers don't.
(*I find that a &block; input (e.g., <p>This is a paragraph.</p>) is OK but an &inline; input (e.g., <i>This text is italicized.</i>) doesn't show up at all if the document is not closed.)

Demo

In the textarea box below, input
(a) some pure text or
(b) some marked-up text, up to and including an entire document, and then
click the button.



Limitations
<script> and <style> elements won't have any effect (or at least they don't on my computer) - if any are present I'd take 'em out.
• Character references (e.g., &pound; for the £ character) are treated as literal text.
• A < character that is not balanced by a > character (e.g., a < is my favorite symbol mystring) will give rise to an infinite loop.

I didn't like the HTML Source checkbox business so I threw it out. The Background selection list works with all inputs and now includes Gold Background and Pale Green Background options. (I'm a big fan of the #eeffee color as it makes me think of mint chocolate chip ice cream. :-))

The title problem

Let's suppose that
(a) we're working with the original script and
(b) we check the isHTML checkbox and
(c) our textarea input features a <title>Hi</title> title.

The title element has a (#PCDATA) -(SCRIPT|STYLE|META|LINK|OBJECT) content model, meaning that it should contain only text and no child elements. When the Hi content is run through the mywin.document.write(a.fontcolor(c)); command, the font element markup (vide supra) will be treated as literal text and the actual title bar output will look like:

<font color="#990099">H</font><font color="#CC00FF">i</font>
<!-- Your color values may be different, depending on the H's location in the mystring string. -->


(The same thing happens to the Some text content of a <textarea>Some text</textarea> input; if you're gonna put a textarea element in the mystring string, leave it blank.)

The simplest way to get the unadulterated Hi in the title bar is to fish it out of the mystring string and assign it to mywin.document.title at the end of the morefun( ) function:

var titleStartTagStart = mystring.indexOf("<title");
var titleStartTagEnd = mystring.indexOf(">", titleStartTagStart);
var titleEndTagStart = mystring.indexOf("</title>");
var titleValue = mystring.substring(titleStartTagEnd + 1, titleEndTagStart);
mywin.document.title = mywin.document.title ? titleValue : "Somewhere over the rainbow....";
/* The ?: conditional operator is documented here. */


Comments: Post a Comment

<< Home

Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)