BUY THIS BOOK
Add to Cart

Print Book $44.99


Add to Cart

PDF $35.99

Safari Books Online

What is this?

Add to UK Cart

Print Book £27.99

What is this?

Looking to Reprint or License this content?


JavaScript & DHTML Cookbook
JavaScript & DHTML Cookbook, Second Edition

By Danny Goodman
Book Price: $44.99 USD
£27.99 GBP
PDF Price: $35.99

Cover | Table of Contents


Table of Contents

Chapter 1: Strings
A string is one of the fundamental building blocks of data that JavaScript works with. Any script that touches URLs or user entries in form text boxes works with strings. Most document object model properties are string values. Data that you read or write to a browser cookie is a string. Strings are everywhere!
The core JavaScript language has a repertoire of the common string manipulation properties and methods that you find in most programming languages. You can tear apart a string character by character if you like, change the case of all letters in the string, or work with subsections of a string. Most scriptable browsers now in circulation also benefit from the power of regular expressions, which greatly simplify numerous string manipulation tasks—once you surmount a fairly steep learning curve of regular expression syntax.
Your scripts will commonly be handed values that are already string data types. For instance, if you need to inspect the text that a user has entered into a form's text box, the value property of that text box object returns a value already typed as a string. All properties and methods of any string object are immediately available for your scripts to operate on that text box value.
If you need to create a string, you have a couple of ways to accomplish it. The simplest way is to simply assign a quoted string of characters (known as a string literal) to a variable (or object property):
	var myString = "Fluffy is a pretty cat.";
Quotes around a JavaScript string can be either single or double quotes, but each pair must be of the same type. Therefore, both of the following statements are acceptable:
	var myString = "Fluffy is a pretty cat.";
	var myString = 'Fluffy is a pretty cat.';
But the following mismatched pair is illegal and throws a script error:
	var myString = "Fluffy is a pretty cat.';
Having the two sets of quote symbols is handy when you need to embed one string within another. The following document.write() statement that would execute while a page loads into the browser has one outer string (the entire string being written by the method) and nested sets of quotes that surround a string value for an HTML element attribute:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Introduction
A string is one of the fundamental building blocks of data that JavaScript works with. Any script that touches URLs or user entries in form text boxes works with strings. Most document object model properties are string values. Data that you read or write to a browser cookie is a string. Strings are everywhere!
The core JavaScript language has a repertoire of the common string manipulation properties and methods that you find in most programming languages. You can tear apart a string character by character if you like, change the case of all letters in the string, or work with subsections of a string. Most scriptable browsers now in circulation also benefit from the power of regular expressions, which greatly simplify numerous string manipulation tasks—once you surmount a fairly steep learning curve of regular expression syntax.
Your scripts will commonly be handed values that are already string data types. For instance, if you need to inspect the text that a user has entered into a form's text box, the value property of that text box object returns a value already typed as a string. All properties and methods of any string object are immediately available for your scripts to operate on that text box value.
If you need to create a string, you have a couple of ways to accomplish it. The simplest way is to simply assign a quoted string of characters (known as a string literal) to a variable (or object property):
	var myString = "Fluffy is a pretty cat.";
Quotes around a JavaScript string can be either single or double quotes, but each pair must be of the same type. Therefore, both of the following statements are acceptable:
	var myString = "Fluffy is a pretty cat.";
	var myString = 'Fluffy is a pretty cat.';
But the following mismatched pair is illegal and throws a script error:
	var myString = "Fluffy is a pretty cat.';
Having the two sets of quote symbols is handy when you need to embed one string within another. The following document.write() statement that would execute while a page loads into the browser has one outer string (the entire string being written by the method) and nested sets of quotes that surround a string value for an HTML element attribute:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Concatenating (Joining) Strings
You want to join together two strings or accumulate one long string from numerous sequential pieces.
Within a single statement, use the plus (+) operator to concatenate multiple string values:
	var longString = "One piece " + "plus one more piece.";
To accumulate a string value across multiple statements, use the add-by-value (+=) operator:
	var result = "";
	result += "My name is " + document.myForm.myName.value;
	result += " and my age is " + document.myForm.myAge.value;
The add-by-value operator is fully backward-compatible and is more compact than the less elegant approach:
	result = result + "My name is " + document.myForm.myName.value;
You can use multiple concatenation operators within a single statement as needed to assemble your larger string, but you must be cautious about word wrapping of your source code. Because JavaScript interpreters have a built-in feature that automatically inserts semicolons at the logical ends of source code lines, you cannot simply break a string with a carriage return character in the source code without putting the syntactically correct breaks in the code to indicate the continuation of a string value. For example, the following statement and format triggers a syntax error as the page loads:
	var longString = "One piece " + "plus one
	more piece.";
The interpreter treats the first line as if it were:
	var longString = "One piece " + "plus one;
To the interpreter, this statement contains an unterminated string and invalidates both this statement and anything coming after it. To break the line correctly, you must terminate the trailing string, and place a plus operator as the final character of the physical source code line (do not put a semicolon there because the statement isn't finished yet). Also, be sure to start the next line with a quote symbol:
	var longString = "One piece " + "plus one " +
	"more piece.";
Additionally, whitespace outside of the quoted string is ignored. Thus, if you wish to format the source code for improved readability, you can even indent the second line without affecting the content of the string value:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Improving String Handling Performance
You wish to improve the execution speed of routines manipulating large amounts of text.
Use a JavaScript array as a temporary storage device when accumulating large chunks of text. The push() method of an array object allows you to assemble individual text blocks in the desired order—the method appends to the end of the array. When it comes time to use the full text (e.g., to assign a large string of HTML code to the innerHTML property of an element object), use the join() method of the array object, specifying an empty string as the delimiter character.
Although the technique is intended for large text blocks, the following example uses small strings to demonstrate the sequence:
	var txtArray = new Array();
	txtArray.push("<tr>");
	txtArray.push("<td>Boston</td><td>24</td><td>10</td><td>Partly Cloudy</td>");
	txtArray.push("</tr>");
	txtArray.push("<tr>");
	txtArray.push("<td>New York</td><td>21</td><td>14</td><td>Snow</td>");
	txtArray.push("</tr>");
	document.getElementById("weatherTBody").innerHTML = txtArray.join("");
	txtArray = null;
The sequence ends by emptying the array so that the browser will free up memory occupied by the array.
String concatenation, especially when it involves either large amounts of text or an inordinate amount of pieces being stitched together via the add-by-value (+=) operator, can be a performance hog in browsers. You may never notice the problem if your strings are not very large, but the signs start to appear when you use standard string concatenation in repeat loops that assemble huge strings. These situations are excellent candidates for using an array as the temporary string data holder. Scripts typically execute array manipulation with much better performance than string manipulation.
Note that, just as with strings, your code is responsible for handling details, such as spaces between words in joined text. If spaces are needed, they should go in the text being pushed onto the end of the array. Alternatively, if a space is needed between absolutely every string stored in the array, you can specify a space character as the parameter to the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Accessing Substrings
You want to obtain a copy of a portion of a string.
Use the substring() method (in all scriptable browsers) to copy a segment starting at a particular location and ending either at the end of the string (omitting the second parameter does that) or at a fixed position within the string, counting from the start of the string:
	var myString = "Every good boy does fine.";
	var section = myString.substring(0, 10);   // section is now "Every good"
Use the slice() method (in IE 4 or later and all modern scriptable browsers) to set the end position at a point measured from the end of the string, using a negative value as the second parameter:
	var myString = "Every good boy does fine.";
	var section = myString.slice(11, -6);      // section is now "boy does"
Use the nonstandard, but widely supported, variant called substr() to copy a segment starting at a particular location for a string length (the second parameter is an integer representing the length of the substring):
	var myString = "Every good boy does fine.";
	var section = myString.substr(6, 4);       // section is now "good"
If the sum of the two arguments exceeds the length of the string, the method returns a string from the start point to the end of the string.
Parameters for the ECMA-compatible slice() and substring() methods are numbers that indicate the zero-based start and end positions within the string from which the extract comes. The first parameter, indicating the start position, is required. When you use two positive integer values for the slice() method arguments (and the first argument is smaller than the second), you receive the same string value as the substring() method with the same arguments.
Note that the integer values for substring() and slice() act as though they point to spaces between characters. Therefore, when a substring() method's arguments are set to 0 and 4, it means that the substring starts to the right of the "zeroeth" position and ends to the left of the fourth position; the length of the string value returned is four characters, as shown in .
Figure 1-1: How substring end points are calculated
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Changing String Case
You want to convert a string to all upper- or lowercase letters.
Use the two dedicated String object methods, toLowerCase() and toUpperCase(), for case changes:
	var myString = "New York";
	var lcString = myString.toLowerCase();
	var ucString = myString.toUpperCase();
Both methods return modified copies of the original string, leaving the original intact. If you want to replace the value of a variable with a case-converted version of the original string (and thus eliminate the original string), reassign the results of the method to the same variable:
	myString = myString.toLowerCase();
Do not, however, redeclare the variable with a var keyword.
Because JavaScript strings (like just about everything else in the language) are casesensitive, it is common to use case conversion for tasks such as testing the equivalency of a string entered into a text box by a user against a known string in your code. Because the user might include a variety of case variations in the entry, you need to guard against unorthodox entries by converting the input text to all uppercase or all lowercase letters for comparison (see ).
Another common need for case conversion is preparing user entries for submission to a database that prefers or requires all uppercase (or all lowercase) letters. You can accomplish this for a user either at the time of entry or during batch validation prior to submission. For example, an onchange event handler in a text box can convert the text to all uppercase letters as follows:
	<input type="text" name="firstName" id="firstName" size="20" maxlength="25"
	   onchange="this.value=this.value.toUpperCase()" />
Simply reassign a converted version of the element's value to itself.
for a practical example of case conversion simplifying an important string task.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Testing Equality of Two Strings
You want to compare a user's text entry against a known string value.
Convert the user input to either all uppercase or all lowercase characters, and then use the JavaScript equality operator to make the comparison:
	if (document.myForm.myTextBox.value.toLowerCase() == "new york") {
	    // process correct entry }
By using the results of the case conversion method as one of the operands of the equality expression, you do not modify the original contents of the text box. (See if you want to convert the text in the text box to all of one case.)
JavaScript has two types of equality operators. The fully backward-compatible, standard equality operator (==) employs data type conversion in some cases when the operands on either side are not of the same data type. Consider the following variable assignments:
	var stringA = "My dog has fleas.";
	var stringB = new String("My dog has fleas.");
These two variables might contain the same series of characters but are different data types. The first is a string value, while the second is an instance of a String object. If you place these two values on either side of an equality (==) operator, JavaScript tries various evaluations of the values to see if there is a coincidence somewhere. In this case, the two variable values would show to be equal, and the following expression:
	stringA == stringB
returns true.
But the other type of equality operator, the strict equality operator (===), performs no data type conversions. Given the variable definitions above, the following expression evaluates to false because the two object types differ, even though their payloads are the same:
	stringA === stringB
If the logic of your code requires you to test for the inequality of two strings, you can use the inequality (!=) and strict inequality (!==) operators. For example, if you want to process an incorrect entry, the branching flow of your function would be like the following:
	if (document.getElementById("myTextBox").value.toLowerCase() != "new york") {
	    // process incorrect entry
	}
The same data type conversion issues apply to the inequality and strict inequality operators as to their opposite partners.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Testing String Containment Without Regular Expressions
You want to know if one string contains another, without using regular expressions.
Use the JavaScript indexOf() string method on the longer string section, passing the shorter string as an argument. If the shorter string is inside the larger string, the method returns a zero-based indexinteger of the start position of the smaller string within the larger string. If the shorter string is not in the larger string, the method returns –1.
For logic that needs to branch if the smaller string is not contained by the larger string, use the following construction:
	if (largeString.indexOf(shortString) == -1) {
	    // process due to missing shortString
	}
For logic that needs to branch if the smaller string is contained somewhere within the larger string, use the following construction:
	if (largeString.indexOf(shortString) != -1) {
	    // process due to found shortString
	}
In either case, you are not interested in the precise position of the short string but simply whether it is anywhere within the large string.
You may also find the integer returned by the indexOf() method to be useful in a variety of situations. For example, an event handler function that gets invoked by all kinds of elements in the event-propagation (bubbling) chain wants to process events that come only from elements whose IDs begin with a particular sequence of characters. This is an excellent spot to look for the returned value of zero, pointing to the start of the larger string:
	function handleClick(evt) {
	    var evt = (evt) ? evt : ((window.event) ? window.event : null);
	    if (evt) {
	        var elem = (evt.target) ? evt.target : ((evt.srcElement) ?
	            evt.srcElement : null);
	        if (elem && elem.id.indexOf("menuImg") == 0) {
	            // process events from elements whose IDs begin with "menuImg"
	        }
	    }
	}
Be aware that if the larger string contains multiple instances of the shorter string, the indexOf() method returns a pointer only to the first instance. If you're looking to count the number of instances, you can take advantage of the indexOf() method's optional second parameter, which specifies the starting position for the search. A compact repeat loop can count up the instances quickly:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Testing String Containment with Regular Expressions
You want to use regular expressions to know whether one string contains another.
Create a regular expression with the short string (or pattern) and the global (g) modifier. Then pass that regular expression as a parameter to the match() method of a string value or object:
	var re = /a string literal/g;
	var result = longString.match(re);
When a global modifier is attached to the regular expression pattern, the match() method returns an array if one or more matches are found in the longer string. If there are no matches, the method returns null.
To work this regular expression mechanism into a practical function, you need some helpful surrounding code. If the string you are looking for is in the form of a string variable, you can't use the literal syntaxfor creating a regular expression as just shown. Instead, use the constructor function:
	var shortStr = "Framistan 2000";
	var re = new RegExp(shortStr, "g");
	var result = longString.match(re);
After you have called the match() method, you can inspect the contents of the array value returned by the method:
	if (result) {
	    alert("Found " + result.length + " instances of the text: " + result[0]);
	} else {
	    alert("Sorry, no matches.");
	}
When matches exist, the array returned by match() contains the found strings. When you use a fixed string as the regular expression pattern, these returned values are redundant. That's why it's safe in the previous example to pull the first returned value from the array for display in the alert dialog box. But if you use a regular expression pattern involving the symbols of the regular expression language, each of the returned strings could be quite different, but equally valid because they adhere to the pattern.
As long as you specify the g modifier for the regular expression, you may get multiple matches (instead of just the first). The length of the array indicates the number of matches found in the longer string. For a simple containment test, you can omit the g modifier; as long as there is a match, the returned value will be an array of length 1.
"Regular Expressions" in the introduction to this chapter; for using regular expressions in form field validations.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Searching and Replacing Substrings
You want to perform a global search-and-replace operation on a text string.
The most efficient way is to use a regular expression with the replace() method of the String object:
	var re = /a string literal/g;
	var result = mainString.replace(re, replacementString);
Invoking the replace() method on a string does not change the source (original) string. Capture the changed string returned by the method, and apply the result where needed in your scripts or page. If no replacements are made, the original string is returned by the method. Be sure to specify the g modifier for the regular expression to force the replace() method to operate globally on the original string; otherwise, only the first instance is replaced.
To work this regular expression mechanism into a practical function, you need some helpful surrounding code. If the string you are looking for is in the form of a string variable, you can't use the literal syntaxfor creating a regular expression as just shown. Instead, use the constructor function:
	var searchStr = "F2K";
	var replaceStr = "Framistan 2000";
	var re = new RegExp(searchStr , "g");
	var result = longString.replace(re, replaceStr);
In working with a text-based form control or an element's text node, you can perform the replace() operation on the value of the existing text, and immediately assign the results back to the original container. For example, if a div element contains one text node with scattered place holders in the form of (ph), and the job of the replace() method is to insert a user's entry from a text box (called myName), the sequence is as follows:
	var searchStr = "\\(ph\\)";
	var re = new RegExp(searchStr, "g");
	var replaceStr = document.getElementById("myName").value;
	var div = document.getElementById("boilerplate");
	div.firstChild.nodeValue = div.firstChild.nodeValue.replace(re, replaceStr);
The double backslashes are needed to escape the escape character before the parentheses characters, which are otherwise meaningful symbols in the regular expression pattern language.
It is also possible to implement a search-and-replace feature without regular expressions, but it's a cumbersome exercise. The technique involves substantial text parsing using the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using Special and Escaped Characters
You want to add low-order ASCII characters (tab, carriage return, etc.) to a string.
Use the escape sequences shown in to represent the desired character. For example, to include a quotation mark inside a literal string, use \", as in:
	var msg = "Today's secret word is \"thesaurus.\"";
The core JavaScript language includes a feature common to most programming languages that lets you designate special characters. A special character is not one of the plain alphanumeric characters or punctuation symbols, but has a particular meaning with respect to whitespace in text. Common characters used these days include the tab, newline, and carriage return.
A special character begins with a backslash, followed by the character representing the code, such as \t for tab and \n for newline. The backslash is called an escape character, instructing the interpreter to treat the next character as a special character. To include these characters in a string, include the backslash and special character inside the quoted string:
	var confirmString = "You did not enter a response to the last " +
	    "question.\n\nSubmit form anyway?";
If you want to use one of these symbols between variables that contain string values, be sure the special character is quoted in the concatenation statement:
	var myStr = lineText1 + "\n" + lineText2;
Special characters can be used to influence formatting of text in basic dialog boxes (from the alert(), confirm(), and prompt() methods of the window object) and textarea form controls. shows the recognized escaped characters and their meanings.
Table 1-2: String escape sequences
Escape sequence
Description
\b
Backspace
\t
Horizontal tab (ASCII 9)
\n
Line feed (newline, ASCII 10)
\v
Vertical tab
\f
Form feed
\r
Carriage return (ASCII 13)
\"
Double quote
\'
Single quote
\\
Backslash
Note that to include a visible backslash character in a string, you must use a double backslash because a single one is treated as the invisible escape character. Use the escaped quote symbols to include single or double quotes inside a string.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Reading and Writing Strings for Cookies
You want to use cookies to preserve string data from one page visit to the next.
Use the cookies.js library shown in the Discussion as a utility for saving and retrieving cookies in modern browsers. To set a cookie via the library, invoke the setCookie() function, passing, at a minimum, the cookie's name and string value as arguments:
	setCookie("userID", document.entryForm.username.value);
To retrieve a cookie's value, invoke the library's getCookie() function, as in:
	var user = getCookie("userID");
shows the code for the entire cookies.js library.
Example 1-1. cookies.js library
// utility function to retrieve an expiration date in proper
// format; pass three integer parameters for the number of days, hours,
// and minutes from now you want the cookie to expire (or negative
// values for a past date); all three parameters are required,
// so use zeros where appropriate
function getExpDate(days, hours, minutes) {
    var expDate = new Date();
    if (typeof days == "number" && typeof hours == "number" &&
        typeof minutes == "number") {
        expDate.setDate(expDate.getDate() + parseInt(days));
        expDate.setHours(expDate.getHours() + parseInt(hours));
        expDate.setMinutes(expDate.getMinutes() + parseInt(minutes));
        return expDate.toUTCString();
    }
}

// utility function called by getCookie()
function getCookieVal(offset) {
    var endstr = document.cookie.indexOf (";", offset);
    if (endstr == -1) {
        endstr = document.cookie.length;
    }
    return decodeURI(document.cookie.substring(offset, endstr));
}

// primary function to retrieve cookie by name
function getCookie(name) {
    var arg = name + "=";
    var alen = arg.length;
    var clen = document.cookie.length;
    var i = 0;
    while (i < clen) {
        var j = i + alen;
        if (document.cookie.substring(i, j) == arg) {
            return getCookieVal(j);
        }
        i = document.cookie.indexOf(" ", i) + 1;
        if (i == 0) break;
    }
    return "";
}

// store cookie value with optional details as needed
function setCookie(name, value, expires, path, domain, secure) {
    document.cookie = name + "=" + encodeURI(value) +
        ((expires) ? "; expires=" + expires : "") +
        ((path) ? "; path=" + path : "") +
        ((domain) ? "; domain=" + domain : "") +
        ((secure) ? "; secure" : "");
}

// remove the cookie by setting ancient expiration date
function deleteCookie(name,path,domain) {
    if (getCookie(name)) {
        document.cookie = name + "=" +
            ((path) ? "; path=" + path : "") +
            ((domain) ? "; domain=" + domain : "") +
            "; expires=Thu, 01-Jan-70 00:00:01 GMT";
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Converting Between Unicode Values and String Characters
You want to obtain the Unicode code number for an alphanumeric character or vice versa.
To obtain the Unicode value of a character of a string, use the charCodeAt() method of the string value. A single parameter is an integer pointing to the zero-based position of the character within the string:
	var code = myString.charCodeAt(3);
If the string consists of only one character, use the 0 argument to get the code for that one character:
	var oneChar = myString.substring(12, 13);
	var code = oneChar.charCodeAt(0);
The returned value is an integer.
To convert a Unicode code number to a character, use the fromCharCode() method of the static String object:
	var char = String.fromCharCode(66);
Unlike most string methods, this one must be invoked only from the String object and not from a string value.
ASCII values and Unicode values are the same for the basic Latin alphanumeric (low-ASCII) values. But even though Unicode encompasses characters from many written languages around the world, do not expect to see characters from other writing systems displayed in alert boxes, text boxes, or rendered pages simply because you know the Unicode values for those characters; the browser and operating system must be equipped for the language encompassed by the characters. If the character sets are not available, the characters generated by such codes will be question marks or other symbols. A typical North American computer won't know how to produce a Chinese character on the screen unless the target writing system and font sets are installed for the OS and browser.
for other ways to extract single-character substrings.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Encoding and Decoding URL Strings
You want to convert a string of plain text to a format suitable for use as a URL or URL search string, or vice versa.
To convert a string consisting of an entire URL to a URL-encoded form, use the encodeURI() global method, passing the string needing conversion as an argument. For example:
	document.myForm.action = encodeURI(myString);
If you are assembling content for values of search string name/value pairs, apply the encodeURIComponent() global method:
	var srchString = "?name=" + encodeURIComponent(myString);
Both methods have complementary partners that perform conversions in the opposite direction:
	decodeURI(encodedURIString)
	decodeURIComponent(encodedURIComponentString)
In all cases, the original string is not altered when passed as an argument to these methods. Capture the results from the value returned by the methods.
Although the escape() and unescape() methods have been available since the first scriptable browsers, they have been deprecated in the formal language specification (ECMA-262) in favor of a set of new methods. The new methods are available in IE 5.5 or later and other modern browsers.
These new encoding methods work by slightly different rules than the old escape() and unescape() methods. As a result, you must encode and decode using the same pairs of methods at all times. In other words, if a URL is encoded with encodeURI(), the resulting string can be decoded only with decodeURI().
The method names use "URI" (Universal Resource Identifier). A URI is an all-encompassing reference to obtain any network-accessible item (document, object, etc.). A URL (Universal Resource Locator) is a type of URI that includes both a network location for the item, as well as an indication of the access mechanism (e.g., http:). That the method names adopt the more general URI nomenclature is not unusual. For most client-side web authoring in HTML, CSS, and JavaScript, the terms URI and URL are interchangeable.
The differences between encodeURI() and encodeURIComponent() are defined by the range of characters that the methods convert to the URI-friendly form of a percent sign (
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Encoding and Decoding Base64 Strings
You want to convert a string to or from Base64 encoding.
Use the functions of the base64.js library shown in the Discussion. Syntaxfor invoking the two functions is straightforward. To encode a string, invoke:
	var encodedString = base64Encode("stringToEncode");
To decode a string, invoke:
	var plainString = base64Decode("encodedString");
shows the entire base64.js library.
Example 1-2. base64.js library
// Global lookup arrays for base64 conversions
var enc64List, dec64List;

// Load the lookup arrays once
function initBase64() {
    enc64List = new Array();
    dec64List = new Array();
    var i;
    for (i = 0; i < 26; i++) {
        enc64List[enc64List.length] = String.fromCharCode(65 + i);
    }
    for (i = 0; i < 26; i++) {
        enc64List[enc64List.length] = String.fromCharCode(97 + i);
    }
    for (i = 0; i < 10; i++) {
        enc64List[enc64List.length] = String.fromCharCode(48 + i);
    }
    enc64List[enc64List.length] = "+";
    enc64List[enc64List.length] = "/";
    for (i = 0; i < 128; i++) {
        dec64List[dec64List.length] = -1;
    }
    for (i = 0; i < 64; i++) {
        dec64List[enc64List[i].charCodeAt(0)] = i;
    }
}

// Encode a string
function base64Encode(str) {
    var c, d, e, end = 0;
    var u, v, w, x;
    var ptr = -1;
    var input = str.split("");
    var output = "";
    while(end == 0) {
        c = (typeof input[++ptr] != "undefined") ? input[ptr].charCodeAt(0) :
            ((end = 1) ? 0 : 0);
        d = (typeof input[++ptr] != "undefined") ? input[ptr].charCodeAt(0) :
            ((end += 1) ? 0 : 0);
        e = (typeof input[++ptr] != "undefined") ? input[ptr].charCodeAt(0) :
            ((end += 1) ? 0 : 0);
        u = enc64List[c >> 2];
        v = enc64List[(0x00000003 & c) << 4 | d >> 4];
        w = enc64List[(0x0000000F & d) << 2 | e >> 6];
        x = enc64List[e & 0x0000003F];

        // handle padding to even out unevenly divisible string lengths
        if (end >= 1) {x = "=";}
        if (end == 2) {w = "=";}
        if (end < 3) {output += u + v + w + x;}
    }
    // format for 76-character line lengths per RFC
    var formattedOutput = "";
    var lineLength = 76;
    while (output.length > lineLength) {
        formattedOutput += output.substring(0, lineLength) + "\n";
        output = output.substring(lineLength);
    }
    formattedOutput += output;
    return formattedOutput;
}

// Decode a string
function base64Decode(str) {
    var c=0, d=0, e=0, f=0, i=0, n=0;
    var input = str.split("");
    var output = "";
    var ptr = 0;
    do {
        f = input[ptr++].charCodeAt(0);
        i = dec64List[f];
        if ( f >= 0 && f < 128 && i != -1 ) {
            if ( n % 4 == 0 ) {
                c = i << 2;
            } else if ( n % 4 == 1 ) {
                c = c | ( i >> 4 );
                d = ( i & 0x0000000F ) << 4;
            } else if ( n % 4 == 2 ) {
                d = d | ( i >> 2 );
                e = ( i & 0x00000003 ) << 6;
            } else {
                e = e | i;
            }
            n++;
            if ( n % 4 == 0 ) {
                output += String.fromCharCode(c) +
                          String.fromCharCode(d) +
                          String.fromCharCode(e);
            }
        }
    } while (typeof input[ptr] != "undefined");
    output += (n % 4 == 3) ? String.fromCharCode(c) + String.fromCharCode(d) :
              ((n % 4 == 2) ? String.fromCharCode(c) : "");
    return output;
}

// Self-initialize the global variables
initBase64();
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Numbers and Dates
Designers of friendly scripting languages might have nonprogrammers in mind when they first define the scope of their languages, but it's difficult for any such language to be taken seriously by professional programmers unless some of the nerdy basics are there. Math may be anathema to scripters not schooled in computer science, but even an accessible language such as JavaScript has a solid complement of features to accommodate the kinds of arithmetic, trigonometric, and other operations typically supported by a programming language. Date manipulation—also numerically intensive, as it turns out—is well supported in JavaScript as well. This chapter includes recipes for both of these areas.
For most scripters, the interior details about how JavaScript treats numbers is of little importance. In fact, the more you know about programming languages and different types of numbers, the more you need to forget in order to use JavaScript numbers. Unlike other languages, JavaScript has only one kind of number data type. All integers and floating-point values are represented by the same data type in JavaScript: number.
Internally, a JavaScript number is an IEEE double-precision 64-bit value. JavaScript provides a usable range of number values from 2.2E-208 to 1.79E+308 (boundary values obtainable by the static Number object properties Number.MIN_VALUE and Number.MAX_VALUE, respectively). JavaScript treats numbers beyond these limits as infinity, represented by Number.NEGATIVE_INFINITY and Number.POSITIVE_INFINITY. It is unlikely that you will ever refer to these four properties in your scripts, but the language has them for the sake of completeness.
Number values do not carry any formatting with them. If a value needs places to the right of the decimal to signify a fractional part of an integer, those places are there. But if a variable that once held a number with 10 digits to the right of the decimal is modified through an arithmetic operation to become an integer, the decimal and zeros to the right of the decimal disappear.
As with JavaScript strings (see ), numbers are most commonly values (of data type
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Introduction
Designers of friendly scripting languages might have nonprogrammers in mind when they first define the scope of their languages, but it's difficult for any such language to be taken seriously by professional programmers unless some of the nerdy basics are there. Math may be anathema to scripters not schooled in computer science, but even an accessible language such as JavaScript has a solid complement of features to accommodate the kinds of arithmetic, trigonometric, and other operations typically supported by a programming language. Date manipulation—also numerically intensive, as it turns out—is well supported in JavaScript as well. This chapter includes recipes for both of these areas.
For most scripters, the interior details about how JavaScript treats numbers is of little importance. In fact, the more you know about programming languages and different types of numbers, the more you need to forget in order to use JavaScript numbers. Unlike other languages, JavaScript has only one kind of number data type. All integers and floating-point values are represented by the same data type in JavaScript: number.
Internally, a JavaScript number is an IEEE double-precision 64-bit value. JavaScript provides a usable range of number values from 2.2E-208 to 1.79E+308 (boundary values obtainable by the static Number object properties Number.MIN_VALUE and Number.MAX_VALUE, respectively). JavaScript treats numbers beyond these limits as infinity, represented by Number.NEGATIVE_INFINITY and Number.POSITIVE_INFINITY. It is unlikely that you will ever refer to these four properties in your scripts, but the language has them for the sake of completeness.
Number values do not carry any formatting with them. If a value needs places to the right of the decimal to signify a fractional part of an integer, those places are there. But if a variable that once held a number with 10 digits to the right of the decimal is modified through an arithmetic operation to become an integer, the decimal and zeros to the right of the decimal disappear.
As with JavaScript strings (see ), numbers are most commonly values (of data type
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Converting Between Numbers and Strings
You want to change a number data type to a string data type, or vice versa.
To convert a number value to a string value, use the toString() method of a number value:
	var numAsStringValue = numValue.toString();
You can also create an instance of a String object by passing the number as an argument to the String object constructor:
	var numAsStringObject = new String(numValue);
To convert a string to a number, use the parseInt() global method if the desired result is an integer only, or the parseFloat() global method if the number could be or is definitely a floating-point number:
	var intValue = parseInt(numAsString, 10);
	var floatValue = parseFloat(numAsString);
If you use parseFloat() and the number passed as an argument is an integer, the result will also be formatted as an integer, without a decimal and trailing zero. Both the parseInt() and parseFloat() functions work with all scriptable browser versions.
In many cases, the JavaScript interpreter tries to cast values between number and string data types automatically. For example, if you multiply a number times a string version of the number, the string is automatically converted to a number value, and the operation succeeds. This kind of casting doesn't always work, however. For instance, the addition (+) operator plays two roles in JavaScript: adding numbers and concatenating strings. When you place this operator between a number and a number that is actually a string value, the string wins the battle, and the two numbers get concatenated together as a string. Thus, the expression 2 + "2" equals "22" in JavaScript.
Most commonly, you need to convert a string to a numeric value when you perform math operations on values entered by the user in form text boxes. The value property of any text field supplies the data as a string value. To add values from two text boxes to fill a third requires converting each operand to a number before doing the math. Then you can assign the resulting number value to the value property of the third text box, where the number automatically converts to a string value because that's the only data type acceptable in a text box. For example:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Testing a Number's Validity
You want to be sure a value is a number before performing a math operation on it.
If the value you're testing can come from any kind of source, the safest bet is to use the typeof operator on the value. Applying this operator to any numeric value evaluates to the string number. Therefore, using it in a conditional expression looks like this:
	if (typeof someVal == "number") {
	    // OK, operate on the value numerically
	}
But some JavaScript methods, such as parseInt() and parseFloat(), return a special value, NaN ("Not a Number"), signifying that they were unable to derive the number you desired. Operations expecting numeric operands or arguments that encounter values evaluating to NaN also generally return NaN. To test for this condition, use the isNaN() method, which returns true if the value is not a number. For example:
	var myVal = parseInt(document.getElementById("myAge").value);
	if (isNaN(myVal)) {
	    alert("Please check the Age text box entry.");
	} else {
	    // OK, operate on the value numerically
	}
Don't get the wrong impression about the isNaN() method from the second example just shown. It is not a suitable approach to validating numeric input to a text box. That's because the parseInt() and parseFloat() methods return the first numbers (if any) they encounter in the string value passed as an argument. If someone enters 32G into a text box intended for an age, the parseInt() method pulls off the 32 portion, but the full value of the text box is not valid for your database that expects a strictly numeric value for that field. See for more robust ways of validating numeric text entries.
You don't have to perform validity testing on absolutely every value about to undergo a math operation. Most values in your scripts tend to be under strict control of the programmer, allowing data-typing kinks to be worked out before the script is put into production. You need to exercise care, however, whenever user input enters the equation.
Look to the NaN value as a debugging aid. If some calculation is failing, use alert dialog boxes or debuggers to show the values of the operands and components. Any value that reports itself to be
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Testing Numeric Equality
You want to know whether two numeric values are equal (or not equal) before continuing processing.
Use the standard equality operator (==) in a conditional statement:
	if (firstNum == secondNum) {
	    // OK, the number values are equal
	}
Values on either side of the equality operator may be variables or numeric literals. Typical practice places the suspect value to the left of the operator, and the fixed comparison on the right.
JavaScript has two types of equality operators. The fully backward-compatible, standard equality operator (==) employs automatic data type conversion in some cases when the operands on either side are not of the same data type. Consider the following variable assignments:
	
	var numA = 45;
	var numB = new Number(45);
These two variables might contain the same numeric value, but they are different data types. The first is a number value, while the second is an instance of a Number object. If you place these two values on either side of an equality (==) operator, JavaScript tries various evaluations of the values to see if there is a coincidence somewhere. In this case, the two variable values would show to be equal, and the following expression:
	numA == numB
returns true.
But the other type of equality operator, the strict equality operator (===), performs no data type conversions. Given the variable definitions above, the following expression evaluates to false because the two object types differ, even though their payloads are the same:
	numA === numB
If one equality operand is an integer and the other is the same integer expressed as a floating-point number (such as 4 and 4.00), both kinds of equality operators find their values and data types to be equal. A number is a number in JavaScript.
If the logic of your code requires you to test for the inequality of two numbers, you can use the inequality (!=) and strict inequality (!==) operators. For example, if you want to process an entry for a special value, the branching flow of your function would be like the following:
	if (parseInt(document.getElementById("myTextBox").value) != 0) {
	    // process entry for non-zero values
	}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Rounding Floating-Point Numbers
You want to round a floating-point value to the nearest whole number.
Use the Math.round() method on the value:
	var roundedVal = Math.round(floatingPointValue);
The operation does not disturb the original value. Capture the rounded result in a variable.
The Math.round() method uses the following algorithm: any floating-point value that is greater than or equal to x.5 is rounded up to x+1; otherwise, the returned value is x.
JavaScript's Math object contains some other useful methods for trimming floating-point numbers of their fractional parts. Math.floor() and Math.ceil() return the next lowest and next highest integer values, respectively. For example, Math.floor(3.25) returns 3, while Math.ceil(3.25) returns 4. With negative values, the rules still apply, but the results seem backward at first glance: Math.floor(-3.25) returns the next lowest integer, -4; Math.ceil(-3.25) returns -3. For positive values, you can use the Math.floor() method as a substitute for what some other languages treat as obtaining the integer part of a number.
Anytime a floating-point number evaluates to a number equal to an integer value, the decimal and digits to the right of the decimal go away. A variable can hold a floating-point number in one statement and be modified to an integer in the next. This drives some programmers crazy because they were indoctrinated by other languages to treat each type of number as a different data type.
"The Math Object" in the introduction to this chapter.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Formatting Numbers for Text Display
You want to display the results of numeric calculations with a fixed number of digits to the right of the decimal.
Two global methods of the JavaScript language (and ECMA standard) simplify the display of numbers with a specific number of digits. These methods are implemented in IE 5.5 or later for Windows and other modern browsers (Mozilla, Safari, and Opera). To obtain a string containing a number with digits to the right of the decimal, use the toFixed() method, as in the following:
	document.getElementById("total").value = someNumber.toFixed(2);
The argument to the toFixed() method is the number of digits to the right of the decimal. Even if the number is an integer, the resulting string has a decimal and two zeros to the right of the decimal.
To obtain a string containing a number with a total fixed number of digits, use the toPrecision() method, as in the following:
	document.getElementById("rate").value = someNumber.toPrecision(5);
The argument to the toPrecision() method is the total number of digits in the returned string value, including digits to the left and right of the decimal (the decimal is not counted). If the original value has fewer digits than the method argument calls for, the result is padded with zeros to the right of the decimal; an argument smaller than the number of integer digits yields a value in scientific notation. Here are some examples:
	var num = 123.45;
	preciseNum = num.toPrecision(7);           // preciseNum is now 123.4500
	preciseNum = num.toPrecision(4);           // preciseNum is now 123.5
	preciseNum = num.toPrecision(3);           // preciseNum is now 123
	preciseNum = num.toPrecision(2);           // preciseNum is now 1.2e+2
For older browsers, number formatting is a more cumbersome process, but one that can be encapsulated in the formatNumber() utility function shown in the Discussion. Invoke the function by passing either a number or string that can be cast to a number and an integer signifying the number of places to the right of the decimal for the returned string:
	document.myForm.total.value = formatNumber(someNumber, 2);
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Converting Between Decimal and Hexadecimal Numbers
You want to change a decimal number to its hexadecimal equivalent, and vice versa.
The core JavaScript language provides facilities for going from hexadecimal to decimal and back again, but through two separate mechanisms.
To get a hexadecimal number as a string into its decimal equivalent, use the parseInt() method and specify the second parameter as 16:
	var decimalVal = parseInt(myHexNumberValue, 16);
For myHexNumberValue, you can use either the hexadecimal characters for the number, or the format required for hexadecimal arithmetic in JavaScript: the hexadecimal characters preceded by 0x or 0X (a zero followed by an X). Here are some examples with string literals in the two formats:
	var decimalVal = parseInt("1f", 16);
	var decimalVal = parseInt("0x1f", 16);
To convert a decimal number to a hexadecimal string equivalent, use the toString() method of the Number object, specifying base 16 as the argument:
	var hexVal = (255).toString(16)     // result = "ff"
Because JavaScript automatically converts hexadecimal numbers to their decimal equivalents for arithmetic operations, the hexadecimal conversion is needed only for display of a hexadecimal result.
Hexadecimal arithmetic isn't used much in JavaScript, but the language provides rudimentary support for base 16 numbers. As long as you signify a hexadecimal number value with the leading 0x, you can perform regular arithmetic on that value to your heart's content. But be aware that the results of those operations are returned in base 10, which allows the odd possibility of using hexadecimal and decimal values in the same expression:
	var result = 0xff - 200;
Hexadecimal digits a through f may be expressed in your choice of upper-or lower-case letters.
The parseInt() method is frequently a handy tool for getting values in other bases into decimal. For example, you obtain a decimal equivalent of a binary number string by specifying base 2 as the second argument of the method:
	var decimalVal = parseInt("11010011", 2);
Converting in the other direction (from decimal to other bases) is aided by the toString() method that you can apply to any number value (not string values). This works not only for hexadecimal values, as shown earlier, but for octal (base 8) and binary (base 2) values as well:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Generating Pseudorandom Numbers
Content preview·Buy PDF of this chapter|