34
Parsing simple XML document: Surf directly to Zend . See that cool menu having 4 main categories ("Products", "Company", "Partners", and "Developer Zone")? Let's think that you have to find the way to store menu data of "Company" category in plain text file. So, we have following tree structure: |= Company |== Corporate Profile |== Management |== Investors |== Customers |== News |== = Press Releases |== = In the press |== = Events |== iSeminar |== Jobs |== Contact Us Representation of the above structure in XML would be something like this: PHP Example: (!) <?xml version="1.0" encoding="ISO-8859-1"?>

Parsing Simple XML Document

  • Upload
    james

  • View
    3.147

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Parsing Simple XML Document

Parsing simple XML document:

Surf directly to Zend. See that cool menu having 4 main categories ("Products", "Company", "Partners", and "Developer Zone")? Let's think that you have to find the way to store menu data of "Company" category in plain text file. So, we have following tree structure:

| = Company

| = =  Corporate Profile

| = =  Management

| = =  Investors

| = =  Customers

| = =  News

| = = =  Press Releases

| = = =  In the press

| = = =  Events

| = =  iSeminar

| = =  Jobs

| = =  Contact Us

Representation of the above structure in XML would be something like this:

PHP Example: (!)

<?xml version="1.0" encoding="ISO-8859-1"?> <menu name="Company">     <item>         <caption>Company</caption>         <url value="http://zend.com/corporate_profile.php"/>     </item>     <item>         <caption>Corporate Profile</caption>         <url value="http://zend.com/ corporate_profile.php"/>     </item>     <item>         <caption>Management</caption>         <url value="http://zend.com/management.php"/>     </item>     <item>         <caption>Investors</caption>         <url value="http://zend.com/investors.php"/>     </item>     <item>         <caption>Customers</caption>         <url value="http://zend.com/customers.php"/>     </item>     <item>         <caption>News</caption>         <url value="http://zend.com/aboutzend_news.php"/>

Page 2: Parsing Simple XML Document

        <item>             <caption>Press Releases</caption>             <url value="http://zend.com/aboutzend_news.php"/>         </item>         <item>             <caption>In the press</caption>             <url value="http://zend.com/press.php"/>         </item>         <item>             <caption>Events</caption>             <url value="http://zend.com/phpevents.php"/>         </item>     </item>     <item>         <caption>iSeminar</caption>         <url value="http://zend.com/iseminar.php"/>     </item>     <item>         <caption>Jobs</caption>         <url value="http://zend.com/careers.php"/>     </item>     <item>         <caption>Contact Us</caption>         <url value="http://zend.com/contact.php"/>     </item> </menu>

Pay attention to how submenu categories are handled.

Now let's turn our attention to XML data parsing in PHP. One way to do it is to use EXPAT 's compatible functions (EXPAT extension provides PHP with support for XML parser object creation and successive assigning of parse event handlers). I believe that with complex XML files EXPAT event handlers prove to be not very flexible. As the way out of it PHP has xml_parse_into_struct() function. This tutorial uses it for XML parsing:

PHP Example: (!)

<?PHP function print_error() {     global $parser;     die(sprintf("XML Error: %s at line %d",         xml_error_string($xml_get_error_code($parser)),         xml_get_current_line_number($parser)     )); }     

//create xml parser object $parser = xml_parser_create();

//this option ensures that unneccessary white spaces //between successive elements would be removed xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,1);

//to use XML code correctly we have to turn case folding

Page 3: Parsing Simple XML Document

//(uppercasing) off. XML is case sensitive and upper //casing is in reality XML standards violation xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);

//read XML file into $data $data = implode("",file('menu.xml'));

//parse XML input $data into two arrays: //$i_ar - pointers to the locations of appropriate values in //$d_ar - data value array xml_parse_into_struct($parser,$data,&$d_ar,&$i_ar) or print_error();

//to view content of $d_ar and/or $i_ar uncomment lines below //echo '<pre>'; //print_r($d_ar); //print_r($i_ar);

//cycle all <item> tags. //$i_ar['item'] contains all pointers to <item> tags for($i=0; $i<count($i_ar['item']); $i++) {     //since we have <item> nested inside another <item> tag,     //we have to check if pointer is to open type tag.     if($d_ar[$i_ar['item'][$i]]['type']=='open') {         //now for all content within single <item> element         //extract needed information         for($j=$i_ar['item'][$i]; $j<$i_ar['item'][$i+1]; $j++) {             if($d_ar[$j]['tag'] == 'caption') {                 $caption = $d_ar[$j]['value'];             }elseif($d_ar[$j]['tag'] == 'url') {                 $url = $d_ar[$j]['attributes']['value'];             }         }         //output link         echo '<a href="'.$url.'">'.str_repeat('=',$d_ar[$j]['level']-1).$caption.'</a><br>';     } }

//unseting XML parser object xml_parser_free($parser);

/* *tab-width=4        *indent=4 *width=90 */ ?>

            

After you understand xml_parse_into_struct() function everything, in the above code must be quite simple. So, let's us discuss this function in more details.

int xml_parse_into_struct(int parser, string data, array &values, array &index)

Page 4: Parsing Simple XML Document

This function parses XML data into two arrays values and index. Values is the array of all XML elements in the document. Index array contains pointers to element start and close locations.Ex:

PHP Example: (!)

<?PHP

function print_error() {     global $parser;     die(sprintf("XML Error: %s at line %d",         xml_error_string($xml_get_error_code($parser)),         xml_get_current_line_number($parser)     )); }     

//create xml parser object $parser = xml_parser_create();

//this option ensures that unneccessary white spaces //between successive elements would be removed xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,1);

//to use XML code correctly we have to turn case folding //(uppercasing) off. XML is case sensitive and upper //casing is in reality XML standards violation xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);

//parse XML input $data into two arrays: //$i_ar - pointers to the locations of appropriate values in //$d_ar - data value array $data = '<item><sub_item>Test Text</sub_item></item>'; xml_parse_into_struct($parser,$data,&$d_ar,&$i_ar) or print_error();

//view content of $d_ar and $i_ar echo '<pre>'; print_r($d_ar); print_r($i_ar);

//unseting XML parser object xml_parser_free($parser);

/* *tab-width=4        *indent=4 *width=90 */?>

    

$d_ar in example above would contain: PHP Example: (!)

Page 5: Parsing Simple XML Document

Array (     [0] => Array (         [tag] => item         [type] => open         [level] => 1         )     [1] => Array (         [tag] => sub_item         [type] => complete         [level] => 2         [value] => Test Text         )     [2] => Array (         [tag] => item         [type] => close         [level] => 1         ) )

And $i_ar would be PHP Example: (!)

Array (     [item] => Array (         [0] => 0         [1] => 2         )     [sub_item] => Array (         [0] => 1         ) )

As you can see $i_ar['item'][0] = 0 therefore entering point of first <item> element (and last in our example) is $d_ar[0] while its exiting point is $d_ar[$i_ar['item'][1]] = $d_ar[2]. For sub_item (which has content within it, therefore being of type=complete i.e CDATA), there's single point $d_ar[$i_ar['sub_item'][0]] = $d_ar[1]

All this may seem a little bit scaring at first, but in reality it's very simple.

Page 6: Parsing Simple XML Document

External JavaScript and PHP

The syntax

The syntax to referencing a PHP file using external JavaScript is consistent enough with what we already know:

<script type="text/javascript" src="myscript.php"></script>

where "myscript.php" is either an absolute or relative path to a PHP script instead of the usual .js file. You can even pass parameters to the PHP script through the URL string:

<script type="text/javascript" src="myscript.php?id=3&name=george"></script>

Your PHP script can then get to these parameters using the global variable $HTTP_GET_VARS[]. So you're probably wondering at this point: "So what's the catch?" Well, there is no catch really, just a few limitations. Since we are invoking the PHP script indirectly and via JavaScript, the final output of the PHP script needs to be valid JavaScript. Think of it as a dynamic .js file, bounded by the same limitations as a regular .js file. A normal PHP script called inside a PHP page can output raw HTML and modify the source code of the page. The JavaScript invoked version obviously cannot, but don't worry, there's plenty of what it can do.

Here's a basic example of a PHP script- ip.php- being called by external JavaScript to do something that JavaScript alone cannot:

<?//"ip.php" example- display user IP address on any pageHeader("content-type: application/x-javascript");$serverIP=$_SERVER['REMOTE_ADDR'];echo "document.write(\"Your IP address is: <b>" . $serverIP . "</b>\")";?>

And once called by external JavaScript:

<script type="text/javascript" src="ip.php"></script>

Output:

In the above, we have a normal PHP script that writes out the IP address of the visitor when referenced using external JavaScript, with two important details:

A JavaScript header is sent at the very beginning to inform the page that our PHP script is outputting a JavaScript file.

Since the final output of our PHP script needs to be a valid .js file, whatever the PHP outputs must conform to valid JavaScript syntax. So to display the IP address from the perspective of JavaScript, the echo function above includes "document.write()" as part the content to send back to the page.

Page 7: Parsing Simple XML Document

Notice how I didn't output the JavaScript script tag itself (<script></script>), as just like inside a regular .js file, this isn't required nor valid.

The ability to reference a PHP script inside your external JavaScript can be very useful! It means your JavaScript now has access to once exclusive information on the server side, whether it's the server time, the visitor's IP address, a list of all the files within a certain directory, or mySQL database information. Furthermore, even regular HTML pages can utilize this information, since all that's required is a JavaScript on these pages that in turn references the desired PHP script on your server or beyond. Want to display the visitor's IP address on a static html page- any html page? The above example already does that.

Ok, time to put our new found discovery to better use- how about a JavaScript slideshow that automatically rotates/displays all images within a directory?

A pesky problem with JavaScript slideshows it that you need to manually specify the images to display inside the script. If you have many images, this can quickly drive you up the wall. How about automating the process through PHP, by getting it to retrieve the file names of all images and passing it to your JavaScript slideshow to play around with?

Lets get straight to it, by creating a PHP script that gets the file names of all images inside the directory the script is placed in, and return them as a JavaScript array:

<?//PHP SCRIPT: getimages.phpHeader("content-type: application/x-javascript");

//This function gets the file names of all images in the current directory//and ouputs them as a JavaScript arrayfunction returnimages($dirname=".") {$pattern="(\.jpg$)|(\.png$)|(\.jpeg$)|(\.gif$)"; //valid image extensions$files = array();$curimage=0;if($handle = opendir($dirname)) {while(false !== ($file = readdir($handle))){if(eregi($pattern, $file)){ //if this file is a valid image//Output it as a JavaScript array elementecho 'galleryarray['.$curimage.']="'.$file .'";';$curimage++;}}

closedir($handle);}return($files);}

echo 'var galleryarray=new Array();'; //Define array in JavaScriptreturnimages() //Output the array elements containing the image file names?>

This script will grab the file names of every image in a directory (based on its extension) and output them as JavaScript array elements:

Page 8: Parsing Simple XML Document

var galleryarray=new Array();galleryarray[0]='dog.gif'galleryarray[1]='cat.gif'galleryarray[2]='person.gif'

where "dog.gif", "cat.gif" etc are the file names of the images inside the directory. Now that the tedious part is taken care of by PHP, we can go ahead and create a JavaScript slideshow script that uses this array to display all images inside the directory!

<script src="pics/getimages.php"></script>

<script type="text/javascript">

var curimg=0function rotateimages(){document.getElementById("slideshow").setAttribute("src", "pics/"+galleryarray[curimg])curimg=(curimg<galleryarray.length-1)? curimg+1 : 0}

window.onload=function(){setInterval("rotateimages()", 2500)}</script>

<div style="width: 170px; height: 160px"><img id="slideshow" src="pics/bear.gif" /></div>

Page 9: Parsing Simple XML Document

JAVSCRIPT: FORMS INTRO

Menus

You can use the Rollovers that we talked about in Lesson 12 to create some cool menus if you want. That is what I did for the menu on the left side of each of these pages.

Another way to create a menu utilizing JavaScript is to use a drop down list as shown in the simple demo below. I included a few of our lessons in the menu for this demo. Try it if you want, but remember you will need to use the back button on your browser to return to this page. If you decide to use this type of menu, then you will probably want to put a similar menu on all your pages.

The JavaScript code for a menu such as the one above is really quite short but I find it difficult to understand. So, I decided to take the lengthy approach to explaining the code here. If you are interested in just the final code, then feel free to go here to see it.

The drop down list is one of the elements that is available in a Form. We discussed the basics of the Form in Lesson 6. You may want to take a look at that now to refresh your memory. I also strongly recommend that you visit our Library and study the section on Forms at "Sizzling HTML Jalfrezi".

Here is the HTML code I used to create the drop down list for our demo:

<FORM NAME="demo"><SELECT NAME="menu" onChange="loadPage()"> <OPTION VALUE="lesson11.htm">Lesson 11 <OPTION VALUE="lesson12.htm">Lesson 12 <OPTION SELECTED VALUE="lesson13.htm">Lesson 13 <OPTION VALUE="lesson14.htm">Lesson 14</SELECT></FORM>

As shown in the above HTML code, the <SELECT> tag is used to create a drop down list.

Nested between the <SELECT> and </SELECT> tags are <OPTION> tags.

Note that there is one <OPTION> tag for each menu entry. The VALUE property of the <OPTION> tag contains the URL of a page and the text following the tag appears in the drop down menu list.

Note that our third <OPTION> tag in the list has SELECTED in it. This identifies the selection that will be the default when the page loads.

The onChange method of the <SELECT> tag calls a function that is used to load the specified URL. Here is the code for that function.

Page 10: Parsing Simple XML Document

function loadPage(){ var sel_idx = document.demo.menu.selectedIndex var urlToLoad = document.demo.menu.options[sel_idx].value

location.href = urlToLoad }

It is important to understand that the option object that is defined by the <OPTION> tags is an Array. In the function above, the variable sel_idx is set equal to the value of the selectedIndex. The selectedIndex is the number of the selected element of the array (remember that the number of the first element in an Array is 0). The urlToLoad variable is the value of the option element that has been selected, which is the URL of the page we wish to load.

Click here if you would like to test our drop down list menu and see the values of sel_idx and urlToLoad that result when you select each of the possible options.

The last line of the function loads the page into the browser utilizing the location object.  

Final Drop Down List Code for our Menu

The code we did above will work just fine. However, most of the time you will see the loadPage() function and Form code written as shown below:

function loadPage(fInfo){ location.href = fInfo.options[fInfo.selectedIndex].value }

 

<FORM NAME="demo"><SELECT NAME="menu" onChange="loadPage(this)"> <OPTION VALUE="lesson11.htm">Lesson 11 <OPTION VALUE="lesson12.htm">Lesson 12 <OPTION SELECTED VALUE="lesson13.htm">Lesson 13 <OPTION VALUE="lesson14.htm">Lesson 14</SELECT></FORM>

The only change in the form is the loadPage() function now contains a parameter and the parameter is the JavaScript keyword this. The this keyword allows all of the information about the SELECT object to be passed to the function. For instance, in the function, fInfo.selectedIndex is the same as document.demo.menu.selectedIndex. Everything that we did in our original version of the loadPage() function is now written on one line. If you study it close, I think you will see that both versions will have the same results.

Page 11: Parsing Simple XML Document

JAVASCRIPT: Accessing the form elements

The form validation script needs to access the form in the HTML page to determine what values the user has filled in. So first we have to enter the form by means of the Level 0 DOM. The general syntax for accessing a form element is:

document.forms[number].elements[number]

When the page is loaded, JavaScript makes an array forms in which it puts all the forms that are on the page. The first form is forms[0], the second is forms[1] etc.

Each form has another array in which JavaScript puts all the elements in the form. The first elements is elements[0], the second elements[1] etc. Every <input>, <select> and <textarea> is an element.

In some cases, it's better to use the names of the forms and elements. In HTML, you have to give a name to each form and each element, like:

<form name="personal" action="something.pl" onsubmit="return checkscript()"><input type=text size=20 name=name><input type=text size=20 name=address><input type=text size=20 name=city></form>

Now you can access these elements by:

document.personal.namedocument.personal.addressdocument.personal.city

The advantage of using names is that you can put all elements somewhere else in the page and still have a working script, while a script using numbers will have to be changed. After all, the input box city is document.forms[0].elements[2] in the example above, but when you suddenly put it at the top of the form, it becomes document.forms[0].elements[0] and you have to change the script.

When you start writing your own scripts using the code snippets below, it is always very important to know exactly how your form is built. To help you, I wrote a form printing script that prints out the form structure for you.

Determining values

Of course, the most important thing is to find out what the user has filled in or checked in the form. At other times you might want to fill in something in the form.

Below are snippets of scripts that help you access form elements. All of them are meant to send the user input to the variable user_input. After you've done that, you can check this value for whatever you want.

Texts, textareas and hidden fields

Very simple:

user_input = document.forms[0].text.value

Page 12: Parsing Simple XML Document

where text is the name of the text field, textarea or hidden field. The value of this element gives the text, so we transfer it to user_input.

Writing is also possible:

document.forms[0].text.value = 'The new value';

Select boxes

Select boxes look very scary, but are actually simple too:

var selectBox = document.forms[0].select;user_input = selectBox.options[selectBox.selectedIndex].value

where select is the name of the select box. First, we need to find out which option the user has selected. document.forms[0].select.selectedIndex gives us the number of the selected option. JavaScript has created an array options which contains all options of the select box. So we ask for the selected option in this array and take the value of it, which we transfer to user_input.

To change the selected option in a select box, you have to change its selectedIndex, like

document.forms[0].select.selectedIndex = 2;

Now the third option in the box is selected.

Checkboxes

Checkboxes need a slightly different approach. We already know their values, but want to know whether the user has checked them. The checked property tells us. It can have two values: true or false.

Now we do:

if (document.forms[0].checkbox.checked){

user_input = document.forms[0].checkbox.name}

in which checkbox is the name of the checkbox. If the checkbox is checked, we take its name (or its value) and transfer it to user_input.

To check a checkbox, set its property checked to true:

document.forms[0].checkbox.checked = true

Radio buttons

Unfortunately it's not possible to see at once which radio button in a group the user has checked. You need to go through all radio's and see which one's checked property is true.

for (i=0;i<document.forms[0].radios.length;i++){

if (document.forms[0].radios[i].checked){

Page 13: Parsing Simple XML Document

user_input = document.forms[0].radios[i].value;}

}

where radios is the name of the group of radio buttons.

Note that document.forms[0].radios is an array filled with all radio buttons. Loop through all of them and see if it is checked. If one is, transfer the value of that radio button to user_input.

document.forms[0].radios.length gives the number of radio buttons. For each radio button, we see if it is

To check a radio button, set its property checked to true:

document.forms[0].radios[i].checked = true;

Page 14: Parsing Simple XML Document

CONCISE JAVASCRIPT:

Data Types and Values

Primitive data type: number, string, boolean value. Composite data type: array, object;

In Javascript, all numbers are floating-point values; The Math object stores all complex math functions [eg, Math.sin(x)].

Otherwise, use +, -, *, and / as usual; toString(x) converts a number to a string. x is the radix; eg,

hexadecimal = x = 16; numbers larger or smaller than the max allowable = Infinity or -

Infinity. Undefined results (eg, 0/0) result in NaN. Nothing equals NaN, including itself [so you must detect it with isNan()];

The backslash, when placed before another character, represents a character that is not otherwise representable within a string (eg, ' can then be used as a literal apostrophe). Other special chars include: \b (backspace), \f (form feed), \n (newline), \r (carriage return), \t (tab), \" (double quote), \\ (backslash);

Concatenate strings with the + operator; Access the length of a string with varname.length; Access a specific character in a string with

varname.charAt(position); Extract part of a string with varname.substring(position1,position2).

Note - strings are indexed starting with zero; Find the position of a letter in a string with

varname.indexOf(position); The two legal boolean values are string literals true and false; To define a function:

function varname(arg) {    return code_block;}

Functions can be stored in variables, arrays, and objects, and can be passed as arguments to other functions;

A function literal looks exactly like a function, minus the function name (eg, var varname = function(arg) { return code_block; } . Functions defined this way are called "lambda" functions;

Create an object with:  varname = new function(); Create an array with: varname = new Array();  followed by: 

varname[0] = value1;  varname[1] = value2; etc... or  varname = new Array (value1, value2,...);

The keyword null indicates that a variable does not contain a valid data type;

The keyword undefined indicates that a variable has no value or does not exist. This is different from null, but they are generally considered equal;

To use the Date object: varname = new Date(year, month, day);

Variables

Declare variables with: var varname = varvalue. Combine variable declaration by putting commas between varname = varvalue statements. If you drop the var keyword, a variable is automatically declared as a global variable;

Primitive data types have a fixed size in memory. This means that if you put a primitive data type into variable x, then put x into y, y will keep that initial value even if you later change x. Composite

Page 15: Parsing Simple XML Document

data types work through references, so it doesn't work that way for them;

Variables in Javascript are fundamentally the same as object properties;

The keyword this can be used to refer to the global object (as well as window);

Expressions and Operators

An expression is a phrase of Javascript that can be evaluated to produce a value. The simplest expression is a literal. More complex expressions involve operators;

A unary operator converts one expression to another. A binary operator combines two expressions. A ternary (condition) operator brings three expressions together in an if/then sort of way;

Table of operators (* = Javascript 1.2   ** = only IE):

Operator Operand Type Operation Performed

++ number pre-or-post increment (unary)

-- number pre-or-post decrement (unary)

- number negation

! boolean invert value

delete* variable undefine a property (unary)

new constructor call create new object (unary)

typeof any return data type (as a string)

void any return value undefined (unary)

== any test for equality

!= any test for inequality

===** any test for identity

!==** any test for non-identity

& integers AND

^ integers XOR

| integers OR

&& booleans logical AND

|| booleans logical OR

?: boolean, any, any conditional (ternary) operator

% numbers modulo (returns remainder)

, any multiple evaluation Javascript will attempt to make an operator work (even when it

shouldn't) by converting expressions to different types (eg, "3" *

Page 16: Parsing Simple XML Document

"5" will evaluate to the number 15). "1" = true would result in true, even though 1 is in quotes;

When ++ or -- are used as post-increment operators, they increment the operand, but evaluate to the un-incremented value (eg, if i = 1, j = i++, then i = 2 and j = 1);

When using ==, note that (in the case of arrays and objects) two variables are equal only if they refer to the same object or array. In other words, two different arrays containing the same elements would come up unequal;

== resolves null and undefined as equal; When using <, <=, >, and >=, note that all capital letters come

before lowercase letters, so that "Zoo" < "ant" evaluates to true; && operates by checking if the left-hand operand is false. If so, it

returns the evaluation of the left-hand operand. If not, it returns the evaluation of the right-hand operand;

|| operates by checking if the left-hand operand is true. If so, it returns the evaluation of the left-hand operand. If not, it returns the evaluation of the right-hand operand;

+= adds the right-hand operand to the left-hand operand, then assigns the new value to the left-hand operand (eg, total += sales_tax is equivalent to: total = total + sales_tax);

Use the conditional operator (?:) as follows: expression1 ? expression2 : expression3 (or, if exp1 then exp2 else exp3);

The delete operator is used to destroy an object property or array element (eg, delete my.birthday);

The void operator is used to create an undefined value, since there is no undefined keyword (eg, void 0);

Statements

if/then/else works as follows: if (expression) {code_block} else {code_block2}. You can also use else if as many times as necessary;

the Javascript switch statement works like the ASP select statement:switch (expression) {    case (value):        code_block        break;   (note - this is optional; it causes the switch loop to end if this value matches the

expression)

    default:   (note - this is optional; it is executed if no case value matches the expression)

        code_block2}

Note - Javascript does *not* allow user-defined variables to be used in case labels;

Loops work as follows: while (expression) {statement}. You can also use do/while;

The for statement works as follows: for(initialize ; test ; increment) {statement}. Eg, for(count = 0 ; count < 10 ; count++). You can also use: for (varname in object) {statement};

Any statement may be labeled by preceding it with an identifier name and a colon:  labelname: statement. This label can then be used to access the statement from anywhere in a script;

The break statement ends a loop, while the continue statementcauses a loop to restart in a new iteration;

The with statement makes it possible to add an object to the top of the scope chain, thus saving type time:  with(object) {statements}. Eg, with(frames[1].document.forms[0]) {name.value = ""; address.value = ""}; etc}. You can also save time by simply storing object into a variable;

Page 17: Parsing Simple XML Document

The <layer> tag in HTML, when placed around a script, causes it to run in its own context with its own global object;

export varname or export funcname makes its target available in other execution contexts (eg, another window). The import statement copies the value of an export target from its source into the new context;

Functions

Define a function with: function funcname(arg1, arg2, ...) {statements}, or with the new operator as follows: varname = new function("arg1", "arg2", "statements");

The return statement ends execution of a function, and returns a value;

If a function does not contain a return statement, it simply executes each statement in the function body and returns the undefined value to the caller - it cannot meaninfully be used as part of a larger expression;

Functions can be stored in a variable, then called with that variable (basically, you give the function a second name);

A Javascript function is defined with a fixed number of arguments, but can be passed any number when invoked. These argument values can be accessed/assessed through the arguments[] array (for example, you could count through all arguments and return the largest). The arguments object also has a callee property that refers to the function being executed. You can use it to recursively invoke an unnamed function;

The arity property of a function returns the number of arguments a function expects to receive. Use the length property with the arguments array if you want the actual arguments passed (note - arguments is only available within the function body). Arity only functions correctly in Naviagor 4 if the language attribute of the script is set to "JavaScript 1.2";

The apply method of the function object allows you to invoke a function as if it were a method of some other object. Its first argument is the object on which the function should be invoked - that object becomes the value of the this keyword within the function. Its second argument is an optional array of arguments to be passed to the function (eg, f.apply(o, [1,2]). In Navigator 5, call serves the same purpose (but the arguments aren't put in []);

Objects

The delete operator is used to entirely remove a property from an object;

To create an object with changeable properties and methods:1) create a constructor function2) prefix all variables in the function with the this keyword3) instantiate the object with that function (eg, var obj_instance = new func_name(args...) ). Note that func_name is effectively the object name;

Every object has a prototype, from which it inherits properties. These properties can be inherited even if they are added to the prototype after the object is created. Inheritance occurs only when reading property values, not writing them. If you set property p in object o as something, you create a new property directly in o;

Define the property of a prototype as follows: func_name.prototype.prop_name = value;

Page 18: Parsing Simple XML Document

In Navigator 3, the prototype object is not created until the constructor function is used for the first time, so instantiate a dummy object before assigning values to the prototype (eg, new func_name(); );

A class defines the structure of an object. There may be multiple objects (ie instances) of the same class;

Built-in classes have prototypes (just as user-defined classes do), and you can assign values to them. This does not work in IE3;

The constructor property of an object simply refers to the function that was used to instantiate the object. For any function f, f.prototype.constructor is always equal to f;

The toString method returns a string that somehow represents the type and/or value of the object it is invoked on. You can define custom toString methods for a prototype, if you like;

The valueOf method returns a number, boolean, or function that somehow represents the value of the object referred to;

Javascript in Web Browsers

The Document object represents an HTML document, and the Window object represents the window (or frame) that displays the document. The Window object is the global object - you can refer to it with window or self;

An example of the object chain in Javascript (see pg 210): parent.frames[0].document.forms[0].elements[3].options[2].text;

How Javascript can be embedded into HTML:o Between a pair of <script> tags;o From an external file specified by the SRC or ARCHIVE

attributes of a <script> tag (the external file should be a .js file, and should not contain <script> tags or HTML in general). .js files are cached by a browser, so if a script is used on multiple pages, this technique is nice;

o In an event handler (eg, onClick);o As the body of a URL that uses the special javascript:

protocol. Use this where any HTML tag is expecting a URL (eg, a form tag, hyperlink, etc);

o In a style sheet, between <style type="text/javascript"> tags (not supported by IE);

o In a Javascript entity, as the value of an HTML attribute. Use: &{statement}; This is effectively conditional HTML;

o In a conditional comment that comments out HTML text unless a given Javascript expression evaluates to true (not supported by IE 4);

<script> tags may appear in the <body> or <head> of an HTML document, and all <script> tags in a document are part of the same Javascript program (meaning variables in one are accessible to another);

Use <script language="Javascript">, even though Javascript is usually the default script language of browsers;

For scripts that write a new script into another window or frame, you will have to document.write the closing tag as <\/script> - otherwise, it won't work;

A script cannot manipulate an object that hasn't been created yet (sequentially speaking) in a document;

An HTML document cannot be fully displayed until all scripts it contains have finished executing. If possible, put long computations in a function, and call that function from an event handler. If the computation will take a while, let the user know beforehand. Note - you *can* define functions that manipulate objects that haven't been created yet;

Page 19: Parsing Simple XML Document

The onLoad and onUnload event handlers are defined in the <body> or <frameset> tag of a document. onLoad is executed when a document fully loads, onUnload executes just before the page is unloaded (when the browser is told to move on to a new page);

If you set a flag within the onLoad event handler (eg, window.loaded = true;), other event handlers can test this flag to see if they can safely run;

The Window object is valid as long as the top-level window is open (even if you leave the page that opened it);

All user-defined properties are erased whenever a web page is unloaded;

Scripts and their variables do not persist across web pages;

Windows and Frames

The alert() method dispays a message to the user; The confirm() method asks the user to click an OK or Cancel button to

confirm an operation. First, place a string in a variable, then call that variable with confirm (resulting in a boolean value);

The prompt() method asks a user to enter a string. The first argument is a message to be displayed to the user, the second argument will appear within the entry field (use "" for no default). Store the method in a variable, which you can then call later in the script to retrieve the user's input;

The status line at the bottom of the browser can be controlled with: event_handler="status='string'; return true;" ... the return statement is used to make the browser abandon its default action for the event;

defaultStatus permanently sets the status line to a certain string value;

The setTimeout() method schedules a piece of Javascript to be run at some time in the future. It has two arguments, a function to be called (which is placed in quotes) and a time (in milliseconds). clearTimeout() can be used to cancel the execution of that function;

setInterval() and clearInterval() are like the timeout methods, except they automatically reschedule the code to run repeatedly;

Window.navigator refers to the Navigator object, which has six properties that describe the user's browser/platform (see pg 237). Its javaEnabled() method returns true if the browser supports Java. Its plugins[] property is an array that contains ever plugin the broswer has installed (test through strings?);

The screen property/object provides information about the size of the user's display and the number of colors available (through its availWidth, availHeight, and colorDepth properties). 256 colors would return a value of 8 (8-bit);

The open() method is used to open a new window. Its first argument is the URL of the document to display in the new window (use null for empty). Its second argument is the name of the window. Its third (optional) argument contains a comma-delimited list of features, including: width,height,status,resizable. The fourth argument is a boolean value used if the second argument names an already-existing window: true tells the browser to replace the current entry in the window's browsing history, false (the default) creates a new entry;

The close() method closes a window. The closed property is true if the window in question has been closed;

In Javascript 1.2, the moveTo() method moves the upper-left corner of the window to the specified coordinates. moveBy() moves the window a specified number of pixels left or right and up or down. resizeTo() and resizeBy() resize the window by an absolute or relative amount;

Page 20: Parsing Simple XML Document

The focus() method brings keyboard focus to the window, while blur() relinquishes keyboard focus;

scrollBy() scrolls the document by a specified number of pixels horizontally and vertically. scrollTo() specifies an absolute position;

The location property refers to the URL of the document in the window; the href property of location contains the complete text of the URL. Other properties of location include: protocol, host, pathname, and search (which contains any portion of a URL following [and including] a question mark). Assigning a URL to the location object causes that URL to be loaded by the browser. Methods of the location object include reload(), which reloads the page, and replace(), which loads and displays a different URL (also replacing the former URL's entry in the history list, preventing a user from going back to the old page);

The History object is an array of URLs in the browsing history of the window. Its back() and forward() methods perform their namesake;

Note - functions are executed within the scope in which they were defined, *not* the scope in which they are invoked;

The Document Object Model

The DOM can be used to refer to HTML elements by name or position. For example, a form named "f1" can be accessed with: document.forms[index#] or document.f1;

The properties of the Document object are:

Property Description

alinkColor color of a link while it is activated (ALINK attribute of the <body> tag)

anchors[] array of anchor objects that represent the anchors in the document

applets[] array of applet objects

bgColor background color of the document (BGCOLOR attribute of the <body> tag)

cookie enables JavaScript to read/write cookies

domain allows mutually trusted web servers within the same internet domain to collaborate

embeds[] array of embedded objects (eg, plugins or ActiveX controls)

fgColor default text color of the document (TEXT attribute of the <body> tag)

images[] array of image objects

lastModified string containing the modification date of the document

linkColor color of unvisited links (LINK attribute of the <body> tag)

links[] array of link objects

referrer URL of the document that referred user to the current document

title text within the <title> tag

URL string specifying the URL from which the document was loaded

vlinkColor color of visited links (VLINK attribute of the <body>

Page 21: Parsing Simple XML Document

tag) Set all color properties of the document object in the <head> of the

document; The write() method:

o can take more than one argument (the equivalent of concatenation)

o if called from an event handler, will overwrite the current document;

o to create a new document, open() it, write() any number of times, then close() the document;

To dynamically create a non-html document, call open() with a single argument (the MIME type desired);

The elements[] property of the Form object contains all the input elements of a form. You can set those elements' default values and read user input with this property;

The Image object:o src property - can be set to make the browser load and display

a new image in the same space. In such a case, you will first want to cache the replacement image off-screen. You can do so by instantiating an Image object and its corresponding image[].src with each loop. When it is time to perform the image replacement, simply set the src property of the desired on-screen image to the URL of the of the desired image;

o onLoad event handler - invoked when the image is fully loaded; o onError event handler - invoked when an error occurs during the

image loading process; o onAbort event handler - invoked when the user cancels the image

load; o complete property - is false while the image is loading; o  

The Link object represents the URL of the hypertext link and contains all the same properties as the Location object;

Chapter 15 - Events and Event Handling

Event Handler

Trigger Object(s) supported by

onAbort loading interrupted Image

onBlur element loses input focus all elements, Window

onChangeuser selects or deselects an item, or enters text and moves input focus to another element

Select, text input elements

onClickuser clicks once. Return false to cancel default action (eg, follow link, submit...)

Link, button elements

onError error occurs while loading image

Image

onFocus element given input focus all elements, Window

onKeyDown* key pressed by user. Return false to cancel

Document*, Image*, Link*, text elements

onKeyUp* key released by user. Return false to cancel

Document*, Image*, Link*, text elements

onLoad document or image finishes loading

Window, Image

onMouseDown* user presses mouse button Document, Image, Link, button

Page 22: Parsing Simple XML Document

elements*

onMouseOut mouse moves off element Link, Image*, Layer*

onMouseOver

mouse moves over element. For links, return true to prevent URL from appearing in status bar

Link, Image*, Layer*

onMouseUp user releases mouse button. Return false to cancel

Document, Link, Image, button elements*

onReset form reset requested. Return false to prevent

Form

onResize window is resized Window

onSubmit Form submission requested. Return false to prevent

Form

onUnload Document is unloaded Window Event handlers are expressed as the values of HTML attributes. In

this context, they are case-insensitive. The value of an event handler is an arbitrary string of Javascript. Multiple statements must ne separated from each other by semicolons. When an event handler requires multiple statements, however, it is usually cleaner to define them in the body of a function, then call that function through the event handler;

Javascript event handlers (as opposed to those expressed as the values of HTML attributes) must be expressed completely in lowercase;

Javascript code can be used to invoke an event handler directly. It will not cause the HTML to execute (ie, an onClick on an hypertext link will not suddenly load the linked document);

Functions always execute in the scope in which they were defined, so keep this in mind when using an event handler to call a function that was defined in some other window, etc...;

Netscape and IE both define an Event object, but the properties of the object are named very differently. This object can be used to to reference the event type, event source, mouse button used, mouse position, key, and modifier key. For more information, see pg 292;

Dynamic HTML

DHTML is a loosely defined term comprising several technologies: the Document Object Model (DOM), the extended event model, cascading style sheets (CSS), and absolute positioning of HTML elements;

CSS styles are specified as a semicolon-separated list of name/value attribute pairs, with each name/value separated by colons. The list is associated with an HTML attribute, or with a class or ID name. In the later case, the style then applies to any HTML element with a CLASS attribute set to that name, or to a unique HTML element with its ID attribute set to that name. Style sheets are imported into an HTML document with the <link> tag;

In Navigator, CSS can be referred to through Javascript with the tags, classes, and ids properties of the Document object;

In IE, CSS can be referred to through the styleSheets[] array of the Document object. Each element of this array is a StyleSheet object, and contains a rules[] array (which allows you to access each rule) and an addRule() method (which allows you to create new rules). In IE (unlike Netscape) you can access inline styles by setting the style property of an HTML element within a document;

CSS-P allows absolute positioning of HTML elements simply by defining a few more CSS properties that can be set, including (most

Page 23: Parsing Simple XML Document

importantly) the position property, which can be set to absolute (or relative). First, you set the position property for an element. Next, you set the left and top properties (a number, followed by "px" or "in"), and optionally, the visibility and z-index (zOrder in IE) properties (the latter specifies the stacking order of elements). CSS-P works best with inline styles, usually as an attribute to an HTML grouping tag such as <span>, <div>, or any other element that has an opening and closing tag (since Netscape 4 can't apply it to tags that don't have a closer). Note - the span tag is much like div, except that it doesn't force a line break;

To dynamically position elements in IE, simply change the value of a position property (eg, left, visibility, etc) through the style object (eg, document.all.p23.style.left = "2.24in";);

To dynamically position elements in Netscape, place the elements in a <layer>, then position that layer with the position properties (after having first set the elements' position style set to absolute). The layer can be referred to through the layers[] array, or through the ID assigned to a layer (eg, document.L2 or document.layers[1]). The Layer object has a document property of its own, through which its elements are accessed (eg, document.L2.document...). The moveBy() and moveTo() methods can be used to move a layer. The visibility property is set to either "show" or "hide" (unlike in IE)

Page 24: Parsing Simple XML Document

Applying CSS to forms

(http://www.webcredible.co.uk/user-friendly-resources/css/css-navigation-menu.shtml)

Forms are an essential part of interaction on the Internet but they can look rather drab. With CSS we can position form items so they all line up nicely and add a bit of colour to jazz them up.

The original form

Name

E-mail

That form looks horrible! Here's the code behind it:

<form action="destination.htm"><label for="name">Name</label> <input type="text" id="name" /><br /><label for="e-mail">E-mail</label> <input type="text" id="e-mail" /><br /><input type="submit" value="submit" /></form>

Positioning the form with CSS

The first thing we need to do to the form is make it line up nicely. In the old days this could only be achieved with tables - not anymore, courtesy of our old friend, CSS. First, we'll assign a class to each form item:

<form action="destination.htm"><label for="name">Name</label> <input type="text" id="name" class="input-box" /><br /><label for="e-mail">E-mail</label> <input type="text" id="e-mail" class="input-box" /><br /><input type="submit" value="submit" class="submit-button" /></form>

The two input boxes have been assigned the class, input-box, and the submit button, submit-button - hmm... how did we think up those names?

Now they've got their classes we'll need to assign some rules to them:

label{width: 4em;float: left;text-align: right;margin: 0 1em 10px 0;clear: both}

Page 25: Parsing Simple XML Document

.input-box{margin-bottom: 10px}

.submit-button{margin-left: 5em;clear: both}

Right, let's go through that CSS bit-by-bit. We gave the label a fixed width of 4em, although this should obviously be increased if the prompt text in the form is anything longer than what we've got now (‘name’ and ‘e-mail’). We also specified the width in terms of em and not px so that if users increase the text size the width will increase with the larger letters.

The margin: 0 1em 10px 0 CSS command means the labels will have a margin above them of 0, to the right of 1em (so that the text isn't up against the input box), a bottom margin of 10px (to create some space between each line) and a left margin of zero. The clear:both CSS command is necessary to ensure the text (‘name’ and ‘e-mail’) starts on a new line.

The submit button has a left margin of 5em so that it aligns with the input boxes, which are 5em from the left. This includes the 4em width and the 1em right margin of the prompt text.

So, putting that altogether gives us this form:

Name

E-mail

Looks much better, but it's still rather plain. Let's use some more CSS to jazz up the form so it's more inline with the colour scheme on the page.

Applying colours to the form

The three CSS commands we'll use to make those forms look good are border, background and color (you can also use any other CSS command, such as font, text size, bold etc.).

So, let's say we want the input boxes in this form to have a dark blue text colour and border and a pale orange background, and the submit button to have black text, an orange background and a dark blue border. In addition to the above CSS, we would add in the following commands:

.input-box{color: #26a;background: #feb;border: #26a solid 1px}

Page 26: Parsing Simple XML Document

.submit-button{color: #000;background: #fb0;border: 2px #9cf outset}

(#26a is an abbreviation of #2266aa - you can apply this shorthand version with any colour value with repetitive numbers like this.)

We use ‘outset’ for the button's border so that it looks like a button. If we used ‘solid’ it would look flat. Here's how the form comes together:

One word of warning, be careful about using a light text colour for text with input boxes. More and more Internet users are using the Google Toolbar which fills in online forms for you. Whenever a form appears it automatically turns the background colour of input boxes to yellow - if you've specified white text it would be virtually impossible for your site visitors with this toolbar installed to see what they're writing when completing the form.

Formatting the whole form

We may want to give this form its own title and border. To do this we add the <fieldset> and <legend> commands to the HTML code:

<fieldset><legend>This is my form</legend><form action="destination.htm"><label for="name">Name</label> <input type="text" id="name" class="input-box" /><br /><label for="e-mail">E-mail</label> <input type="text" id="e-mail" class="input-box" /><br /><input type="submit" value="submit" class="submit-button" /></form></fieldset>

We'll apply some CSS commands to the fieldset and legend to give the form a blue border and a title with an orange background:

fieldset{border: #26a solid 1px;width: 20em}

legend{

Page 27: Parsing Simple XML Document

background: #fb0;border: #26a solid 1px;padding: 1px 10px}

Here's the CSS we used to make this, all in one place:

label{width: 4em;float: left;text-align: right;margin: 0 1em 10px 0;clear: both}

.input-box{float: left;margin-bottom: 10px;color: #26a;background: #feb;border: #26a solid 1px}

.submit-button{margin-left: 5em;clear: both;color: #000;background: #fb0;border: 2px #9cf outset}

fieldset{border: #26a solid 1px;width: 20em}

legend{background: #fb0;border: #26a solid 1px;padding: 1px 10px}