CD-142 Part VI ✦ Appendixes Listing 15-11 (continued) <INPUT TYPE=”text” NAME=”HTMLInput” VALUE=”<I>First</I> Article <SPAN CLASS=’small’>(of ten)</SPAN>” SIZE=50> <INPUT TYPE=”button” VALUE=”Change Heading HTML” onClick=”setGroupLabelAsHTML(this.form)”> </P> <P> <INPUT TYPE=”text” NAME=”textInput” VALUE=”<I>First</I> Article <SPAN CLASS=’small’>(of ten)</SPAN>” SIZE=50> <INPUT TYPE=”button” VALUE=”Change Heading Text” onClick=”setGroupLabelAsText(this.form)”> </P> </FORM> <H1 ID=”label1”>ARTICLE I</H1> <P> Congress shall make no law respecting an establishment of religion, or prohibiting the free exercise thereof; or abridging the freedom of speech, or of the press; or the right of the people peaceably to assemble, and to petition the government for a redress of grievances. </P> </BODY> </HTML> isContentEditable NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓ Example Use The Evaluator (Chapter 13) to experiment with both the contentEditable and isContentEditable properties on the myP and nested myEM elements (reload the page to start with a known version). Check the current setting for the myEM element by typing the following statement into the top text field: myEM.isContentEditable elementObject.isContentEditable CD-143 Appendix F ✦ Examples from Parts III and IV This value is false because no element upward in the element containment hierar- chy is set to be editable yet. Next, turn on editing for the surrounding myP element: myP.contentEditable = true At this point, the entire myP element is editable because its child element is set, by default, to inherit the edit state of its parent. Prove it by entering the following statement into the top text box: myEM.isContentEditable While the myEM element is shown to be editable, no change has accrued to its contentEditable property: myEM.contentEditable This property value remains the default inherit. You can see an additional example of these two properties in use in Listing 15-7. isDisabled NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓ Example Use The Evaluator (Chapter 13) to experiment with both the disabled and isDisabled properties on the myP and nested myEM elements (reload the page to start with a known version). Check the current setting for the myEM element by typ- ing the following statement into the top text field: myEM.isDisabled This value is false because no element upward in the element containment hierar- chy is set for disabling yet. Next, disable the surrounding myP element: myP.disabled = true At this point, the entire myP element (including its children) is disabled. Prove it by entering the following statement into the top text box: myEM.isDisabled elementObject.isDisabled CD-144 Part VI ✦ Appendixes While the myEM element is shown as disabled, no change has accrued to its disabled property: myEM.disabled This property value remains the default false. isMultiLine NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓ Example Use The Evaluator (Chapter 13) to read the isMultiLine property for elements on that page. Try the following statements in the top text box: document.body.isMultiLine document.forms[0].input.isMultiLine myP.isMultiLine myEM.isMultiLine All but the text field form control report that they are capable of occupying multiple lines. isTextEdit NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓ ✓ Example Good coding practice dictates that your script check for this property before invok- ing the createTextRange() method on any object. A typical implementation is as follows: if (document.all.myObject.isTextEdit) { var myRange = document.all.myObject.createTextRange() [more statements that act on myRange] } elementObject.isTextEdit CD-145 Appendix F ✦ Examples from Parts III and IV lang NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓✓✓ Example Values for the lang property consist of strings containing valid ISO language codes. Such codes have, at the minimum, a primary language code (for example, “fr” for French) plus an optional region specifier (for example, “fr-ch” for Swiss French). The code to assign a Swiss German value to an element looks like the following: document.all.specialSpan.lang = “de-ch” language NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓ ✓ Example Although it is unlikely that you will modify this property, the following example shows you how to do it for a table cell object: document.all.cellA3.language = “vbs” lastChild See firstchild. length NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓✓ ✓ ✓ ✓✓✓✓ elementObjectCollection.length CD-146 Part VI ✦ Appendixes Example You can try the following sequence of statements in the top text box of The Evaluator to see how the length property returns values (and sets them for some objects). Note that some statements work in only some browser versions. (All browsers) document.forms.length (All browsers) document.forms[0].elements.length (NN3+, IE4+) document.images.length (NN4+) document.layers.length (IE4+) document.all.length (IE5+, NN6) document.getElementById(“myTable”).childNodes.length nextSibling previousSibling NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓✓ Example The following function assigns the same class name to all child nodes of an element: function setAllChildClasses(parentElem, className) { var childElem = parentElem.firstChild while (childElem.nextSibling) { childElem.className = className childElem = childElem.nextSibling } } This example is certainly not the only way to achieve the same results. Using a for loop to iterate through the childNodes collection of the parent element is an equally valid approach. nodeName NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓✓ elementObject.nodeName CD-147 Appendix F ✦ Examples from Parts III and IV Example The following function demonstrates one (not very efficient) way to assign a new class name to every P element in an IE5+ document: function setAllPClasses(className) { for (var i = 0; i < document.all.length; i++) { if (document.all[i].nodeName == “P”) { document.all[i].className = className } } } A more efficient approach uses the getElementsByTagName() method to retrieve a collection of all P elements and then iterate through them directly. nodeType NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓✓ Example You can experiment with viewing nodeType property values in The Evaluator. The P element whose ID is myP is a good place to start. The P element itself is a nodeType of 1: document.getElementById(“myP”).nodeType This element has three child nodes: a string of text (nodeName #text); an EM ele- ment ( nodeName EM); and the rest of the text of the element content (nodeName #text ). If you view the nodeType of either of the text portions, the value comes back as 3: document.getElementById(“myP”).childNodes[0].nodeType In NN6 and IE5/Mac, you can inspect the nodeType of the one attribute of this ele- ment (the ID attribute): document.getElementById(“myP”).attributes[0].nodeType With NN6 and IE5/Mac, you can see how the document object returns a nodeType of 9: document.nodeType elementObject.nodeType CD-148 Part VI ✦ Appendixes When IE5 does not support a nodeType constant for a node, its value is sometimes reported as 1. However, more likely the value is undefined. nodeValue NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓✓ Example The first example increases the width of a TEXTAREA object by 10 percent. The nodeValue is converted to an integer (for NN6’s string values) before performing the math and reassignment: function widenCols(textareaElem) { var colWidth = parseInt(textareaElem.attributes[“cols”].nodeValue, 10) textareaElem.attributes[“cols”].nodeValue = (colWidth * 1.1) } The second example replaces the text of an element, assuming that the element contains no further nested elements: function replaceText(elem, newText) { if (elem.childNodes.length == 1 && elem.firstChild.nodeType == 3) { elem.firstChild.nodeValue = newText } } The function builds in one final verification that the element contains just one child node and that it is a text type. An alternative version of the assignment statement of the second example uses the innerText property in IE with identical results: elem.innerText = newText offsetHeight offsetWidth NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓✓✓ elementObject.offsetHeight CD-149 Appendix F ✦ Examples from Parts III and IV Example With IE4+, you can substitute the offsetHeight and offsetWidth properties for clientHeight and clientWidth in Listing 15-6. The reason is that the two ele- ments in question have their widths hard-wired in style sheets. Thus, the offsetWidth property follows that lead rather than observing the default width of the parent (BODY) element. With IE5+ and NN6, you can use The Evaluator to inspect the offsetHeight and offsetWidth property values of various objects on the page. Enter the following statements into the top text box: document.getElementById(“myP”).offsetWidth document.getElementById(“myEM”).offsetWidth document.getElementById(“myP”).offsetHeight document.getElementById(“myTable”).offsetWidth offsetLeft offsetTop NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓✓✓ Example The following IE script statements utilize all four “offset” dimensional properties to size and position a DIV element so that it completely covers a SPAN element located within a P element. This can be for a fill-in-the-blank quiz that provides text entry fields elsewhere on the page. As the user gets an answer correct, the blocking DIV element is hidden to reveal the correct answer. document.all.blocker.style.pixelLeft = document.all.span2.offsetLeft document.all.blocker.style.pixelTop = document.all.span2.offsetTop document.all.blockImg.height = document.all.span2.offsetHeight document.all.blockImg.width = document.all.span2.offsetWidth Because the offsetParent property for the SPAN element is the BODY element, the positioned DIV element can use the same positioning context (it’s the default context, anyway) for setting the pixelLeft and pixelTop style properties. (Remember that positioning properties belong to an element’s style object.) The offsetHeight and offsetWidth properties can read the dimensions of the SPAN element (the example has no borders, margins, or padding to worry about) and assign them to the dimensions of the image contained by the blocker DIV element. elementObject.offsetLeft CD-150 Part VI ✦ Appendixes This example is also a bit hazardous in some implementations. If the text of span2 wraps to a new line, the new offsetHeight value has enough pixels to accommo- date both lines. But the blockImg and blocker DIV elements are block-level ele- ments that render as a simple rectangle. In other words, the blocker element doesn’t turn into two separate strips to cover the pieces of span2 that spread across two lines. offsetParent NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5 Compatibility ✓✓✓✓ Example You can use the offsetParent property to help you locate the position of a nested element on the page. Listing 15-12 demonstrates how a script can “walk” up the hierarchy of offsetParent objects in IE for Windows to assemble the location of a nested element on a page. The goal of the exercise in Listing 15-12 is to position an image at the upper-left corner of the second table cell. The entire table is centered on the page. The onLoad event handler invokes the setImagePosition() function. The func- tion first sets a Boolean flag that determines whether the calculations should be based on the client or offset sets of properties. IE4/Windows and IE5/Mac rely on client properties, while IE5+/Windows works with the offset properties. The dis- crepancies even out, however, with the while loop. This loop traverses the offsetParent hierarchy starting with the offsetParent of the cell out to, but not including, the document.body object. The body object is not included because that is the positioning context for the image. In IE5, the while loop executes only once because just the TABLE element exists between the cell and the body; in IE4, the loop executes twice to account for the TR and TABLE elements up the hierarchy. Finally, the cumulative values of left and top measures are applied to the position- ing properties of the DIV object’s style and the image is made visible. Listing 15-12: Using the offsetParent Property <HTML> <HEAD> <TITLE>offsetParent Property</TITLE> <SCRIPT LANGUAGE=”JavaScript”> function setImagePosition(){ var cElement = document.all.myCell elementObject.offsetParent CD-151 Appendix F ✦ Examples from Parts III and IV // Set flag for whether calculations should use // client- or offset- property measures. Use // client- for IE5/Mac and IE4/Windows; otherwise // use offset- properties. An ugly, but necessary // workaround. var useClient = (cElement.offsetTop == 0) ? ((cElement.offsetParent.tagName == “TR”) ? false : true) : false if (useClient) { var x = cElement.clientLeft var y = cElement.clientTop } else { var x = cElement.offsetLeft var y = cElement.offsetTop } var pElement = document.all.myCell.offsetParent while (pElement != document.body) { if (useClient) { x += pElement.clientLeft y += pElement.clientTop } else { x += pElement.offsetLeft y += pElement.offsetTop } pElement = pElement.offsetParent } document.all.myDIV.style.pixelLeft = x document.all.myDIV.style.pixelTop = y document.all.myDIV.style.visibility = “visible” } </SCRIPT> </HEAD> <BODY onload=”setImagePosition()”> <SCRIPT LANGUAGE=”JavaScript”> </SCRIPT> <H1>The offsetParent Property</H1> <HR> <P>After the document loads, the script positions a small image in the upper left corner of the second table cell.</P> <TABLE BORDER=1 ALIGN=”center”> <TR> <TD>This is the first cell</TD> <TD ID=”myCell”>This is the second cell.</TD> </TR> </TABLE> <DIV ID=”myDIV” STYLE=”position:absolute; visibility:hidden; height:12; width:12”> <IMG SRC=”end.gif” HEIGHT=12 WIDTH=12></DIV> </BODY> </HTML> elementObject.offsetParent . Property</TITLE> <SCRIPT LANGUAGE= JavaScript > function setImagePosition(){ var cElement = document.all.myCell elementObject.offsetParent CD-151 Appendix F ✦ Examples from Parts III and IV // Set flag. field: myEM.isContentEditable elementObject.isContentEditable CD-143 Appendix F ✦ Examples from Parts III and IV This value is false because no element upward in the element containment hierar- chy. the following statement into the top text box: myEM.isDisabled elementObject.isDisabled CD-144 Part VI ✦ Appendixes While the myEM element is shown as disabled, no change has accrued to its disabled