Приглашаем посетить
Бальмонт (balmont.lit-info.ru)

11.4 Working with the DOM Core interfaces

Table of Contents

Previous Next

11.4 Working with the DOM Core interfaces

11.4.1 The node interface

The node interface is the skeleton and primary data structure of the entire DOM Core. Beginning with just a single node, the whole document tree is clearly represented. For example, the firstChild, lastChild, nodeName, and childNodes objects are defined in the node interface. In fact, the node interface also contains a number of primary methods or functions such as insert, remove, replace, and append for you to manipulate a document tree.

The node interface is a big interface and if you ignore the declarations of the "NodeType," "TreePosition," and some other functions not frequently used, you will get a simplified version of the interface as listed in ex11-06.txt.



Listing: ex11-06.txt - DOM Core: Document Interface  Node

 1: interface Node {
 2:
 3:   readonly attribute DOMString        nodeName;
 4:            attribute DOMString        nodeValue;
 5:   readonly attribute Node             parentNode;
 6:   readonly attribute NodeList         childNodes;
 7:   readonly attribute Node             firstChild;
 8:   readonly attribute Node             lastChild;
 9:   readonly attribute Node             previousSibling;
10:   readonly attribute Node             nextSibling;
11:   readonly attribute NamedNodeMap     attributes;
12:
13:   // Modified in DOM Level 3:
14:   Node               insertBefore(in Node newChild,
15:                                   in Node refChild);
16:   // Modified in DOM Level 3:
17:   Node               replaceChild(in Node newChild,
18:                                   in Node oldChild);
19:   // Modified in DOM Level 3:
20:   Node               removeChild(in Node oldChild);
21:   Node               appendChild(in Node newChild);
22:   boolean            hasChildNodes();
23: };

Instead of providing definitions for every property and function of the interface, we would like to explain and show you how to use them by example. Consider the following page fragment:



Listing: ex11-07.txt - Page Fragment Of Example ex11-07.htm (Part One)

 1:  <body id="body" style="background:#000088;font-family:arial;
 2:    font-size:22pt;color:#ffff00;font-weight:bold;text-align:center">
 3:  DOM Core  Node Interface<br /><br />
 4:
 5:  <br />
 6:  <div style="color:#ffffff" id="id01">This is paragraph one</div>
 7:  <div style="color:#ffff00">This is paragraph two</div>
 8:  <div style="color:#ff0000">This is paragraph three</div><br /><br />
 9:  <div id="outMsg" style="font-size:14pt"></div>
10: </body>

The nodeName and nodeValue represent the name and the value of the node. They are strings and can be displayed easily on the screen. Since the node is an object, you may need these two and possibly other properties to view the information of the node. For example, the following script statements return the element name and text of the division in line 6:

childV = document.getElementById("id01")

  

childV.nodeName

returns the name "DIV"

childV.firstChild.nodeValue

returns the string "This is paragraph one"


The parentNode object returns the parent of this node. Most nodes have a parent. However, if a node has just been created and not yet added to the tree, or if it has been removed from the tree, this is "null." For example, the parent of childV is <body>:

childV.parentNode.nodeName

returns the name "BODY"


The childNodes object is a collection of type NodeList and contains all children of the node concerned. If the node contains no children, NodeList has no nodes, i.e., "null."

The firstChild and lastChild objects represent the first child and the last child of the node respectively. Again, if there is no such node, "null" is returned. Example ex11-06.htm shows the behavior of these properties.

The previousSibling object is the node immediately preceding this node and nextSibling is the node immediately following the current node. If there is no such node, "null" is returned. For example,

childV.previousSibling.nodeName

returns the name "BR"

childV.nextSibling.nodeName

returns the name "DIV"


To show all these in action, we consider the remaining part of the example ex11-07.htm.



Listing: Continuation Of The Example ex11-07.htm (Part Two)

11: <script>
12:    llSt = 'childV = document.getElementById("id01") <br />'
13:    childV = document.getElementById("id01")
14:    llSt = llSt +"childV.nodeName= "+childV.nodeName +'<br />'
15:    llSt = llSt +"childV.firstChild.nodeValue= "+
16:           childV.firstChild.nodeValue +'<br />'
17:    llSt = llSt +"childV.parentNode.nodeName= "+
18:           childV.parentNode.nodeName +'<br />'
19:    llSt = llSt +"childV.nextSibling.nodeName= "+
20:           childV.nextSibling.nodeName +'<br />'
21:    llSt = llSt +"childV.previousSibling.nodeName= "+
22:           childV.previousSibling.nodeName +'<br />'
23:
24:  document.getElementById("outMsg").innerHTML = llSt
25: </script>
26: </html>

This page fragment is a script block illustrating the applications of noName, nodeValue, parentNode, nextSibling, and previousSibling. All these properties have a reference point defined in line 13, i.e., the division with an id="id01". A screen shot of this example is shown in Fig. 11.12.

Figure 11.12. ex11-07.htm

graphics/11fig12.jpg


The ability to define attributes inside the node interface is a powerful feature. It provides a method to gain access and to control all attributes (if any) of an element. At the time of writing, not many browsers (including IE5.5) have managed to implement it completely. Attributes of the node interface can be considered as a collection of attributes of a node. For example, the following statements provide a complete listing of the attribute on childV:



for (jj=0;jj< childV.attributes.length;jj++)
{
 childV.attributes.item(jj).nodeName
 childV.attributes.item(jj).nodeValue
}

If your browser has a proper implementation of the node interface, you should have the results



childV.attributes.item(0).nodeName = style
childV.attributes.item(0).nodeValue = color: rgb(255,255,255);
childV.attributes.item(1).nodeName = id
childV.attributes.item(1).nodeValue = id01

They represent the attribute settings of the division element given in line 6 of ex11-07.txt, i.e.



<div style="color:#ffffff" id="id01">This is paragraph one</div>

The node interface also provides a useful set of functions or methods for you to add, delete, and modify the existing DOM tree representation of a document. In order words, you can modify the structure of a document at run time by using the node functions insertBefore(), removeChild(), and appendChild() to insert, remove, and append page elements.

To add or insert a new element to the structure of a document, you need to know how to generate or to create a new element at run time. For this purpose, some knowledge of the document interface of the DOM Core is necessary.

11.4.2 The document interface of the DOM Core

Another interface we need to continue the discussion on the DOM Core is the document interface. This interface represents the entire HTML or XML document. It is the root of the document tree, and provides primary access to the document's data. The document interface also contains a number of methods to create objects or page elements at run time.

It is outside the scope of this book to give every detailed definition and explanation of the properties and functions inside the document interface. We concentrate only on the functions that are needed in our applications. A simplified version of the document is listed in ex11-08.txt.



Listing: ex11-08.txt - DOM Core: Document Interface  Document

1:
2: interface Document : Node {
3:   // Modified in DOM Level 3:
4:   readonly attribute DocumentType      doctype;
5:   readonly attribute Element           documentElement;
6:
7:   Element            createElement(in DOMString tagName)
8:
9:   Text               createTextNode(in DOMString data);
10:  Comment            createComment(in DOMString data);
11:
12:  NodeList           getElementsByTagName(in DOMString tagname);
13:
14:  // Introduced in DOM Level 2:
15:  Element            getElementById(in DOMString elementId);
16:
17: };

The doctype attribute in line 4 returns the DTD associated with this document. A document without one will return "null."

The documentElement attribute allows direct access to the child node, i.e., the root element of the document. For HTML/XHTML documents, it represents the element <html>, i.e.,

document.documentElement returns the node of the <html> element

Another frequently used shortcut to the child node is

document.body returns the node of the <body> element

The first important function of this interface is createElement(). This function is often used to create an element of the type specified. For example, the statement



document.createElement("div")

creates an element pair "<div></div>". Almost any XHTML element and node can be generated this way at run time. If you want to add some text to the newly created division element <div>, the function createTextNode() is needed. This function converts a text string into a node type. For example, a typical application of this function is



newdiv = document.createElement("div")
newText = createTextNode("This is a new text node")
newdiv.appendChild(newText)

After generating two new nodes from the functions of the document interface, the appendChild() function from the node interface is used to append the two nodes together. The resulting statement is



<div>This is a new text node</div>

This is a powerful structure and enables us to create element and insert and delete them anywhere on the DOM tree at run time.

The function createComment() generates a comment node with the specified string. The remaining functions getElementsByName() and getElementById() are frequently mentioned and used in the last and current chapters.

11.4.3 Inserting and deleting page elements at run time

The DOM Core provides an opportunity to modify page structure in real time. Some of these functions are listed as follows:



Node insertBefore(in Node newChild, in Node refChild)
Node removeChild(in Node oldChild)
Node appendChild(in Node newChild)

The first function allows you to insert a node (whether new or old) before a node inside the DOM tree. A typical procedure to use the insertBefore() function is



newDiv = document.createElement("div")
newText = createTextNode("This is a new text node")
newDiv.appendChild(newText)
myRefNode = document.getElementById("id01")
document.body.insertBefore(newDiv,myRefNode)

The first three lines together create the node "<div>This is a new text node</div>". The fourth line gets the node that you want to insert just before that. The final line can be interpreted as: insert the newDiv node before the node myRefNode inside the body node collection.

The removeChild() function is easier to use. For example, the following statement removes the node with id="id01" from the body collection of the DOM tree:



idObj = document.getElementById("id01")
document.body.removeChild(idObj)

The node itself, and all subsequent subnodes if any, will be removed from the tree at the same time.

Consider the following example:



Example: ex11-08.htm - Insert And Delete Elements At Run Time (Part One)

 1:  <?xml version="1.0" encoding="iso-8859-1"?>
 2:  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 3:      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 4:  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 5:  <head><title>Insert and Delete at Run Time -- ex1108.htm</title></head>
 6:  <style>
 7:   .butSt{background-color:#dddddd;font-family:arial;font-weight:bold;
 8:      font-size:14pt;color:#880000;width:150px;height:35px}
 9:  </style>
10:  <body style="background:#000088;font-family:arial;font-size:22pt;
11:     color:#ffff00;font-weight:bold;text-align:center">
12:   Inserting and Deleting Elements <br />At Run Time<br /><br />
13:
14:  <div id="id01" style="color:#ffffff">This is paragraph one</div>
15:  <div style="color:#ffff00">This is paragraph two</div>
16:  <div style="color:#ff0000">This is paragraph three</div>
17:  <div style="color:#00ff00">This is paragraph four</div>
18:  <img src="picUp.gif" alt="pic" width="100" height="100" />
19:  <img src="picRight.gif" alt="pic" width="100" height="100" />
20:  <img src="picDown.gif" alt="pic" width="100" height="100" />
21:  <img src="picLeft.gif" alt="pic" width="100" height="100" />
22:     <br /><br />
23:
24:  <input type="button" onclick="myDelApp(1)" class="butSt"
25:     value="Remove div" />
26:  <input type="button" onclick="myDelApp(2)" class="butSt"
27:     value="Remove Img" /><br />
28:  <input type="button" onclick="myAddApp(1)" class="butSt"
29:     value="Append div" />
30:  <input type="text" id="txId" class="butSt" style="width:350px;
31:     color:#008800" value="Enter Text Here"/>
32:  <br /><br /><span id="outMsg"></span>
33:

This code fragment is the first part of the example ex11-08.htm containing the interface part. For demonstration purposes, this page contains four division elements and four images. The divisions are defined in lines 1417 and the images are in lines 1821. You also have two buttons soon after the images. When the Remove div button is clicked (lines 2425), the function myDelApp(1) is called to delete the first item of the divisions. The argument 1 in the myDelApp() function indicates that we want to delete the <div> element. On the other hand, if myDelApp(2) in lines 2627 is called, the first image is removed.

The third and fourth input elements defined in lines 2831 are considered as a pair. The third input is a button with the name "Append div." The fourth input element is actually a text field to allow you to type something in. Once the typing is finished and the Append div button is clicked, a node is generated and inserted at the end of the divisions.

The details of the functions myDelApp() and myAddApp() are listed in the second part of the example:



Listing: Continuation Of The Example ex11-08.htm (Part Two)

34:  <script>
35:  function myDelApp(stV)
36:  {
37:    objDiv = document.getElementsByTagName("div")
38:    objImg = document.getElementsByTagName("img")
39:
40: if((stV ==1)&&(objDiv.length > 0)) document.body.removeChild(objDiv.item(0))
41: if((stV ==2)&&(objImg.length > 0)) document.body.removeChild(objImg.item(0))
42:
43:    llSt = "There are "+objDiv.length+" &lt;div&gt; elements <br />"+
44:            "and "+objImg.length+" &lt;img&gt; elements left <br />"
45:    document.getElementById("outMsg").innerHTML = llSt
46:  }
47:
48:  function myAddApp(stV)
49:  {
50:    objDiv = document.getElementsByTagName("div")
51:    objImg = document.getElementsByTagName("img")
52:
53:    if ((stV ==1) && (objDiv.length < 6)) {
54:        newO = document.createElement("div")
55:        txtId = document.getElementById("txId")
56:        newT = document.createTextNode(txtId.value)
57:        newO.appendChild(newT)
58:        document.body.insertBefore(newO,objImg.item(0))
59:    }
60:
61:    llSt = "There are "+objDiv.length+" &lt;div&gt; elements <br />"+
62:            "and "+objImg.length+" &lt;img&gt; elements left <br />"
63:    document.getElementById("outMsg").innerHTML = llSt
64:  }
65:  </script>
66:
67:  </body>
68:  </html>

Inside the function myDelApp(), the statements in lines 37 and 38 are used to collect all the division and image elements and assign them to the objects objDiv and objImg. If the value of the variable stV is 1, the if statement in line 40 is executed and the function removeChild() is called to delete the selected division specified by objDiv.item(0). If the variable stV is 2, the statement in line 41 is activated and the selected image element will be deleted from the page. It is good practice to check the object length objDiv.length (see line 40) before any deletion to prevent undesirable effects or system errors.

The function myAddApp() in lines 4864 is used to insert elements into the page. When this function is called, the following tasks are performed to insert the text before the first image element:

  • Create a division element (line 54).

  • Get the text from the text box (line 55).

  • Create a text node with the text (line 56).

  • Add the text node to the division element (line 57).

  • Insert the node before the first image element (line 58).

Most XHTML elements contain attributes. In many cases, attributes are the integral part of an element. Elements such as anchor <a> and image <img> require them to function properly. The next step is to know how to generate attributes for an element at run time. Some screen shots of this example are shown in Figs 11.13 and 11.14.

Figure 11.13. ex11-08.htm

graphics/11fig13.jpg


Figure 11.14. Inserting and deleting elements at run time

graphics/11fig14.jpg


11.4.4 Generating and controlling attributes with the element interface

The attributes property (not supported by IE5.5) defined in the node interface provides a handy way to gain access to the existing attributes of a page element. However, the node interface contains very little information on how to create them in the first place. In fact, the functions to generate and control attributes at run time are embedded inside another DOM core interface called the "element interface." A simplified verion of the interface is listed in ex11-09.txt.



Listing: ex11-09.txt - DOM Core: Doucment Interface  Element

 1: interface Element : Node {
 2:   readonly attribute DOMString        tagName;
 3:   DOMString          getAttribute(in DOMString name);
 4:   void               setAttribute(in DOMString name,
 5:                                   in DOMString value)
 6:
 7:   void               removeAttribute(in DOMString name)
 8:
 9:   NodeList           getElementsByTagName(in DOMString name);
10:
11:   // Introduced in DOM Level 2:
12:   boolean            hasAttribute(in DOMString name);
13:
14: };

The function getAttribute() in line 3 is a general standard function to obtain attributes from elements. Again, not all browsers (including IE5.5) implement and support this function completely. For example, suppose that you have defined a division element as



<div id="id01" style="color:#ffffff;font-size:16pt;
     font-family:arial">This is paragraph one</div>

The script statements



objV = document.getElementById("id01")
objV.getAttribute("id")

return the value "id01," whereas the command



objV.getAttribute("style")

returns the CSS style settings as



color: rgb(255,255,255); font-size: 16pt; font-family: arial;

IE5.5 doesn't fully support the getAttribute() function and some ways to work around it are necessary. You will need IE6+ and NS6+ to display the result directly. The setAttribute() function is a powerful function to set the attributes of an element. One very simple use of this function is



objV.setAttribute("style","color:#ffff00;font-size:18pt;
      font-family:Times")

Since the variable objV represents the element with id="id01", the call on the setAttribute() function above sets the CSS style of the division element. Obviously, you can also use the style object to set the style properties one by one. The real strength of this function is that it can set the attributes of a newly created element.

The following is a typical program fragment to generate an image at run time and insert it before an element with id="id01":



1:  objV = document.getElementById("id01")
2:  newImg = document.createElement("img")
3:  tmpV = newImg.setAttribute("alt","pic")
4:  tmpV = newImg.setAttribute("hspace","10")
5:  tmpV = newImg.setAttribute("vspace","10")
6:  tmpV = newImg.setAttribute("src","myPic.jpg")
7:  tmpV = document.body.insertBefore(newImg,objV)

You create the image element <img> and assign the element to a variable newImg in line 2. In lines 36, the function setAttribute() is called to build up the attributes that are associated with <img>. At the end of line 6, you have an image element like this:



<img alt="pic" hspace="10" vspace="10" src="myPic.jpg" />

The final line is to insert this image element before the element with id="id01". To actually use these attribute functions, let's consider an example to generate photographs online.

11.4.5 Generating images at run time

To put the setAttribute() function into action, we consider a simple example to generate images from your hard drive to a Web page at run time. This example uses an input element with type="file" to get a picture file from your hard drive and then insert it into a page as an element. A modification of this example is also discussed in section 11.5.1 to build a more practical example. That is, a page to generate an image and organize an online photo album at run time.

The interface part of this example is listed as follows:



Example: ex11-09.htm - Generating Images At Run Time

 1:  <?xml version="1.0" encoding="iso-8859-1"?>
 2:  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 3:      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 4:  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 5:  <head><title>Generating Images At Run Time  ex1109.htm</title></head>
 6:  <style>
 7:   .butSt{background-color:#aaaaaa;font-family:arial;font-weight:bold;
 8:      font-size:14pt;color:#880000;width:150px;height:35px}
 9:  </style>
10:  <body style="background:#dddddd;font-family:arial;font-size:20pt;
11:     color:#000088;font-weight:bold;text-align:center">
12:   Inserting Images At Run Time<br />
13:
14:  <div id="id01" style="color:#00ff00"></div>
15:
16:  <img src="line1.gif" width="550" height="6" alt="pic" />
17:  <table align="center">
18:  <tr><td><input type="text" readonly class="butSt"
19:           style="color:#000088" value="Pic File Name" /></td>
20:      <td><input type="file" id="fileId"
21:           class="butSt" style="width:350px" /><br /></td></tr>
22:  <tr><td><input type="button" onclick="myAddPic()"
23:           class="butSt" value="Insert Pic" /></td>
24:      <td><input type="button" onclick="genBr()"
25:           class="butSt" value="Line Break" /></td></tr>
26:  </table>
27:  <script src="ex11-09.js"></script>
28:  </body>
29:  </html>

The division element defined in line 14 is an empty element ready to accept the images loaded from your hard drive. After the graphic line in line 16, there is a table with two rows. The first row contains two input elements. The first input element is a text to display "Pic File Name." The type of the second input element in lines 2021 is type=file. This button opens a "Choose File" dialog box so you can search your local hard drive for a desirable picture. Once you have picked your picture file with a double click or opened it inside the dialog box, the file name of the picture appears inside the input field specified in lines 2021.

The second row of the table contains two buttons. When the Insert Pic button (lines 2223) is clicked, the myAddPic() function is called to load the picture into the page. All pictures are loaded adjacent to each other until the Line Break button is clicked to generate a line break.

Some screen shots of this example are shown in Figs 11.1511.17.

Figure 11.15. ex11-09.htm

graphics/11fig15.jpg


Figure 11.17. Inserting image at run time

graphics/11fig17.gif


Figure 11.16. Choose file dialog box

graphics/11fig16.jpg


The external program file ex11-09.js is listed below.



Example: ex11-09.js - The ECMAScript For ex1109.htm

 1:  var IE = document.all?true:false
 2:
 3:  var widthV=200
 4:  var heightV=150
 5:  var hspaceV =10
 6:  var vspaceV =10
 7:  var picV = "pic"
 8:  var objV = document.getElementById("id01")
 9:
10:  function myAddPic()
11:  {
12:    fileV = document.getElementById("fileId").value
13:    fileVV = "file://"+fileV
14:    newImg = document.createElement("img")
15:    tmpV = newImg.setAttribute("alt",picV)
16:    tmpV = newImg.setAttribute("hspace",hspaceV)
17:    tmpV = newImg.setAttribute("vspace",vspaceV)
18:
19:    if (!IE){
20:      tmpV = newImg.setAttribute("width",200)
21:      tmpV = newImg.setAttribute("height",150)
22:    }
23:
24:    tmpV = newImg.setAttribute("src",fileVV)
25:    tmpV = document.body.insertBefore(newImg,objV)
26:
27:    if (IE) {
28:      newImg.style.width=widthV+"px"
29:      newImg.style.height=heightV+"px"
30:    }
31:  }
32:
33:  function genBr()
34:  {
35:   lineBr = document.createElement("br")
36:   tmpV = document.body.insertBefore(lineBr,objV)
37:  }
38:

The first line is to detect whether an IE browser is used. The next couple of lines are the parameters controlling the size of the image. Initially, a dimension of 200 x 150 pixels is specified to display the picture. The hspaceV and vspaceV variables provide some extra spaces between each picture. The statement in line 8 declares a variable objV (object variable) before which all images are inserted.

Once the Insert Pic button is clicked, the myAddPic() function is called. First, this function gets the file name from the input field with id="fileId". We add the keyword file:// in front of the file name to indicate that the file name is from a local hard drive. The statement in line 14 generates an image element at run time, i.e., <img />. To control the image, we want the image element to have the following attributes:



<img alt="pic" hspace="10" vspace="10" width="200" height="150"
      src=file://xxxxx />

Lines 1517 use the function setAttribute() to set hspace and vspace. Since IE (IE5.x and IE 6.01) didn't support W3C's setAttribute() function on width and height, a browser detection is used in lines 1922. If the browser is not IE, we continue W3C's attribute settings and use the statement



document.body.insertBefore(newImg,objV)

and ultimately insert the newly created image element before the object objV with identity id="id01". After this element insertion, an IE detection code is used to set the image's width and height using IE's style properties.

When the Line Break button is pressed, the function genBr() defined in lines 3337 is called. This function creates a line break element, i.e., <br />, which is inserted before the object element objV.

    Table of Contents

    Previous Next