Cover | Table of Contents | Colophon
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.
var myString = "Fluffy is a pretty cat.";
var myString = "Fluffy is a pretty cat."; var myString = 'Fluffy is a pretty cat.';
var myString = "Fluffy is a pretty cat.';
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.
var myString = "Fluffy is a pretty cat.";
var myString = "Fluffy is a pretty cat."; var myString = 'Fluffy is a pretty cat.';
var myString = "Fluffy is a pretty cat.';
+) operator to
concatenate multiple string values:
var longString = "One piece " + "plus one more piece.";
+=) operator:
var result = ""; result += "My name is " + document.myForm.myName.value; result += " and my age is " + document.myForm.myAge.value;
result = result + "My name is " + document.myForm.myName.value;
var longString = "One piece " + "plus one more piece.";
var longString = "One piece " + "plus one;
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"
slice( )
method (in NN 4 or later and IE 4 or
later) 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"
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"
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.
substring( ) and
slice( ) act as though they point to spaces
between characters. Therefore, when a String object methods,
toLowerCase( )
and toUpperCase(
)
, for case changes:
var myString = "New York"; var lcString = myString.toLowerCase( ); var ucString = myString.toUpperCase( );
myString = myString.toLowerCase( );
var
keyword.
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( )" />
if (document.myForm.myTextBox.value.toLowerCase( ) = = "new york") {
// process correct entry
}
=
=) 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.");
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
true.= = =), 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
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
index integer 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.
if (largeString.indexOf(shortString) = = -1) {
// process due to missing shortString
}
if (largeString.indexOf(shortString) != -1) {
// process due to found shortString
}
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"
}
}
}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);
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.
var shortStr = "Framistan 2000"; var re = new RegExp(shortStr, "g"); var result = longString.match(re);
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.");
}
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.
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
replace(
)
method of the String
object:
var re = /a string literal/g; var result = mainString.replace(re, replacementString);
replace( ) method on a string does
not change the source 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.
var searchStr = "F2"; var replaceStr = "Framistan 2000"; var re = new RegExp(searchStr , "g"); var result = longString.replace(re, replaceStr);
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.myForm.myName.value;
var div = document.getElementById("boilerplate");
div.firstChild.nodeValue = div.firstChild.nodeValue.replace(re, replaceStr);\', as in:
var msg = "Welcome to Joe\'s Diner.";
\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. Table 1-2 shows the recognized escape sequence
characters and their meanings. 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?";
var myStr = lineText1 + "\n" + lineText2;
alert( ),
confirm( ), and prompt( )
methods) and textarea form controls.
setCookie(
)
function, passing, at a minimum, the
cookie's name and string value as arguments:
setCookie ("userID", document.entryForm.username.value);
getCookie( ) function,
as in:
var user = getCookie("userID");
// 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.toGMTString( );
}
}
// utility function called by getCookie( )
function getCookieVal(offset) {
var endstr = document.cookie.indexOf (";", offset);
if (endstr = = -1) {
endstr = document.cookie.length;
}
return unescape(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 + "=" + escape (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";
}
}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);
0 argument to get the code for that one character:
var oneChar = myString.substring(12, 13); var code = oneChar.charCodeAt(0);
fromCharCode( )
method of the static
String object:
var char = String.fromCharCode(66);
String object and not from a string value.
encodeURI(
)
method, passing the string needing
conversion as an argument. For example:
document.myForm.action = encodeURI(myString);
encodeURIComponent(
)
method:
var srchString = "?name=" + encodeURIComponent(myString);
decodeURI(encodedURIString) decodeURIComponent(encodedURIComponentString)
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 for Windows and
Netscape 6 or later.
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( ).
encodeURI( ) and
encodeURIComponent( ) are defined by the range of
characters that the methods convert to the URI-friendly form of a
percent sign (%) followed by the hexadecimal
Unicode value of the symbol (e.g., a space becomes
var encodedString = base64Encode("stringToEncode");
var plainString = base64Decode("encodedString");
// 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( );number
.
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
.
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.
toString(
)
method of a number value:
var numAsStringValue = numValue.toString( );
String object
by passing the number as an argument to the String
object constructor:
var numAsStringObject = new String(numValue);
parseInt(
)
method if the desired result is an
integer only, or the parseFloat(
)
method if the number could be or is
definitely a floating-point number:
var intValue = parseInt(numAsString, 10); var floatValue = parseFloat(numAsString);
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.
+)
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.
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
}
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.myForm.myAge.value);
if (isNaN(myVal)) {
alert("Please check the Age text box entry.");
} else {
// OK, operate on the value numerically
}
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(
) or 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 Recipe 8.2 for more robust ways of
validating numeric text entries.
=
=) in a conditional statement:
if (firstNum = = secondNum) {
// OK, the number values are equal
}
=
=) 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);
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
true.= = =), 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
Math.round(
)
method on the value:
var roundedVal = Math.round(floatingPointValue);
Math.round( ) method uses
is that 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.
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 the integer of a number.
toFixed(
)
method, as in the following:
document.myForm.total.value = someNumber.toFixed(2);
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.
toPrecision(
)
method, as in the following:
document.myForm.rate.value = someNumber.toPrecision(5);
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:
var num = 98.6; var preciseNum = num.toPrecision(5); // preciseNum is now 98.600
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);
parseInt( )
method and specify the second
parameter as 16:
var decimalVal = parseInt(myHexNumberValue, 16);
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);
function dec2Hex(dec) {
dec = parseInt(dec, 10);
if (!isNaN(dec)) {
hexChars = "0123456789ABCDEF";
if (dec > 255) {
return "Out of Range";
}
var i = dec % 16;
var j = (dec - i) / 16;
result = "0x";
result += hexChars.charAt(j) + hexChars.charAt(i);
return result;
} else {
return NaN;
}
}
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:
Math.random( )
method returns a pseudorandom number
between 0 and 1. To calculate a pseudorandom integer value within a
range starting with zero, use the formula:
var result = Math.floor(Math.random( ) * (n + 1);
var result = Math.floor(Math.random( ) * (n - m + 1)) + m;
Math.floor( )
call to let the rest of the expression create random numbers with
decimal fractions if you need them.
Math
object comes with a typical
complement of functions for trigonometric calculations. Each one
requires one or two arguments and returns a result in radians.
Arguments representing angles must also be expressed in radians. The
following statement assigns the sine of a value to a variable:
var sineValue = Math.sin(radiansInput);
Math object methods must be invoked as methods
of the static Math object.
Math object methods and constants. You can see an
application of trigonometric functions in Recipe 13.10, which
calculates the circular path for a positioned element to follow on
the page.
Date object to use for
date calculations or display.
Date object constructor method with any of
the acceptable arguments signifying a date (and, optionally, a time
for that date):
var myDate = new Date(yyyy, mm, dd, hh, mm, ss); var myDate = new Date(yyyy, mm, dd); var myDate = new Date("monthName dd, yyyy hh:mm:ss"); var myDate = new Date("monthName dd, yyyy"); var myDate = new Date(epochMilliseconds);
var now = new Date( );
Date
object constructor is entirely dependent upon the accuracy of the
client computer's internal clock, control panel
settings, and occasional browser anomalies. Correct setting of the
computer's local time zone and daylight saving time
option is essential to accurate date and time calculations based on
the current date.
Date object
constructor—as specified in the ECMAScript standard—have
no variation that readily accepts shortcut ways of entering dates
(such as
mm
/
dd
/
yyyy,
or the numerous variations used around the world). Instead, numerical
entries need to be broken into the component parts to be passed as
discrete arguments for the constructor. If you need to generate a
date object from user entries in a text box (or, better still, a
series of three text boxes), you can pass the value properties of
those text boxes directly as arguments of the constructor:
var myDate = new Date( ); myDate.setDate(myDate.getDate( ) + 10);
myDate object contains the
future date in milliseconds, irrespective of months, dates, and
years. But if you then read
myDate's string version (or
locale string in recent browsers), you see the future date correctly
calculated:
document.myForm.deadline.value = myDate.toLocaleDateString( );