home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Book HomeActionScript: The Definitive GuideSearch this book

4.6. Working with Strings

By manipulating strings we can program anything from a user-input validator to a word-scramble game. With a little ingenuity, we can make neat visual text effects and other fun stuff.

We can manipulate strings with both operators and built-in functions. String operators can join multiple strings together or compare the characters of two strings. Built-in functions can examine a string's properties and contents, extract a portion of a string, check a character's code point, create a character from a code point, change the case of the characters in a string, and even turn a string into a variable or property name.

4.6.1. Joining Strings Together

Joining strings together (creating a new string from two or more strings) is called concatenation. As seen earlier, we can concatenate two strings with the plus operator (+), like this:

"Macromedia" + "Flash"

That line of code yields the single string value "MacromediaFlash". Oops! We forgot to put a space between the words. To add the space, we can insert it within the quotes that define one of the strings, such as:

"Macromedia " + "Flash"  // Yields "Macromedia Flash"

But that's not always practical. In most cases we don't want to add a space to a company or a product name. So instead, we join three strings together, the middle one of which is simply an empty space:

"Macromedia" + " " + "Flash"   // Also yields "Macromedia Flash"

Note that the space character is not the same as the empty string we saw earlier because the empty string has no characters between the quotes.

We can also concatenate variables that contain string data. Consider the following code:

var company = "Macromedia";
var product = "Flash";

// Set the variable sectionTitle to "Macromedia Flash"
var sectionTitle = company + " " + product;

In lines 1 and 2, we store string values in variables. Then, we join those values together with a space. Two of our string values are contained in variables, one (the space) is a string literal. Not a problem. Happens all the time.

Occasionally, we'll want to append characters onto an existing string. For example, we could change the tone of a welcome message like this:

var greeting = "Hello";     // Our welcome message
greeting = greeting + "?";  // Our quizzical welcome message: "Hello?"

The preceding code gets the job done, but notice that we have to refer to greeting twice in line 2. To be more efficient, we can use the += operator, which appends the string on its right to the string variable on the left:

var greeting = "Hello";    // Our welcome message
greeting += "?";           // Our quizzical welcome message: "Hello?"

WARNING

The Flash 4 string concatenation operator (&) performs a different operation (bitwise AND) in Flash 5. If exporting a Flash 4 .swf, you must use the add operator to concatenate strings. Note that add is supported only for backward compatibility; the + operator is preferred in Flash 5.

4.6.2. Comparing Strings

To check whether two strings are the same, we use the equality (==) and inequality (!=) operators. We often compare strings when executing code based on a condition. For example, if a user enters a password, we need to compare his input string with the actual password. The result of our comparison governs the behavior of our code.

4.6.2.1. Using the equality (==) and inequality (!=) operators

The equality operator takes two operands -- one on its left and one on its right. The operands may be string literals or any variable, array element, object property, or expression that can be converted to a string:

"hello" == "goodbye"       // Compare two string literals
userGuess == "fat-cheeks"  // Compare a variable with a string
userGuess == password      // Compare two variables

If the operand on the right has the exact same characters in the exact same order as the operand on the left, the two strings are considered equal and the result is the Boolean value true. However, upper- and lowercase letters have different code points in a character set, so they are not considered equal. The following comparisons all evaluate to false:

"olive-orange" == "olive orange"  // Not equal
"nighttime" == "night time"       // Not equal
"Day 1" == "day 1"                // Not equal

Because string comparisons result in the Boolean value true or false, we can use them as test expressions within conditional statements and loops, like this:

if (userGuess == password) {
  gotoAndStop("classifiedContent");
}

If the expression (userGuess == password) is true, then the gotoAndStop("classifiedContent"); statement will be executed. If the expression is false, the gotoAndStop("classifiedContent"); statement will be skipped.

We'll learn more about Boolean values later in this chapter. And we'll learn about conditional statements in Chapter 7, "Conditionals".

To check whether two strings are not equal, we use the inequality operator, which yields a result opposite to the equality operator. For example, the following expressions represent the values false and true, respectively:

"Jane" != "Jane"  // false because the two strings are equal
"Jane" != "Biz"   // true because the strings are different

Here we use the inequality operator to take some action only if two strings are not equal:

if (userGender != "boy") {
  // Girls-only code goes here...
}

TIP

If exporting a Flash 4 .swf, you must use the older eq and ne operators for string equality and inequality comparisons. Although eq and ne are supported for backward compatibility, the == and != operators are preferred in Flash 5.

4.6.2.2. Character order and alphabetic comparisons

We can also compare two strings on a character-order basis. We saw earlier that each character has a numeric code point assigned to it and that those code points are ordered numerically in a character set. We can check which character comes first in the order using the comparison operators: greater than (>), greater than or equal to (>=), less than (<), and less than or equal to (<=). All of the comparison operators compare two operands:

"a" < "b"
"2" > "&"
"r" <= "R"
"$" >= "@"

Much like equality and inequality expressions, comparison expressions yield a Boolean value, true or false, depending on the relationship of the operands. Each operand can be anything that yields a string value.

Since the characters `A' to `Z' and `a' to `z' are grouped in alphabetic sequence in the Latin 1 character set, we frequently use character-order comparisons to determine which of two letters comes first alphabetically. Note, however, that any uppercase letter comes before all lowercase letters in the Latin 1 character set. If we forget this, we're in for some surprising results:

"Z" < "a"       // Evaluates to true
"z" < "a"       // Evaluates to false
"Cow" < "bird"  // Evaluates to true

Here's a closer look at each comparison operator; in the following descriptions, the comparison character is defined as the first nonidentical character found in the two operands:

Greater than (>)

Yields true if the comparison character of the left operand appears later in the Latin 1 or Shift-JIS character order than the comparison character of the right operand. If the two operands are completely identical, > returns false:

"b" > "a"      // true
"a" > "b"      // false
"ab" > "ac"    // false (the second character is the comparison character)
"abc" > "abc"  // false (the strings are identical)
"ab" > "a"     // true (b is the comparison character)
"A" > "a"      // false ("A" comes before "a" in the character order)
Greater than or equal to (>=)

Yields true if the comparison character of the left operand appears later in the character order than the comparison character of the right operand or if the two operands are completely identical:

"b" >= "a"  // true
"b" >= "b"  // true
"b" >= "c"  // false
"A" >= "a"  // false ("A" and "a" occupy different code points)
Less than (<)

Yields true if the comparison character of the left operand appears earlier in the Latin 1 or Shift-JIS character order than the comparison character of the right operand. If the two operands are completely identical, < returns false:

"a" < "b"      // true
"b" < "a"      // false
"az" < "aa"    // false (the second character is the comparison character)
Less than or equal to (<=)

Yields true if the comparison character of the left operand appears earlier in the character order than the comparison character of the right operand or if the two operands are completely identical:

"a" <= "b"  // true
"a" <= "a"  // true
"z" <= "a"  // false

To determine which of two nonalphabetic characters comes first in the Latin 1 character order, consult Appendix B, "Latin 1 Character Repertoire and Keycodes".

The following example checks whether a character is a letter from the Latin alphabet (as opposed to a number, punctuation mark, or other symbol):

var theChar = "w";

if ((theChar >= "A" && theChar <= "Z") || (theChar >= "a" && theChar <= "z")) {
  trace("The character is in the Latin alphabet.");
}

Notice how the logical OR operator (||) lets us check two conditions at once. We'll study OR in Chapter 5, "Operators".

TIP

If exporting a Flash 4 .swf, you must use the older gt, ge, lt, and le string comparison operators. Although the older operators are supported for backward compatibility, the >, >=, <, and <= operators are the preferred equivalents in Flash 5.

4.6.5. Examining Strings

We can inspect and search within strings using the built-in length property or the charAt( ), indexOf( ), and lastIndexOf( ) functions.

4.6.5.3. The indexOf( ) function

We use the indexOf( ) function to search for characters in a string. If the string we're searching contains our search sequence, indexOf( ) returns the index (i.e., position) of the sequence's first occurrence in the string. Otherwise, it returns the value -1. The general form of indexOf( ) is:

string.indexOf(character_sequence, start_index)

where string is any literal string value or an identifier that contains a string; character_sequence is the string for which we're searching, which may be a string literal or an identifier that contains a string; and start_index is the starting position of the search. If start_index is omitted, the search starts at the beginning of string.

Let's use indexOf( ) to check whether a string contains the character W:

"GWEN!".indexOf("W");  // Returns 1

Yup, W is the second character in "GWEN!", so we get 1, the index of the W character. Remember, character indexes start at 0, so the second character occupies index 1.

What happens if we search for the lowercase character w ? Let's see:

"GWEN!".indexOf("w");  // Returns -1

There is no w in "GWEN!" so indexOf( ) returns -1. The upper- and lowercase versions of a letter are different characters and indexOf( ) is case sensitive!

Now let's make sure that there's an @ sign in an email address:

var email = "daniella2dancethenightaway.ca";  // Oops, someone forgot to
                                              // press Shift!

// If there's no @ sign, warn the user via the formStatus text field
if (email.indexOf("@") == -1) {
  formStatus = "The email address is not valid.";
}

We don't always have to search for single characters. We can search for an entire character sequence in a string too. Let's look for "Canada" in the address of a company:

var iceAddress = "St. Clair Avenue, Toronto, Ontario, Canada";
iceAddress.indexOf("Canada");  // Returns 36, the index of the letter "C"

Notice that indexOf( ) returns the position of the first character in "Canada". Now let's compare the return value of iceAddress.indexOf("Canada") to -1, and assign the result to a variable that stores the nationality of the company:

var isCanadian = iceAddress.indexOf("Canada") != -1;

The value of iceAddress.indexOf("Canada") != -1 will be true if iceAddress.indexOf("Canada") does not equal -1 ("Canada" is found) and false if iceAddress.indexOf("Canada") does equal -1 ("Canada" is not found). We then assign that Boolean value to the variable isCanadian, which we can use to create a country-specific mailing form for North America:

if (isCanadian) {
  mailDesc = "Please enter your postal code.";
} else {
  mailDesc = "Please enter your zip code.";
}

The indexOf( ) function can also help us determine which part of a string we need to extract. We'll see how that works when we learn about the substring( ) function.

4.6.6. Retrieving Portions of Strings

Sometimes a long string contains a sequence of characters that we'd like to access more conveniently. In the string "Steven Sid Mumby", for example, we may want to extract the last name, "Mumby". To extract a shorter string (or substring) we use one of these functions: substring( ), substr( ), splice( ), or split( ).

4.6.6.1. The substring( ) function

We use substring( ) to retrieve a sequence of characters from a string based on starting and ending character indexes. The substring( ) function takes the following form:

string.substring(start_index, end_index)

where string is any literal string value or an identifier that contains a string, start_index is the index of the first character to include in the substring, and end_index is the character after the last character we want in our substring. If not provided, end_index defaults to string.length. Hence:

var fullName = "Steven Sid Mumby";
middleName = fullName.substring(7, 10);  // Assigns "Sid" to middleName
firstName = fullName.substring(0, 6);    // Assigns "Steven" to firstName
lastName = fullName.substring(11);       // Assigns "Mumby" to lastName

In reality, we wouldn't know where the first name, middle name, and last name begin and end, so we'd typically look for some delimiter, such as the space character to help us guess where the word breaks are. Here we search for the last space in the name and assume that the remainder of the string following it is the user's last name:

fullName = "Steven Sid Mumby";
lastSpace = fullName.lastIndexOf(" "); // Returns 10

// Characters from 11 to the end of the string are presumably the last name
lastName = fullName.substring(lastSpace+1);
trace ("Hello Mr. " + lastName);

If start_index is greater than end_index, the two arguments are swapped automatically before the function executes. Although the following function invocations yield the same result, you shouldn't make a habit of using substring( ) with the indexes reversed because it makes your code harder to understand:

fullName.substring(4, 6);  // Returns "en"
fullName.substring(6, 4);  // Returns "en"

4.6.6.2. The substr( ) function

The substr( ) function extracts a sequence of characters from a string using a starting index and a length (in contrast to substring( ), which uses starting and ending indexes). The general form of substr( ) is:

string.substr(start_index, length)

where string is, as usual, any literal string value or an identifier that contains a string; start_index is the first character to include in the substring; length specifies how many characters should be included in our string, starting at start_index and counting to the right. If length is omitted, the substring starts at start_index and ends with the last character in the original string. Some examples:

var fullName = "Steven Sid Mumby";
middleName = fullName.substr(7, 3);    // Assigns "Sid" to middleName
firstName = fullName.substr(0, 6);     // Assigns "Steven" to firstName
lastName = fullName.substr(11);        // Assigns "Mumby" to lastName

The start_index can be specified relative to the end of a string by using a negative number. The last character is -1, the second last character is -2, and so on. So the preceding three substr( ) examples could be written as:

middleName = fullName.substr(-9, 3);  // Assigns "Sid" to middleName
firstName = fullName.substr(-16, 6);  // Assigns "Steven" to firstName
lastName = fullName.substr(-5);       // Assigns "Mumby" to lastName

A negative length, however, is not allowed.

TIP

In Flash 5, the substr( ) function is the string-extraction function that most closely resembles Flash 4's substring( ) function, which also used a start index and a length to retrieve a substring.

4.6.6.3. The slice( ) function

Like substring( ), slice( ) retrieves a sequence of characters from a string based on starting and ending character indexes. While substring( ) can specify only the indexes relative to the beginning of the original string, slice( ) can specify them relative to the string's beginning or end.

The slice( ) function takes the following form:

string.slice(start_index, end_index)

where string is any literal string value or an identifier that contains a string and start_index is the first character to include in the substring. If start_index is a positive integer, it is a normal character index; if start_index is a negative integer, the equivalent character index is determined by counting back from the end of the string (that is, string.length + start_index). Finally, end_index is the character after the last character we want in our substring. If end_index is not provided, it defaults to string.length. If end_index is negative, the equivalent character index is determined by counting back from the end of the string (that is, string.length + end_index).

Using nonnegative indexes with slice( ) works just like substring( ). When using negative indexes, remember that you are not getting a substring with reversed characters, and you are not getting a string from end_index to start_index in that order. You are merely specifying the indexes relative to the end of the original string. Remember also that the last character of the string is -1, and the end_index argument specifies the character after the last character in your substring, so it's impossible to refer to the last character in the original string using a negative end_index. Take a careful look at how we use negative indexes to extract the following substrings:

var fullName = "Steven Sid Mumby";
middleName = fullName.slice(-9, -6);   // Assigns "Sid" to middleName
firstName = fullName.slice(-16, -10);  // Assigns "Steven" to firstName
lastName = fullName.slice(-5, -1);     // Assigns "Mumb" to lastName: not what
                                       // we want, but the best we can do with
                                       // a negative end_index.
lastName = fullName.slice(-5, 16)      // Assigns "Mumby" to lastName. Notice 
                                       // how we combine negative and 
                                       // positive indexes.

4.6.6.4. The split( ) function

So far, the string-extraction functions we've seen have retrieved only one character sequence at a time. If we want to rip out a bunch of substrings in one fell swoop, we can use the powerful split( ) function. (As the split( ) function uses arrays, you may want to skip this function for now and come back after you've read Chapter 11, "Arrays".)

The split( ) function breaks a string up into a series of substrings and puts those substrings into an array, which it returns. The split( ) function takes the following form:

string.split(delimiter)

where string is any literal string value or an identifier that contains a string, and delimiter is the character or characters that indicate where string should be split. Typical delimiters are commas, spaces, and tabs. To break up a string at each comma, for example, we use:

theString.split(",")

One of the neat tricks we can pull with split( ) is to break a sentence up into individual words. In our coverage of the substring( ), substr( ), and slice( ) functions, we had to manually grab each name from the string "Steven Sid Mumby." Look how much easier things are when we use split( ) with a space (" ") as the delimiter :

var fullName = "Steven Sid Mumby";
var names = fullName.split(" ");  // Man that's easy!

// Now assign the names in our array to individual variables
firstName  = names[0];
middleName = names[1];
lastName   = names[2];

4.6.7. Combining String Examination with Substring Extraction

We've seen how to search for characters in a string and how to extract characters from a string. These two tasks are most powerful when we put them together.

Most of the examples we've seen so far use literal expressions as arguments, like this:

var msg = "Welcome to my website!";
var firstWord = msg.substring(0, 7);  // 0 and 7 are numeric literals

That's a decent demonstration of the way substring( ) works, but it doesn't represent the typical real-world use of substring( ). More often, we don't know the content of the string in advance and we must generate our arguments dynamically. For example, instead of saying something static like, "Get me the substring from index to index 7," we usually say something dynamic like, "Get me the substring starting from the first character and ending at the first occurrence of a space in this string." This more flexible approach doesn't require us to know the content of a string in advance. Here we extract the first word of the variable msg, by combining substring( ) with indexOf( ) :

var firstWord = msg.substring(0, msg.indexOf(" "));

The expression msg.indexOf(" ") evaluates to the numeric index of the first space in msg. Our technique will work regardless of the space's location. This allows us to work with strings that change while our program is running and saves us a lot of character counting, which is prone to error.

The combinations of string examination and string extraction are practically endless. In Example 4-2 we extract the second word of the msg variable without hard-coding the character indexes. In natural language we want to "Extract a substring from msg starting with the character after the first occurrence of a space and ending with the character before the second occurrence of a space." We store the location of the first and second spaces as variables, making what's going on more obvious.

Example 4-2. Retrieving the Second Word of a String

var msg = "Welcome to my website!";
firstSpace = msg.indexOf(" ");                   // Find the first space
secondSpace = msg.indexOf(" ", firstSpace + 1);  // Find the next space

// Now extract the second word
var secondWord = msg.substring(firstSpace + 1, secondSpace);

4.6.8. Character Case Conversion

We can convert a string to upper- or lowercase using the built-in toUpperCase( ) and toLowerCase( ) functions. These are typically used to display a string with nice formatting or to compare strings with different cases.

4.6.9. Character Code Functions

In Section 4.5.2.3, "Unicode-style escape sequences", we learned how to insert characters into a string as escape sequences. ActionScript also includes two built-in functions for working with character codes in strings: fromCharCode( ) and charCodeAt( ).

4.6.10. Executing Code in a String with eval

In ActionScript, the eval( ) function converts a string to an identifier. But to thoroughly understand the ActionScript eval( ) function, we must learn how JavaScript's analogous eval( ) function works. In JavaScript, eval( ) is a top-level, built-in function that converts any string to a block of code and then executes that block of code. The syntax for JavaScript's eval( ) is:

eval(string)

When eval( ) is executed in JavaScript, the interpreter converts string to code, runs that code, and returns the resulting value (if a value is generated). Consider the following JavaScript examples:

eval("parseInt('1.5')");  // Calls the parseInt( ) function, which returns 1
eval("var x = 5");        // Creates a new variable named x and 
                          // sets its value to 5

If you've never seen eval( ) before, you may be thinking, "When would I ever have a string with code in it? Why not just write the code out?" Because eval( ) lets you dynamically generate code when you need to. For example, suppose you have ten functions named sequentially: func1, func2, func3, ..., func10. You could execute those functions with 10 function-call statements:

func1( );
func2( );
func3( );
// etc...

But you could also execute them more conveniently using eval( ) in a loop, like this:

for (i = 1; i <= 10; i++){
  eval("func" + i + "( )");
}

ActionScript's eval( ) function supports a small subset of its JavaScript cousin's functionality: it works only when its argument is an identifier. Hence, ActionScript's eval( ) function can only retrieve the data associated with the specified identifier. For example:

var num = 1;
var person1 = "Eugene";
trace (eval("person" + num));  // Displays: "Eugene"

Even in this pared-back form, eval( ) is quite useful. Here we generate a series of movie clips dynamically with a loop. We place our clips in an array by using eval( ) to refer to them:

for (var i = 0; i < 10; i++) {
  duplicateMovieClip("ballParent", "ball" + i, i);
  balls[i] = eval("ball" + i);
}

Note, however, that eval( ) can be quite processor-intensive. In more demanding scenarios, we're better off using the array-access operator to generate dynamic clip references. For example:

duplicateMovieClip("ballParent", "ball" + i , i);
balls[ballCount] = _root ["ball" + i];

In Flash 4, eval( ) was used abundantly to simulate arrays through dynamic variable-name generation and referencing. This technique is not recommended or required in Flash 5 due to Flash 5's native support for arrays. See Section 2.1.2.1, "Creating dynamically named variables" in Chapter 2, "Variables", for more details.

4.6.11. Flash 4 Versus Flash 5 String Operators and Functions

Throughout the descriptions of the string operators and functions, we looked at equivalent Flash 4 techniques. When we're using Flash 5 to author Flash 4 movies, we should use the Flash 4 string operators and functions in all of our work. But when we're authoring for Flash 5, we should use the swanky Flash 5 operators. If you're accustomed to the Flash 4 syntax, see Table 4-2 for the Flash 5 equivalents.

Table 4-2. Flash 4 Operators and Functions with Flash 5 Equivalencies

Flash 4 Syntax

Flash 5 Syntax

Description

""

"" or ''

String literal

&

+ (or add for backward compatibility)

String concatenation operator

eq

==

Equality operator

ge

>=

Greater-than-or-equal-to comparison

gt

>

Greater-than comparison

le

<=

Less-than-or-equal-to comparison

lt

<

Less-than comparison

ne

!=

Inequality operator (not equal to)

chr( ) or mbchr( )

fromCharCode( ) [1]

Creates a character from an encoded number

length( ) or mblength( )

length*

Function in Flash 4, property in Flash 5; gives the number of characters in a string

mbsubstring( )

substr( )

Extracts character sequence from a string

ord( ) or mbord( )

charCodeAt( ) *

Gives the code point of the specified character

substring( )

substr( ) *

Extracts character sequence from a string

[1]

Because all the Flash 5 string operations and functions work with multibyte characters, there's no way in Flash 5 to force a single-byte operation as there was in Flash 4. The fromCharCode( ) function is, for example, as close as things get to chr( ) in Flash 5. The same is true of mblength( ) and length, mbsubstring( ) and substr( ), and mbord( ) and charCodeAt( ).



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.