Chapter 2. Working with Core Technologies

Whereas a native iPhone app is built entirely in Objective-C, an iPhone Web app is composed of a variety of core technologies that serve as interlocking building blocks. HTML provides structure for the user interface and application data, and CSS is used for styling and presentation. JavaScript and Ajax provide the programming logic used to power the app. And, depending on the app, it may have a backend application server, such as Java or PHP.

Books on programming native iPhone apps often have a primer chapter on the basics of Objective-C to make sure everyone is speaking the same language, so to speak. And, although an entire book could easily be filled writing a primer on the core Web technologies you will work with to develop an iPhone Web app, I do want to explore some of the key technologies you'll need to be sure you know about to be successful.

So as not to start from ground zero, I will assume that you at least know the basics of HTML and have a working knowledge of CSS. That's why I will spend most of my time talking about both the scripting logic layer and the Document Object Model (DOM). However, before I do so, I want to highlight the new HTML 5 tags that Safari on iPhone supports for embedding media into your Web app.

Exploring HTML 5 Media Elements

Before iPhone OS 3.0, working with video inside of an iPhone Web app usually consisted of a simple link to a YouTube clip, which then launched the YouTube app. Because Safari on iPhone didn't (and still doesn't) support Flash video (FLV), there were few alternatives to an ordinary link when working with video. However, one of the key HTML 5 technologies that Safari on iPhone now supports is the video element.

The video element defines a video clip or stream, much like an img tag defines an image on your page. The promise of the video tag is that it eliminates the complicated hoops that developers have to go through now with embedded media content. Instead of mixing complicated object definitions and script, you can embed media with a simple tag definition.

Unfortunately for normal Web sites, the video element remains something of a tease, because most desktop browsers don't yet support HTML 5. As a result, developers have to either add code for unsupported browsers or avoid its use altogether.

However, if you are creating an iPhone Web app, you don't have this same dilemma. Safari on iPhone, starting with the OS 3.0 release, provides full support. Therefore, if you need to utilize video in your app, be sure to take advantage of the video tag.

Note that the video does not play inside the Web page as an embedded video, but instead launches the built-in iPhone media player, which occupies the full screen of the iPhone. The user then clicks the Done button to return to your app.

The basic syntax for the element is shown here:

<video src="../video/trailer.mov" controls="true" poster="picture.jpg" width="300"
height="200"/>

Table 2-1. Attributes for video Element

Attribute

Description

autoplay

When set to true, the video plays as soon as it is ready to play.

controls

If true, the user is shown playback controls.

end

Specifies the endpoint to stop playing the video. If it's not defined, the video plays to the end.

height

Defines the height of the video player.

loopend

Defines the ending point of a loop.

loopstart

Defines the starting point of a loop.

playcount

Specifies the number of times a video clip is played. Defaults to 1.

poster

Specifies the URL of a "poster image" to show before the video begins playing.

src

Defines the URL of the video.

start

Sets the point at which the video begins to play. If start is not defined, the video starts playing at the beginning.

width

Defines the width of the video player.

Supported video formats include QuickTime (MOV) and MPEG (MP4). Note that Safari on iPhone does not support Flash media (FLV) or Ogg Theora (OGG).

Adding a video into your app becomes as easy as adding the video tag to your page. For example:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Video</title>
<meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0;
user-scalable=0;"/>
<style type="text/css">

body
{
  background-color: #080808;
  margin: 10;
}

p
{
  color: #ffffff;
  font-family: Helvetica, sans-serif;
  font-size:10px;
}

</style>

</head>
<body>
  <div style="text-align:center">
  <p>Check out the new trailer for our upcoming video game release.</p>
  <video src="../videos/tlr2_h.640.mov" controls="true" width="300"/>
  </div>
</body>
</html>

Figure 2-1 shows how Safari displays the video player. When the user touches the video player, Safari displays the video in the built-in media player, as shown in Figure 2-2.

The audio element works in much the same way, although its attributes are a subset of the video tag's set. They include src, autobuffer, autoplay, loop, and controls. Figure 2-3 shows the audio file being played in the media player.

Safari displaying the video element

Figure 2-1. Safari displaying the video element

Video plays in a separate media player.

Figure 2-2. Video plays in a separate media player.

Audio files are also played in the media player.

Figure 2-3. Audio files are also played in the media player.

Scripting JavaScript

The scripting layer of your iPhone Web app is often the "brains behind the operation," the place on the client side in which you add your programming logic. That's why as you begin to develop more and more sophisticated Web apps for the iPhone platform, you'll find that the technology you'll rely more and more on is JavaScript. Therefore, before you go any further in this book, you need a solid grasp of how to script with JavaScript. Use this extended section as a primer for the core essentials of programming with JavaScript.

Syntax and Basic Rules

Like any other programming language, JavaScript has its own syntax rules and conventions. Consider the following script:

<script language="javascript" type="text/javascript">

// Defining a variable
var message = "Hello";

// Creating a function, a module of code
function showGreeting(allow)
{
  // If allow is true, then show the message variable
  if (allow == true)
{
    alert(message);
  }
  // Otherwise, show this message
  else
    alert("I withhold all greetings.");
}

// Call function
showGreeting(true)

</script>

Notice a few aspects of the JavaScript syntax:

  • Case sensitivity: JavaScript is a case-sensitive language. The core language words (such as var, function, and if in the example) are all lowercase. Built-in JavaScript and Document Object Model objects use lowerCamelCase conventions, which are explained in the later section titled "JavaScript Naming Conventions." Variable names that you define can be in the case you choose, but note that the following terms are not equivalent:

    var message = "Hello";
    var MESSAGE = "Hello";
    var Message = "Hello";
  • Whitespace: Just like HTML, JavaScript ignores spaces, tabs, and new lines in code statements. Each of the following is equivalent:

    var message="Hello";
    var message = "Hello";

    These are as well:

    if (allow==true)
    if ( allow == true )
  • Semicolons: Each JavaScript statement ends with a semicolon (except for the descriptive comment lines).

  • Curley brackets: Some JavaScript control structures, such as functions and if statements, use curly brackets {} to contain multiple statements between them. These brackets can be placed on separate lines or on the same line as the other code. For example:

    if (allow == true) {
      alert(message) }

    is the same as

    if (allow == true)
    {
      alert(message)
    }

Variables

A variable is an alias that stores another piece of data — a text string, a number, a true or false value, or whatever. Variables are core to programming because they eliminate the need for having everything known while you are developing the script or application.

For example, suppose you wanted to capture the first name of the user and add it to a welcome message that appears when the user returns to your iPhone Web app. Without variables, you'd have to know the person's name beforehand — which is, of course, impossible — or you'd have to use a generic name for everyone.

By using a variable, you eliminate this problem. You can capture the name of the user and then store it in the code as a variable — I'll call it firstName. Then, anytime in my script I need to work with the user's name, I call firstName instead.

Declaring and Assigning Variables

When you want to use a variable, your first task is to declare it with the keyword var and then assign it a value. Here's how this two-step process can look:

var firstName;
firstName = "Jonah";

The var keyword instructs the JavaScript interpreter to treat the following word, in this case firstName, as a variable. The following line then assigns the literal string Jonah to the firstName variable.

Although declaring and assigning a variable may be two separate actions, you'll usually want to combine them into one step. For example, the following code is functionally equivalent to the previous two lines of code:

var firstName = "Jonah";

Truth be told, you can actually assign a variable without even using the keyword var. For example, the following code also works:

firstName = "Jonah";

However, I strongly recommend regular use of var when you first define it to ensure your code is readable and manageable by both you and other developers.

Hanging Loose with Variable Types

You can assign a variety of data types to a variable. Following are a few examples:

// String value
var state = "CO";
// Boolean value
var showForm = true;
// Number value
var maxWidth = 300;
// HTML document "node"
var element = document.getElementById("container");
// Array item
var item = myArray[0];

If you are coming from an Objective C, Java, ActionScript, or other stronger-typed language, you are probably wondering where you declare the type of data that can be stored by the variable. Well, to put it simply — you don't have to. Because JavaScript is a loosely typed language, you don't need to declare the variable type.

Naming Variables

When you are naming variables, keep in mind the following general rules:

  • A variable name must begin with a letter or underscore, not a number or other special character. For example:

    // Valid
    var helper;
    var _helper;
    
    // Invalid
    var 2helper;
    var ^helper;
  • Although a number can't start off a variable name, you can include one elsewhere in the word, such as here:

    var doc1;
    var doc2;
  • As with other aspects of JavaScript, variable names are case sensitive. Therefore, each of the following is a unique variable name:

    var counter;
    var Counter;
    var COUNTER;
    var counTer;
  • A variable name can't contain spaces. For example:

    // Valid
    var streetAddress;
    var street_address;
    
    //Invalid
    var street address;
  • You can't use a reserved word (see Table 2-8) or the name of a JavaScript or Document Object Model object as a variable name. For example:

    // Valid
    var isDone;
    var defaultValue;
    var mainWindow;
    
    // Invalid
    var in;
    var default;
    var window;

Accessing a Variable

After you define a variable and assign it a value, each time you reference it in your code, the variable represents the value that was last assigned to it. In the following snippet of code, the company variable is assigned a string value and displayed in an alert box:

var company = "Cyberg Coffee";
alert( "Our company is proudly named " + company);

The alert box displays this:

Our company is proudly named Cyberg Coffee.

You can also change the value of a variable inside your source code. After all, they are called variables, aren't they? A typical example is a counter variable that has a value incremented during a looping process. Consider the following example:

for (var i = 1;i <= 5; i++)
{
  document.write( "The value of the variable is: " + i + ".<br/>" );
}

I'll explain what the for loop does later in the chapter. For now, just focus on the variable named i. The variable starts out with a value of 1 during the execution of the first pass of the code inside the for block. During the next pass, its value is incremented to 2. On the third pass, its value is incremented to 3. This same process continues until i is 5. In total, the document.write() method would be called five times and would output the following content:

The value of the variable is 1.
The value of the variable is 2.
The value of the variable is 3.
The value of the variable is 4.
The value of the variable is 5.

Scope

Variables can have either a limited or a wide scope. If you define a variable inside a function, that variable (called a local variable) is only available to the function and expires when the function is finished processing. For example, check out the markup variable in the code that follows:

function boldText(textToDisplay)
{
  var markup = "<strong>" + textToDisplay + "</strong>";
  return markup;
}

The variable is created when the boldText() function runs, but it no longer exists after the function ends.

However, if you define the variable at the top level of the scripting block — in other words, outside a function — that variable (known as a global variable) is accessible from anywhere in the document. What's more, the lifetime of a global variable persists until the document is closed.

Table 2-2 summarizes the differences between local and global variables.

Table 2-2. Local Versus Global Variables

Type

Scope

Lifetime

Local

Accessible only inside a function

Exists until the function ends

Global

Accessible from anywhere in the document

Exists until the document closes

Scope deals with the context of the variable within the scripting hierarchy. However, the location at which a variable is defined also matters. Simply put, a variable is accessible when it is declared. Therefore, you'll typically want to define global variables at or near the top of the script and local variables at or near the top of the function.

I've put together a sample script that demonstrates the scope of variables. First, I'll define a global variable at the top of a script:

<script language="javascript" type="text/javascript">
var msg = "I am a global variable";
var msgEnd = ", and you cannot stop me."

Next, I'll add an alert box to display the variable:

alert(msg + msgEnd);

When this code runs, the alert message text that appears will be as follows:

I am a global variable, and you cannot stop me.

Now check out what I am going to do. I am creating a function that assigns a local variable with the same name (msg) and then simply references msgEnd, the global variable I already defined. Here's the code:

function displayAltMessage()
{
  var msg = "Don't hassle me, I'm a local variable";
  alert(msg + msgEnd);
}

I call this function in my script with the following line:

displayAltMessage();

When this function is executed, the alert box displays the following text:

Don't hassle me, I'm a local variable, and you cannot stop me.

Notice that the local variable msg took precedence over the global variable msg. So within the function, the local msg variable "hides" the global msg variable, and any changes made to msg apply only to the local variable. However, when that function finishes, the local variable msg is destroyed, whereas the global variable msg remains.

Suppose that I reassign the value of the global variable msg later in my script and then display the alert box once again:

msg = "Reassigning now!";
alert(msg);

Yes, you've got it — the following text is displayed:

Reassigning now!

Notice that when I reassigned the variable, I didn't need to add the var keyword again.

Here's the full script:

<script type="text/javascript">
  // Global variable
  var msg = "I am a global variable";
  var msgEnd = ", and you cannot stop me."

  // Displays "I am a global variable, and you cannot stop me."
  alert(msg + msgEnd);
  function displayAltMessage()
  {
    // Local variable
    var msg = "Don't hassle me, I'm a local variable';
    // Displays "Don't hassle me, I'm a local variable, and you cannot stop me."
    alert(msg + msgEnd);
  }
  // Calls the function
  displayAltMessage();

  // Reassigning value to msg
  msg = "Reassigning now!";

  // Displays "Reassigning now!"
  alert(msg);
</script>

JavaScript Naming Conventions

Like Java and ActionScript, JavaScript uses CamelCase conventions for naming parts of the language. Variables, properties, and methods use what is known as lowerCamelCase. When using the lowerCamelCase convention, the name begins with a lowercase letter, but the first letter of each subsequent new word in a compound word is uppercase, with all other letters lowercase. You'll find that JavaScript and the DOM adhere to this convention. For example:

var divElements = document.getElementsByTagName("div");

In this example, document is the DOM object name for the HTML document and is all in lowercase. The method getElementsByTagName() is a compound word, so the first letter of each additional word in the method is capitalized. My variable divElements uses lowerCamelCase style to make it clear that the term combines two words.

Another type of coding convention that some JavaScript developers follow is what is known as Hungarian notation. Following this coding style, variables are prefixed with a letter that indicates the data type of the variable. Table 2-3 shows several examples of this notation.

In the end, the coding and naming convention you decide on is your personal or team preference. But no matter what you decide on, what ultimately matters is sticking with your conventions to create readable and manageable code.

Table 2-3. Using Hungarian Notation with Your Variables

Data/Object Type

Prefix

Example

String

S

sFirstName

Number

N

nRating

Boolean

B

bFlag

Array

A

aMembers

Object (DOM elements, user objects, and so on)

O

oCustomer

Date

D

dTransactionDate

Working with Constants

As you work with variables, they often change values during the course of a script. However, sometimes you want to work with a variable that refers to a value that doesn't change. These are called constants.

ActionScript, Java, and many other programming languages actually have a constant built into the language that is different from a variable. JavaScript does not. However, from a practical standpoint, you can define a variable and treat it as a constant in your code.

If you do, I recommend following standard conventions for naming constants:

  • Use uppercase letters.

  • Separate words with underscores.

For example:

var APP_TITLE = "iPhoneWebApp";
var VERSION_NUM = "2.01";
var MAX_WIDTH = 320;

You can then use these constant-looking variables just as you would a variable throughout your script.

Operators

An operator is a no-frills symbol used to assign values, compare values, manipulate expressions, or connect pieces of code.

The equal sign is perhaps the most common operator. It assigns a value to an expression. For example:

var i = 10;

Note that the operator that assigns a value (=) is different from the operator that compares whether two values are equal. The == operator is charged with comparing two items and returning true if conditions are true or false if not. For example:

alert(n == 100);

As you would expect, the + operator can add two number values together. However, you can also use it to combine two string literals or variables. So, check out this code:

var s = "Welcome ";
var t = " to the world of operators.";
alert(s + t);

The text Welcome to the world of operators would be displayed in a JavaScript alert box.

Tables 2-4 through 2-7 highlight the major operators. A few of the operators are pretty esoteric in real-world situations, but the ones you will typically use are shown in bold.

Table 2-4. Assignment Operators

Operator

Example

Description

=

x = y

The value of y is assigned to x

+=

x += y

Same as x=x+y

-=

x -= y

Same as x=x-y

*=

x *= y

Same as x=x*y

/=

x /= y

Same as x=x/y

%=

x %= y

Same as x=x%y (modulus, division remainder)

Table 2-5. Comparison Operators

Operator

Example

Description

==

x == y

x is equal to y

!=

x != y

x is not equal to y

===

x === y

Evaluates both for value and data type (e.g., if x = "5" and y = 5, then x==y is true, but x===y is false)

<

x < y

x is less than y

<=

x <= y

x is less than or equal to y

>

x > y

x is greater than y

>=

x >= y

x is greater than or equal to y

?:

x=(y < 5) ? −5 : y

If y is less than 5, then assign −5 to x; otherwise, assign y to x (known as the conditional operator)

Table 2-6. Logical Operators

Operator

Example

Description

&&

if ( x > 3 && y=0 )

Logical and

||

if ( x>3 || y=0 )

Logical or

!

if !( x=y )

Not

Table 2-7. Mathematical Operators

Operator

Example

Description

+

x + 2

Addition

-

x − 3

Subtraction

*

x * 2

Multiplication

/

x / 2

Division

%

x%2

Modulus (division remainder)

++

x++

Increment (same as x=x+1)

--

x--

Decrement (same as x=x-1)

Reserved Words

JavaScript has reserved words (see Table 2-8) that are set aside for use with the language. Avoid using these words when you name variables, functions, or objects.

Table 2-8. JavaScript 1.5 Reserved Words

abstract

boolean

break

byte

case

catch

Char

class

const

continue

debugger

Default

delete

do

double

else

Enum

export

extends

false

final

Finally

float

for

function

goto

If

implements

import

in

instanceof

Int

interface

long

native

new

Null

package

private

protected

public

Return

short

static

super

switch

Synchronized

this

throw

throws

transient

True

try

typeof

var

void

Volatile

while

with

 

Basic Conditional Expressions

JavaScript has three conditional statements that you can use to evaluate code:

  • if

  • if/else

  • switch

These three statements are explained in the following sections.

The if Statement

The if statement is used when you want to evaluate a variable and expression and then perform an action depending on the evaluation. The basic structure looks like this:

if (condition)
{
  // code to execute if condition is true
}

For example:

response = prompt("Enter the name of the customer.", "");
if (response == "Jerry Monroe")
{
  alert("Yes!");
}

A prompt box is displayed to the user. The typed response of the user is assigned to the response variable. The if statement then evaluates whether response is equal to "Jerry Monroe". If it is, the alert box is displayed. Otherwise, the if block is ignored.

I mentioned this in the operator section, but it bears repeating. The double equal signs are not a typo. Whereas a single equal sign (=) is used to assign a value to a variable, a double equal sign (==) compares one side of an expression to another.

If you are evaluating a Boolean variable, you can write the if statements in two ways:

if (isValid == true)
{
  alert("Yes, it is valid!");
}

Or, as a shortcut:

if (isValid)
{
  alert("Yes, it is valid!");
}

If you have a single line of code in the if block, you can actually forgo the curly brackets. So, this syntax works too:

if (isValid == true) alert("Yes, it is valid!");

You can also use if on a negative expression. Suppose, for example, that you want to perform an operation if a Boolean variable named isValid is false. The code would look something like this:

if (isValid == false)
{
  // do something to get validation
}

Notice that even though the false value is being used to evaluate the variable, the if block only executes if the expression (isValid == false) is true.

An alternative and usually preferred way to write this expression is to use the not operator (!):

if (!isValid)
{
  // do something to get validation
}

This expression says, in effect, if isValid is not true, then do something.

The if/else Statement

The if/else statement extends the if statement so that you can also execute a specific block of code if the expression evaluates to true and a separate block if it evaluates to false. The basic structure is this:

if (condition)
{
  // code to execute if condition is true
}
else
{
  // code to execute if condition is false
}

Here's an example of the if/else statement:

if (showName)
{
  document.write("My name is Sonny Madison.");
}
else
{
  document.write("I cannot disclose my name.");
}

Chaining if and if/else

You can also chain together if and if/else statements. Consider this scenario:

if (state = "MA")
{
  document.write("You live in Massachusetts.");
}
else if (state="CA")
{
  document.write("You live in California.");
}
else
{
  document.write("I have no idea where you live.");
}

The switch Statement

Besides chaining the if and if/else statements, you can use the switch statement to evaluate multiple values. Its basic structure is this:

switch (expression)
{
case label1 :
  // code to be executed if expression equals label1
  break;
case label2 :
  //code to be executed if expression equals label2
  break;
case label3 :
  //code to be executed if expression equals label3
  break;
default :
  // code to be executed if expression is different
  // from both label1, label2, and label3
}

The switch statement evaluates the expression to see if the result matches the first case value. If it does, the code inside the first case statement is executed. Note the break at the end of each of the case statements. This stops the switch statement from continuing to evaluate more of the case statements that follow. The default statement is executed if no matches are found.

Note that the case blocks do not use curly braces inside of them.

Here's an example that uses the switch statement to evaluate the current time of day using the built-in Date() object:

var d = new Date();
var hrs = d.getHours();

switch (hrs)
{
case 7 :
  document.write("Good morning.");
  break;
case 12 :
  document.write("It must be time for lunch.");
  break;
case 15 :
  document.write("Afternoon siesta. Zzzzz.");
  break;
case 23 :
  document.write("Bed time. Boo!");
  break;
default
  document.write("Check back later.");
}

The hrs variable is assigned the current hour using the Date,getHours() method. The switch statement evaluates hrs, examining whether this value matches the case statements in sequence. If it finds a match, the code inside the case is executed. Otherwise, the default statement is executed.

Loops

A common need that you will have in developing scripts in your iPhone Web apps is the ability to perform a given task several times or on a series of objects. Or maybe you need to execute code until a condition changes. JavaScript provides two programming constructs for these purposes: for and while blocks. A for loop cycles through a block of code x number of times. A while loop executes a block of code as long as a specific condition is true.

The for Loop

Along with the if statement, the for loop is likely the construct you'll use most often. The following snippet shows a for loop calling document.write() five times:

for (var i = 1; i <= 5; i++)
{
  document.write("Number:" i + "<br/>");
}

When run, the output looks like this:

Number 1
Number 2
Number 3
Number 4
Number 5

Going back to the code, notice the three parts of the for statement inside the parentheses:

  • Initialize variable: The var i = 1 initializes the variable used in the count. (The variable i is the typical name you'll see used for loop counters.)

  • Looping condition: The i <= 10 indicates the condition that is evaluated each time the loop is cycled through. The condition returns true as long as the i value is less than or equal to 10.

  • Update: The i++ statement is called after each pass of the loop completes. The ++ is the operator that increments the value of i by 1.

while and do/while Loops

A while loop also cycles through a block of code one or times. However, it continues as long as the expression evaluates to true. Here's the basic form:

while(expression)
{
  // statements
}

Here's an example:

var max = 100;
while(num > max)
{
  document.write("Current count: " + num);
  num++;
}

In this example, the code block loops as long as num is less than 100. However, suppose that num has the value of 101. If it does, the while code block is never executed.

The do/while loop is similar except that the condition evaluates at the end of the loop instead of at the start. Here's the basic structure:

do
{
   // statement
} while (expression)

In real-world practice, while loops are used more often than do/while ones.

Comments

As in HTML or other languages, you can add your own comments to your JavaScript code. Comments are useful when you go back into the code weeks or months later and need to understand again your code and the thought process behind it. Or, you might use comments to note specific places in the code that you need to rework later on.

You can add single-line or multiline comments.

Single-Line Comments

To add a single-line comment, add two slashes (//) to a line. Any text on the same line to the right of the slashes is considered a comment and is ignored by the interpreter. For example:

// Define two string variables
var s = "Welcome ";
var t = " to the world of operators.";
// Display concatenated values in an alert box
alert(s + t);

Multiline Comments

You can also define a comment that spans multiple lines. To do so, enclose the comments inside /* and */ marks. Here's what it looks like:

/*
 * Purpose: Converts Internet string date into Date object
 * RICH TO DO: Double-check that this works under all cases
*/
function getDateFromString(s)
{
  s = s.replace(/-/g, "/");
  s = s.replace("T", " ");
  s = s.replace("Z", " GMT-0000");
  return new Date(Date.parse(s));
}

Using JSDoc Comments

The Java world has a documentation generator called Javadoc, which is a tool that can generate HTML-based documentation from the comments a developer adds to source code. JSDoc is an open source tool, written in Perl, that provides similar functionality.

You can download JSDoc at http://jsdoc.sourceforge.net.

To enable a script for JSDoc, simply denote that comments you want included using a multiline comment, but with a slightly special syntax: open the comment with a slash and two asterisks (/**), and close the comment the normal way (*/). Here's an example:

/**
 * Converts Internet string date into Date object
*/
function getDateFromString(s)
{
  s = s.replace(/-/g, "/");
  s = s.replace("T", " ");
  s = s.replace("Z", " GMT-0000");
  return new Date(Date.parse(s));
}

You can also add several attributes that can be used to better describe the code. These attributes are prefixed with an @ sign. You can even add HTML tags for readability. Check this out:

/**
 * Converts Internet string date into Date object.
 * <p>
 * This function is called when the user selects the
 * Cyborg option in the left-side module.
*
 * @param  s string containing the
 * @returns  the date as a Date object
*/
function getDateFromString(s)
{
  s = s.replace(/-/g, "/");
  s = s.replace("T", " ");
  s = s.replace("Z", " GMT-0000");
  return new Date(Date.parse(s));
}

For full details on available attributes, formatting commands, and syntax rules, check out http://jsdoc.sourceforge.net as well the Javadoc conventions page at http://java.sun.com/j2se/javadoc/writingdoccomments.

Even if you don't plan on using the JSDoc tool to create source code documentation, the JSDoc conventions are useful for creating well-documented code. Plus, you may find in the future that if you would like to use the JSDoc generator, you're all set.

Functions

A function is the basic building block or organizing unit of JavaScript. A foundation of a house is composed of many building blocks. In the same way, a JavaScript or Ajax script usually consists of a set of functions.

These building blocks may be easy to take for granted. But just as a beautifully decorated home means nothing apart from its foundation, a killer Ajax or JavaScript animation routine is pretty meaningless without these building blocks to rest upon.

Creating a Function

A function is a module of JavaScript statements that together perform a specific action. Here's a basic example:

function addAndDisplay(a, b)
{
  var total = a + b;
  alert(total);
}

To call the function, you do this:

addAndDisplay(3, 2);

There are a few things to note. The function is named addAndDisplay() and takes two arguments: a and b. An argument (also called a parameter) is a variable or literal value that you want to pass on to the function to process. In this case, the calling function sends to the 3 and 2 integer values the function to do something with (add them together).

Inside the curly brackets, the first line adds together the arguments and assigns the sum to the total variable. The second line displays the total in an alert box. When the alert box is closed, the function ends and returns control to the code that called it.

As you can see, a function

  • Is called by another section of code to perform a process, return a result, or both

  • Hides the details of its programming logic from other parts of the code

A function can return a value to the calling code. For example, check out the following function:

function getTotal(subtotal)
{
  var t = subtotal * .05;
  return t;
}

The getTotal() function receives subtotal as an argument, multiples it by the state tax percentage, and then returns the total value to the statement that called the function using the return command.

When return executes, the function stops executing at that line and returns to the calling function. For example:

function createProfile(el)
{
if (el == null)
  {
    alert("Undefined DOM element. Cannot continue.");
    return;
  }
  else
  {
     // do something really important to el
  }
}

In this example, the function checks to see if the el parameter is null. If it is, the function ends processing after displaying an alert box. If not, the function continues.

Creating an Inline Function

JavaScript also supports inline functions, which enable you to define an unnamed function for use within a specific context. For example, suppose you want to display an alert message when the window loads. Using a normal function, you can structure your script as follows:

<script>
  function init()
  {
    alert("I am saying something important.");
  }

  window.onload = init;

</script>

The onload event is assigned the init() function as its event handler. However, you can also use an inline function and eliminate the specific function definition:

<script>
  window.onload = function() { alert("I am saying something important.") };
</script>

Another advantage is that you can reference variables within a specific scope without having to pass them to a function as arguments.

Overloading Functions

Function overloading is the concept of being able to pass varying amounts of arguments to a function. You can overload a function in JavaScript if you use the arguments property of a function. For example, suppose you wanted to create a function that added two numbers together and then returned the result. You could code it like this:

function add(a, b)
{
  return a + b;
}

However, your needs can change over time. Instead of two numbers, you might now need to add three or four or five numbers at a time. Instead of writing separate functions for each case, you could overload the add() function to do all these summing tasks:

function add()
{
  var t = 0;
  for (var i = 0, l = arguments.length; i < l; i++)
  {
    t += arguments[i];
  }
  return t;
}

The add() function creates a for loop to iterate through each of the supplied arguments. As it does so, it adds the current argument to the t variable. This total is then returned to the statement that called the function. Each of the following calls now works:

var t = add(2, 2);
var t1 = add(2, 4, 5);
var t2 = add(392, 1230, 3020202, 1, 2033);

You can also use the typeof() command to overload different data types inside the same function. For example, if I wanted to expand the functionality of add to "add" string values, I could modify the function as follows:

function add()
{
  var argType = typeof(arguments[0]);

  if (argType == "number")
  {
    var t = 0;
    for (var i = 0, l = arguments.length; i < l; i++)
    {
      t += arguments[i];
    }
    return t;
  }
  else if (argType == "string")
  {
    for (var i = 0, l = arguments.length; i < l; i++)
    {
      if (i == 0)
      {
        var s = arguments[i];
      }
      else
      {
        s += ", " + arguments[i];
}
     return s;
    }
    else
      return "Unsupported data type";
  }
}

The add() function examines the type of the first parameter and assigns the result to argType. If the type is a number, the routine continues just like the earlier example. If the type is a string, however, the function combines the arguments into a single comma-delimited string. If the type is neither a number nor a string, an error message is returned.

Data Types

JavaScript allows you to work with specific data types:

  • String

  • Number

  • Boolean

  • Null

  • Undefined

  • Array

  • Object

Strings, numbers, and Booleans are often known as primitive data types, null and undefined as special data types, and objects and arrays as composite data types.

Strings

A string is a collection of characters enclosed in single or double quotation marks. A string is also called a string literal. The following lines are examples of strings:

var wd = 'Kitchen sink';
var el = "<p>This is HTML.</p>";
var n = "3.14";
var char = 'z';
var special = "@#(*&^%$#@!~<>S"}{+=";
var blank = "";

As you can see, you can include most anything in a string — normal text, HTML tags, numeric values, special characters, and more.

Notice that you can have an empty string (""), which is not the same as a null or undefined value.

Because a string can be enclosed in either single or double quotation marks, you can easily embed a quotation mark and apostrophe by using the opposite type pair to enclose the string literal. For example:

var str = '"I like living dangerously", said Jack. "I am enclosing a quote in this
string."';
var str2 = "I'm happy, aren't I?";

Alternatively, you can use the backslash character () to "escape" an apostrophe/quotation mark if the string is enclosed by the same type of quotation mark. Here are a couple cases:

var str2 = 'I'm happy, aren't I';
var el = "<div id="container"></div>";

The backslash character tells the interpreter to treat the following quote mark as part of the string rather than as the ending delimiter.

For many tasks, you can work with string values as string literals in the manner in which I described. However, if you are going to parse, manipulate, transform, or otherwise pick on a string, you can also treat it as a String object.

Numbers

The number data type represents any sort of numeric value — integer, real floating-point number, octal, and even hexadecimal numbers.

Table 2-9 lists the variety of number values that are valid within JavaScript.

Table 2-9. Examples of Numbers

Number

Description

32

Integer

.00223

Floating-point number

1.42e5

Floating-point number

0377

Octal value

0x32CF

A hexadecimal integer.

In addition to these normal number types, JavaScript contains a special value NaN, which stands for "not a number." As you might expect, if you perform an invalid math operation, you'll get NaN as the result.

Boolean Values

A Boolean type represents either a true or a false value. You typically use it to determine whether a condition in your code is true or false. For example, suppose you assign false to the flagUser variable:

var flagUser = false;

You can then evaluate the flagUser variable to determine its Boolean state in an if control structure. For example:

if (flagUser == true)
{
  alert("Hey User! You are hereby flagged.");
}

The if statement displays the alert box if flagUser evaluates to true.

Note that a Boolean value is not wrapped in quotation marks. So notice the difference:

// Boolean
var isABoolean = true;
var isAString = "true";

Null Values

When a variable or object contains no value, its value is expressed as null. (Not the literal string "null", just null.) You can test whether a variable or object is null to determine if it was defined earlier in the code. For example:

if (myArray != null)
{
  doSomethingReallyImportant();
}

This code block evaluates the variable myArray. If its value is not equal to null, the condition evaluates to true and something really important happens.

A null value is not the same as an empty string, the number 0 or NaN, or the undefined data type, which I explain in the next section.

If you want to remove the contents of the variable, you can assign it a non-value by setting it to null:

if (loggedOut == true)
{
  userName = null;
}

So, in this example, if the loggedOut variable is true, the userName variable is reset.

Undefined Values

On first take, an undefined value sounds like just another name for null. But an undefined value is actually a different data type. An undefined value is returned by the interpreter when you access a variable that has been declared but never assigned a value. For example, the following snippet displays an alert box with undefined as the message.

var isSmiling;
alert (isSmiling);

You'll also get undefined if you try to call a property that does not exist. For example:

alert(document.theStreetThatHasNoName);

Arrays

So far, I've been talking about variables as individuals. An array, in contrast, is a collection of values. An array is grouped and indexed so that you can access a specific item stored in the group.

JavaScript stores arrays as Array objects, meaning that it has a variety of properties and methods. As you work with these members, you can perform numerous tasks.

Creating an Array

You can create a new array by assigning a variable to empty brackets:

var castMembers = [];

You can also create a new array by using new Array(). It goes like this:

var myArray = new Array();

However, using the new operator to create an array is considered old school and is not considered a good practice.

In some programming languages, you need to specify the number of items in an array at the time you define it. That's not so with JavaScript. It just increases the size of the array each time you add a new item to it.

Adding Items to an Array

To add items to the array, you simply assign a value to a specific index in the array. The index is designated by a value within brackets, such as the following:

var castMembers = [];
castMembers[0] = "Jerry";
castMembers[1] = "George";
castMembers[2] = "Elaine";
castMembers[3] = "Kramer";

Notice that, because arrays are zero-based, you start counting at 0 rather than 1.

You can also define the array items by passing values as parameters:

var primeNumbers = [1, 3, 5, 7, 11];

Storing Multiple Types in an Array

You can store most any kind of data in an array, including strings, numbers, Boolean values, undefined and null values, objects, and functions. You can even store an array within an array if you really want to. What's more, you can store various types of data within the same array. For example, consider the following array that contains a string, number, function, DOM object, and Boolean value:

var el = document.getDocumentById("easy_bake_oven");
var pieLove = ["pie", 3.14, function() { alert("Apple Pie") }, el, true];

Getting and Setting the Size of an Array

You can get the number of items in an array by accessing its length property. (Yes, an array is an object, so it has its own set of properties and methods.) For example:

var primeNumbers = [1, 3, 5, 7, 11];
alert(primeNumbers.length));

The alert box displays 5.

In most cases, you don't need to explicitly set the size of an array, because it dynamically resizes on its own when you add or remove items from it. However, when you need to specify an array's size, you can assign a value to the length property. For example, the following line increases the size of the array to 10:

primeNumbers.length = 10;

Note that no new data items are created when you do so.

If you specify a length that is smaller than the current size of the array, the items that fall outside of that length value get the axe.

Keep in mind that because array indices start at 0, the last item in the array will have an index value one fewer than the total number of elements in an array.

Accessing Items in an Array

You can access any value in the array according to its index. For example, to write the third item in a states array to the document, you can use the following code:

function showHomeState(idx)
{
  document.write("<p>Your home state is " + states[idx] + "</p>";
}

You can also iterate through an array using a for loop if you want to work with each item in the group:

var castMembers = [];
castMembers[0] = "Jerry";
castMembers[1] = "Jan";
castMembers[2] = "Elias";
castMembers[3] = "Bob";
document.writeln("<ul>");
for (var i = 0, l = castMembers.length; i < l; i++)
{
  document.writeln("<li>" + castMembers[i] + "</p>");
}
document.writeln("</ul>");

In this example, the castMembers array defines four string items. The length property determines the size of the array, so you know the number of times to loop through the for structure.

Notice that the length property is assigned to a variable rather than being included directly inside the for loop like this:

// Valid, but less efficient
for (var i = 0; i < castMembers.length; i++)
{
}

Although that is perfectly valid, it is not as efficient, particularly for large arrays. That's because the interpreter has to evaluate the length property on each pass rather than once. Therefore, it's a good habit to assign an array's length to a variable for loops.

The HTML output for this script is as follows:

<ul>
<li>Jerry</li>
<li>Jan</li>
<li>Elias</li>
<li>Bob</li>
</ul>

Passing by Reference or Value?

When a primitive variable (string, number, or Boolean) is passed into an array, the array creates a copy of the variable's value rather than storing a reference to that variable. In programming lingo, this is known as passing by value. Here's an example that demonstrates the difference:

var n = 100;
var b = true;
var s = "string";
ar = [n, b, s];

document.write("<p>[First pass]</p>");
for (var i = 0; i <= 2; i++)
  document.write("<p>"+ar[i]+"</p>");

n = 200;
b = false;
s = "new and improved string";

document.write("<p>[Second pass]</p>");
for (var i = 0; i <= 2; i++)
  document.write("<p>"+ar[i]+"</p>");

Notice that the variables n, b, and s are passed as parameters in the ar array. The for loop then outputs the values of the array items as HTML content to the document. The variables are then updated and given new assignments. However, when the same for loop is run again, the original values are output. Check out the HTML content that is output:

[First pass]
100
true
string
[Second pass]
100
true
string

However, when you pass an object or a function into an array, the array stores a reference to those advanced data types rather than a copy of it. As a result, any changes you make to the object or function outside the array are reflected when you access its corresponding item in the array. This is called passing by reference.

The Document Object Model

The Document Object Model (DOM) provides a scripting interface into an HTML document so that you can work with all its elements within a hierarchical structure. As a result, you can navigate through the document structure with JavaScript to access and manipulate anything inside of it.

The DOM is a standard that was originated by the W3C, the Web standards body. There are three DOM levels:

  • Level 1: Level 1 contains the core functionality to be able to script the DOM for an HTML or XML document. Any modern browser provides support for the Level 1 version of the DOM.

  • Level 2: Level 2 extends DOM support to include new core functionality, event listeners, CSS DOM, and traversal and range. Safari and other browsers generally provide strong support for aspects of DOM2.

  • Level 3: Level 3 adds support for newer properties and methods, keyboard events, and XPath. Safari provides strong support for Level 3.

The DOM as a Tree

You'll find it helpful to think of the DOM as a hierarchical tree that contains all the parts of the HTML document — elements, attributes, text, comments, and so on. In DOM lingo, these individual pieces are known as nodes.

When working with HTML markup, the primary building block of your document is the element. However, when working with the DOM, the basic piece you will work with is the node. Remember that they are not identical. Although the DOM tree is dominated by element nodes, you need to be aware of several other types.

Just like a family tree in real life, each of the nodes is interconnected. A node can have a parent, a sibling, a child, and the occasional half-crazy "grandparent" that no one talks about. The document object is the family patriarch, serving as the container for all the nodes (the descendants) of the HTML file. The document object has no corresponding HTML element. The html, head, and body elements are contained by document.

One point I should stress is that a DOM hierarchy is not identical to the natural element hierarchy you find in an HTML document. Take, for example, the following plain vanilla HTML file:

<html>
    <head>
        <title>Really Awesome Web Page</title>
    </head>
    <body>
        <div id="container">
            <h1>Pretty awesome heading</h1>
            <p id="para1">Pretty lame paragraph</p>
        </div>
    </body>
</html>

The levels of indentation show the natural element hierarchy in the document. Or, you can express the same hierarchy in a visual tree, as shown in Figure 2-4.

An element-based hierarchy is not the same as a DOM.

Figure 2-4. An element-based hierarchy is not the same as a DOM.

Every HTML element in the DOM has properties that correspond to the element's attributes. For example, an img has src and alt properties. However, DOM elements also have a set of common properties and methods.

In the DOM, elements are just one type of node. As a result, you have to express other nodes of the document, such as attributes and text content, in the tree. The text content inside an element is a child node of the parent element. So, for example, Pretty lame paragraph is considered a child node of the p element that contains it.

Attributes are also considered nodes, but they are a bit of a special case. They don't participate in the parent/child relationships that the other nodes do. Instead, they are accessed as properties of the element node that contains them. Figure 2-5 shows the same document in a DOM tree.

When working with the DOM in JavaScript, you typically work with the document object and DOM element objects. Each DOM element object has childNodes and attributes properties for accessing these nodes, as shown in Figure 2-6. And, as Figure 2-6 illustrates, each node has a nodeType property that can determine the type of node you are working with.

A DOM tree consists of many types of nodes.

Figure 2-5. A DOM tree consists of many types of nodes.

JavaScript's view of the DOM.

Figure 2-6. JavaScript's view of the DOM.

Understanding Node Types

Before you begin to access the DOM, it is important to take a moment to identify the node types that the DOM contains and that you'll work with. The nodeType property of each DOM node returns a constant from the Node object that represents the type of node. These include:

  • Node.ELEMENT_NODE

  • Node.ATTRIBUTE_NODE

  • Node.TEXT_NODE

  • Node.CDATA_SECTION_NODE

  • Node.ENTITY_REFERENCE_NODE

  • Node.ENTITY_NODE

  • Node.PROCESSING_INSTRUCTION_NODE

  • Node.COMMENT_NODE

  • Node.DOCUMENT_NODE

  • Node.DOCUMENT_TYPE_NODE

  • Node.DOCUMENT_FRAGMENT_NODE

  • Node.NOTATION_NODE

Each of the Node constants represents an unsigned short number. ELEMENT_NODE represents 1, ATTRIBUTE_NODE equals 2, and so on.

Accessing the DOM from JavaScript

You access the document object through a named object called, appropriately enough, document. Therefore, if you want to access a document object's property or method, you can do so directly. For example:

document.open();

You can access other elements and nodes in the DOM in a variety of ways, as shown in the following sections.

Accessing a Specific Element

When you know the id of an element, the most common way to access the element node is by using getElementById(). This method searches the DOM looking for the one node that has an id value matching the string you specify. For example, consider the following:

<html>
<body>
<div id="header">
<p>Rawhide!</p>
</div>
</body>
</html>

If you wanted to access the div, you could use the following line:

var d = document.getElementById("header");

The variable d now references the div id="header" element. You can now use the d variable to access its properties and perform methods on it. For example, to set its text color, you can use the following:

d.style.color = #cccccc;

Accessing a Set of Elements

In addition to accessing a specific element, you'll find occasions in which you'll want to access all element nodes of a given kind. You can also access a set of elements by using the document object's getElementsByTagName() method. This method takes an HTML element as its parameter:

var e  = document.getElementsByTagName(elementName);

This method returns all the elements with the specified tag name as a NodeList, or a collection of nodes ordered by their appearance in the document.

For example, to get all the p elements in a document and return it as a NodeList, you can type the following:

var cPara = document.getElementsByTagName("p");

After you have the collection of elements through either of these techniques, you can access a particular node in the NodeList by using its index number. For example, to access the first p element in the document, you can write this:

var p1 = cPara[0];

If you are accessing a specific p element, such as the first, you can combine both lines into a single call:

var p1 =  document.getElementByTagName("p")[0];

This returns the first p element and assigns it to the p1 variable.

More commonly, you can use it in a for loop to perform an action on each element:

for (var i = 0; i < cPara.length; i++)
{
    var para = cPara[i];
    para.style.color = #000000;
}

This code block iterates through each p element in the document and changes its text color to black. Notice that because the cPara variable is a nodeList, you can access its length property to determine the number of elements returned.

In addition, you can use getElementsByTagName() to return all element nodes inside the calling element by using * as the parameter:

var cElements = document.getElementsByTagName("*");

This call returns all the descending elements inside the document, regardless of the level of hierarchy they sit on.

Accessing Family Members

You can access nodes related to other nodes through more "familial ways" by using several node properties:

  • parentNode returns the parent node of the current element.

  • firstChild gets the first child of a node.

  • lastChild gets the last child of a node.

  • previousSibling gets the node just before the current one in the parent's NodeList.

  • nextSibling gets the node just after the current one in the parent's NodeList.

  • childNodes gets all the children of a node.

For example, you can use the parentNode property to get the parent node of a given element. For example, consider the following HTML snippet:

<div id="container">
<p id="p1"></p>
</div>

The following JavaScript returns a reference to the div element:

iParent = document.getElementById("p1").parentNode;

A parent node must be the document, the element node, or a document fragment.

In addition, suppose you wanted to return all the nodes that were direct children under an element. You could use the childNodes property instead to retrieve its children as a NodeList and store it in a variable. Here's what you would code:

var c = document.getElementById("container");
var cChildren = c.childNodes;

In this code, the element with an id of container is assigned to the c variable. Its children are then assigned to the cChildren variable and are ready for action.

You can also use the hasChildNodes() method to verify whether an element has child nodes. For example:

var c = document.getElementById("container");
if (c.hasChildNodes())
{
    var cChildren = c.childNodes;
}

Retrieving Attributes

Attributes are technically nodes in a DOM, but don't think of them as being equal to element nodes. You cannot, for example, retrieve a list of id attribute nodes through some sort of GetAttributeByName() method. In fact, except in rare occasions, there would be no practical reason for doing so because attributes are inextricably associated with an element. Not surprisingly, attributes are accessible through a DOM element by accessing its attributes property or by using one of two methods (hasAttributes() and hasAttribute()).

Accessing All Attributes

The object that returns from the attributes property is called NamedNodeMap object, which is similar to a NodeList except that its items are listed in arbitrary order, rather than a specific defined order.

If you want to retrieve a list of attributes for a given element, you might write something like the following:

var atts = document.getElementById("container").attributes;

You can then work with the attributes by accessing their name and value properties. For example:

var atts = document.getElementById("container").attributes;
var str = "";

for (var i = 0; i < atts.length; i++)
{
str += "Name:" + atts[i].name + " Value:" + atts[i].value + "<br/>";
}

This code block gets the attributes for an element and outputs the name and value for each attribute to the str variable.

You can check to see whether an element has attributes by using the hasAttributes() method:

var ctr = document.getElementById("container");
if (ctr.hasAttributes())
{
    var atts = ctr.attributes;
}

Accessing a Specific Attribute

You can also access a specific attribute using the element's getAttribute() method. Simply enter the name of the attribute as the parameter. Suppose, for example, you want to get the href attribute from a link:

var att = document.getElementById("book").getAttribute("href");

You can also check for the existence of an attribute with the hasAttribute() method. To verify whether an element has a style attribute, use the following code:

if (document.getElementById("contentMajor").hasAttribute("style"))
{
    var att = document.getElementById("contentMajor").getAttribute("style");
}

Manipulating the DOM

You can do more with the DOM than simply look at a document. In fact, you can also manipulate it — creating nodes, adding them to the DOM tree, editing nodes, and removing parts of a document you have no more use for.

When it comes to creating nodes, the document is the one in charge. The document creates all the nodes, and then you can insert it into the DOM tree at the appropriate location.

In the sections that follow, I'll show you how to add and remove various parts of a document to and from the DOM.

Creating an Element and Other Nodes

The document object has several methods for creating nodes. I'll focus on element nodes here.

To create an element, use the document.createElement() method. This method creates an instance of the element specified by the parameter. For example, to create a p element, use this:

var para = document.createElement("p");

The createElement() method creates the p element and returns the node, which is assigned to the para variable.

Note that the act of creating an element does not automatically add it to the DOM tree. The instance only exists in your script until you explicitly add it. It's in a sort of limbo land — a node without a country, if you will. Instead, you need to insert it into the document hierarchy to be a card-carrying node of the DOM.

Adding a Node to the DOM

DOM elements have two methods that you can use to add a node to the tree:

  • appendChild(node) adds the node as a child at the end of the current element's childNodes list.

  • insertBefore(newNode, targetNode) adds a new element as a child of the current node but inserts it just before the node specified by the targetNode parameter.

To show these in action, I'll be working with this HTML document:

<html>
  <head>
    <title>FavFilms</title>
  </head>
  <body>
    <div id="content">
      <h1 id="header1">Welcome to the World of Cinema</p>
      <p id="p1">Favorite films are shown below:</p>
      <ol id="movieList">
        <li id="film_30329">The Shawshank Redemption</li>
        <li id="film_30202">Casablanca</li>
        <li id="film_20216">Braveheart</li>
        <li id="film_28337">Groundhog Day</li>
      <ol>
    </div>
  </body>
</html>

Suppose that I wanted to add a new film onto the end of the movieList. I'd use the following code:

var fa = document.createElement("li");
document.getElementById("movieList").appendChild(f);

At the same time, I'd like to add a movie in the spot just before Casablanca by using insertBefore():

var fb = document.createElement("li");
var casa = document.getElementById("film_30202");
document.getElementById("movieList").insertBefore(f, casa);

Although there is no insertAfter() method, you can perform the equivalent functionality by using insertBefore() in combination with the nextSibling property of the targetNode. So, supposing I wanted to add a node after Braveheart, I could use this:

var fb = document.createElement("li");
var br = document.getElementById("film_20216");
document.getElementById("movieList").insertBefore(f, br.nextSibling);

It's time to look at our results. The ordered list would now be updated to include the new element I added:

<ol id="movieList">
  <li id="film_30329">The Shawshank Redemption</li>
  <li/>
  <li id="film_30202">Casablanca</li>
  <li id="film_20216">Braveheart</li>
  <li/>
  <li id="film_28337">Groundhog Day</li>
  <li/>
<ol>

Creating Other Elements

The document object contains methods for creating the rest of the common node types: attribute, text, comment, and document fragment. Each of these methods returns a node that you can add to your document using appendChild() or insertBefore().

An attribute node represents an element's attribute. To create an attribute, you use createAttribute(). For example:

var a = document.createAttribute("alt");
a.nodeValue = "Welcome to DOM and DOMMER.";
document.getElementById("logo").appendChild(a);

A text node is a container of text. When you are introduced to the DOM, it is probably natural to think of text being a property of an element. But text inside of an element is contained by a child text node. To create a text node, use createTextNode(). For example, the following code snippet creates a text node and adds it to the end of a p element with an id of para:

var t = document.createTextNode("I scream for ice cream.");
document.getElementById("para").appendChild(t);

A comment node represents an HTML comment. To create it, use createComment():

var c = document.createComment("Insert new toolbar here.");
document.getElementById("toolbar_container").appendChild(c);

Finally, a document fragment is a temporary off-line document that you can use to create and modify part of a tree before you add the fragment to the actual DOM tree. When you're manipulating the DOM, it's much more efficient to work with a document fragment during the processing of a subtree (less overhead) than to always work directly with the actual DOM. To create a document fragment, use createDocumentFragment(). For example, the following script creates a document fragment, adds nodes to it, and appends it to the document:

var df = document.createDocumentFragment();

for (var i = 0; i < 30; i++)
{
  var e = document.createElement("p");
  var t = document.createTextNode("Line " + i);
  e.appendChild(t);
  df.appendChild(e);
}

document.getElementById("content").appendChild(df);

Now that you know how to create the other node types, I want to revisit the movie list example in the previous section. Instead of adding empty li elements, I want to add attribute and text nodes needed to fill out the ordered list appropriately.

First, I want to add a new film onto the end of the movieList using the following code:

var e; // Element
var a; // Attribute
var t; // Text
var nd; // Target/Parent

e = document.createElement("li");
a = document.createAttribute("id", "film_29299");
t = document.createTextNode("Babette's Feast");
e.appendChild(a);
e.appendChild(t);
document.getElementById("movieList").appendChild(e);

e = document.createElement("li");
a = document.createAttribute("id", "film_29323");
t = document.createTextNode("Amélie (Le Fabuleux destin d'Amélie Poulain)");
e.appendChild(a);
e.appendChild(t);
nd = document.getElementById("film_30202");
document.getElementById("movieList").insertBefore(e, nd);
e = document.createElement("li");
a = document.createAttribute("id", "film_30276");
t = document.createTextNode("Vertigo");
e.appendChild(a);
e.appendChild(t);
nd = document.getElementById("film_20216");
document.getElementById("movieList").insertBefore(f, nd.nextSibling);

The ordered list will now look the way I want it to:

<ol id="movieList">
  <li id="film_30329">The Shawshank Redemption</li>
  <li id="film_29323">Amélie (Le Fabuleux destin d'Amélie Poulain)</li>
  <li id="film_30202">Casablanca</li>
  <li id="film_20216">Braveheart</li>
  <li id="film_30276">Vertigo</li>
  <li id="film_28337">Groundhog Day</li>
  <li id="film_29299">Babette's Feast</li>
<ol>

Setting a Value to an Attribute

The setAttribute() method is a shortcut to creating an attribute and adding it to an element. This method sets the attribute value for an element, but if the attribute doesn't exist, the method creates it. It takes the attribute name and value as parameters:

setAttribute("name", "value")

For example, if you want to change the href of a link, you might use this:

document.getElementById("myblog").setAttribute("href",
"http://richwagnerwords.com");

Here's a little more detailed example of using setAtttribute() to clean up a document. Suppose you have an HTML document that has attributes with uppercase names. If you want to convert them to all lowercase, you can use the following script:

var all = document.getElementsByTagName("*");
for (var i = 0; i < all.length; i++)
{
  var e = all[i];

  for (var j = 0; j < all.length; j++)
  {
    e.attibutes[j].setAttribute(all.attributes[j].nodeName.toLowerCase());
  }
}

The script looks for all the elements in a document and returns them as a NodeList. The first for loop iterates through all the elements and assigns the e variable to be the current element in the loop. The second for loop cycles through all the attributes of e and uses setAttribute() in combination with toLowerCase().

Moving a Node

Although no moveNode() method is defined in JavaScript, appendChild() and insertBefore() do the same thing. In addition to adding new nodes you create, these two methods enable you to move a node from one location to another in the tree. For example, consider the following document:

<html>
  <head>
  </head>
  <body>
    <div id="header">
      <img id="logoImg" src="logo.png"/>
    </div>
    <div id="footer">
    </div>
    </body>
</html>

If you want to move the image from the header to the footer, you can write this:

var i = document.getElementById("logoImg");
document.getElementById("footer").appendChild(i);

When this code is executed, the appendChild() method moves the logoImg from its current location and adds it as a child to the footer div.

Cloning a Node

You can clone a node and add it elsewhere to the document tree by using the DOM element's cloneNode() method. This method copies the specified node and returns a new instance that is not part of the DOM. You can then add it wherever you want using the familiar appendChild() and insertBefore() methods.

This method takes a single Boolean parameter:

cloneNode(deepBoolean)

If the parameter is set to true, all subnodes of the current node are copied along with it.

When cloning nodes, you have to be careful. Every part of the node comes with using cloneNode(), including its id. Be sure to update the id before you add it to the document tree.

To demonstrate, I'll begin with the following document:

<html>
  <head>
  </head>
  <body>
    <div id="right_box">
<p id="main">All content should begin with this sentence.</p>
    </div>
    <div id="left_box">
    </div>
    </body>
</html>

If I want to copy the paragraph to the left_box div, I can enter the following:

var cn = document.getElementById("main_right").cloneNode(true);
cn.setAtttribute("id", "main_left");
document.getElementById("left_box").appendChild(cn);

Removing a Node from the DOM

To remove a node, call the removeChild() method of its parent, specifying it as the parameter. For example, to remove a paragraph with id="p1", use the following code snippet:

var cp = document.getElementById("p1");
cp.parentNode.removeChild(cp);

In this code, the p variable is assigned the returning node of the specified paragraph element. Using parentNode to reference its parent, the removeChild() method is then called, specifying cp as the node to delete. The paragraph is removed from the DOM.

Or, suppose you want to remove all the children an element. To do so, you can loop through all the child nodes and delete them one at a time. Here's the code you can use:

while (bodyContent.childNodes[0])
{
  bodyContent.removeChild(bodyContent.childNodes[0]);
}

In this routine, the while loop checks to see if a child node exists for the current node. If it does, the child node is removed using removeChild(). This process repeats until there are no childNodes[0].

Removing an Attribute

Suppose you have had it with an attribute and simply want to rid yourself of the pain and aggravation. Or maybe you just don't have a use for it anymore. If so, you can use the removeAttribute() method to delete an attribute from the DOM. The following rather draconian script removes all the alt attributes from the document — simply out of spite! Here's the code:

var kitAndKaboodle = document.getElementsByTagName("*");
for (var i = 0; i < kitAndKaboodle.length; i++)
{
  kitAndKaboodle[i].removeAttribute("alt");
}

Summary

In this chapter, I walked through some of the basics that will help you as you begin iPhone web app development. I began by showing you how to use and incorporate the new HTML 5 media elements into your web app to display rich media and serve as an alternative to using Flash or another unsupported technology. The chapter continued with an in-depth primer on the basics of JavaScript, which is a skill set you'll want to have as you begin to create functionality for your web apps. Finally, I closed out with a survey of the Document Object Model and how you can use it to find page data as well as manipulate it.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.2.141