15.3. Legacy DOM: Document Object CollectionsThe list of Document object properties in the previous section omitted an important category of properties: document object collections. These array-valued properties are the heart of the legacy DOM. They are the properties that give you access to certain special elements of the document:
As their names imply, these properties are collections of all the links, images, forms, etc., that appear in a document. Their elements are in the same order as in the document source code. document.forms[0] refers to the first <form> tag in the document, and document.images[4] refers to the fifth <img> tag, for example. The objects contained by these legacy DOM collections are scriptable, but it is important to understand that none of them allows you to alter the structure of the document. You can inspect and alter link destinations, read and write values from form elements, and even swap one image for another image, but you can't change the text of the document. Old browsers, such as Netscape 2, 3, and 4 and IE 3, were not able to reflow (or relayout) a document once it had been parsed and displayed. For this reason, the legacy DOM did not (and does not) allow document changes that require a reflow. For example, the legacy DOM includes an API for adding new <option> elements within a <select> element. It can do this because HTML forms display <select> elements as pull-down menus, and adding new items to such a menu does not alter the layout of rest of the form. There is no API in the legacy DOM for adding a new radio button to a form or adding a new row to a table, however, because changes like these would require a reflow. 15.3.1. Naming Document ObjectsThe problem with numerically indexed document object collections is that position-based indexes are brittle: small document changes that reorder document elements can break code that relies on their order. A more robust solution is to assign names to important document elements and to refer to those elements by name. In the legacy DOM, you do this with the name attribute of forms, form elements, images, applets, and links. When the name attribute is present, its value is used to expose the corresponding object by name. So, for example, suppose an HTML document contains the following form: <form name="f1"><input type="button" value="Push Me"></form> Assuming that the <form> is the first one in the document, your JavaScript code can refer to the resulting Form object with any of the following three expressions: document.forms[0] // Refer to the form by position within the document document.forms.f1 // Refer to the form by name as a property document.forms["f1"] // Refer to the form by name as an array index In fact, setting the name attribute of a <form>, <img>, or <applet> (but not of an <a> tag) also makes the corresponding Form, Image, or Applet object (but not Link or Anchor object) accessible as a named property of the document object itself. Thus, you can also refer to the form as: document.f1 The elements within a form may also be given names. If you set the name attribute of a form element, the object that represents that form element becomes accessible through a property of the Form object itself. So suppose you have a form that looks like this: <form name="shipping"> ... <input type="text" name="zipcode"> ... </form> You can refer to the text input field element of this form with an intuitive syntax: document.shipping.zipcode One final note is necessary about the naming of document elements in the legacy DOM. What happens if two document elements have name attributes with the same value? If a <form> and <img> tag both have the name "n", for example, the document.n property becomes an array that holds references to both elements. Typically, you should strive to ensure that your name attributes are unique so that this situation does not arise. It is common in one case, however. In HTML forms, convention dictates that groups of related radio buttons and checkboxes are given the same name. When you do this, that name becomes a property of the containing Form object, and the property value is an array that holds references to the various radio button or checkbox objects. You'll learn more about this in Chapter 18. 15.3.2. Event Handlers on Document ObjectsTo be interactive, an HTML document and the elements within it must respond to user events. You learned a bit about events and event handlers in Chapter 13, and you've seen several examples that use simple event handlers. There are many more examples of event handlers in this chapter because they are the link between document objects and JavaScript code. I'll defer a complete discussion of events and event handlers until Chapter 17. For now, remember that event handlers are defined by attributes of HTML elements, such as onclick and onmouseover. The values of these attributes should be strings of JavaScript code. This code is executed whenever the specified event occurs on the HTML element. Document objects accessed through collections such as document.links have properties that correspond to the attributes of the HTML tag. A Link object, for example, has an href tag that mirrors the HRef attribute of the <a> tag. This holds for event handlers as well. You can define an onclick event handler for a hyperlink either by setting the onclick attribute on the <a> tag or by setting the onclick property of the Link object. As another example, consider the onsubmit attribute of the <form> element. In JavaScript, the Form object has a corresponding onsubmit property. (Remember that HTML is not case-sensitive, and attributes can be written in uppercase, lowercase, or mixed case. In JavaScript, all event handler properties must be written in lowercase.) In HTML, event handlers are defined by assigning a string of JavaScript code to an event-handler attribute. In JavaScript, however, they are defined by assigning a function to an event-handler property. Consider the following <form> and its onsubmit event handler: <form name="myform" onsubmit="return validateform();">...</form> In JavaScript, instead of using a string of JavaScript code that invokes a function and returns its result, simply assign the function directly to the event-handler property like this: document.myform.onsubmit = validateform; Note that there are no parentheses after the function name. This is because you don't want to invoke the function here; you just want to assign a reference to it. See Chapter 17 for a complete discussion of event handlers. 15.3.3. Legacy DOM ExampleExample 15-1 shows a listanchors() function that opens a new window and uses document.write() to output a list of all the anchors in the original document. Each entry in this list is a link with an event handler that causes the original window to scroll to the location of the specified anchor. The code in this example is particularly useful if you write your HTML documents so that all section headings are enclosed in anchors like this: <a name="sect14.6"><h2>The Anchor Object</h2></a> Note that the listanchors() function uses the Window.open() method. As shown in Chapter 14, browsers typically block pop-up windows unless they are created in response to a user action. Call listanchors() when the user clicks on a link or button; don't do it automatically when your web page loads. Example 15-1. Listing all anchors
|