JavaScript Bible, Gold Edition part 26 ppsx

10 256 0
JavaScript Bible, Gold Edition part 26 ppsx

Đang tải... (xem toàn văn)

Thông tin tài liệu

98 Part III ✦ Document Objects Reference Of the three models, NN4’s DOM is the trickiest one to deal with at the HTML level. While it may be possible that your content design will look the same using positioned DIV and SPAN elements in all DHTML-capable browsers, often the appearance in NN4 is unacceptable. At that point, you will probably have to use scripts in your Body to dynamically generate HTML, specifying the <LAYER> tag for NN4 and positioned <DIV> elements for the rest. Although IE4 and IE5.x can use the same basic Microsoft object model, not all DHTML code renders the same on both generations of browsers. Microsoft made some changes here and there to the way some style attributes are rendered so that IE5.x comes into better compliance with the CSS recommendation. Using script libraries As long as you plan to use scripts to dynamically generate HTML for the page, you might consider creating separate, external .js libraries for each of the object models you want to support for the page. Scripts in each library contain code for both the HTML accumulation (for use with document.write() in the main page) and for processing user interaction. Assuming that only DHTML-capable browsers reach the page, branching is required only at the beginning of the document where an object model-specific library is loaded: var isIE4 = ((navigator.appName.indexOf(“Microsoft”) == 0 && parseInt(navigator.appVersion) == 4)) var isW3C = (document.documentElement) ? true : false if (isW3C) { // give priority to W3C model for IE5.x document.write(“<SCRIPT LANGUAGE=’JavaScript’ SRC=’page3_W3C.js’><” + “\/SCRIPT>”) } else if (isIE4) { document.write(“<SCRIPT LANGUAGE=’JavaScript’ SRC=’page3_IE4.js’><” + “\/SCRIPT>”) } else { document.write(“<SCRIPT LANGUAGE=’JavaScript’ SRC=’page3_generic.js’><” + “\/SCRIPT>”) } Each of the statements that writes the <SCRIPT> tag includes a workaround that is required on some browsers (NN4 especially) to facilitate using document.write() to write script tags to the page. Once these libraries are specified for the page, script statements anywhere later in the page can invoke functions defined in each library to generate a particular element or set of elements in the object model HTML optimized for the current browser. Of course, it’s not necessary to have one library devoted to each object model. You might find it more convenient for authoring and maintenance to keep all the code in one library that has numerous internal branchings for browser ver- sions. Branches in a library can use the version sniffing global variables defined in the main HTML page’s scripts. Better still, a library can be entirely self-contained by using object detection. You can see an example of such a DHTML library in Chapter 48. Note 99 Chapter 14 ✦ Document Object Model Essentials Handling events Thanks to the W3C DOM’s event model implementing a similar event bubbling scheme as IE4+, you can apply that event propagation model to IE4+ and W3C DOM browsers. There are differences in the details, however. IE’s approach does not pass the event object as a parameter to a function invoked by an event handler. Instead, the IE event object is a property of the window object. Therefore, your functions have to look for the passed parameter and substitute the window.event object in its place for IE: function calculate(evt) { evt = (evt) ? evt : window.event // more statements to handle the event // } Additional branching is necessary to inspect many details of the event. For example, IE calls the object receiving the event the srcElement, while the W3C DOM calls it the target. Canceling the default behavior of the event (for example, preventing a form’s submission if it fails client-side validation) is also different for the models (although the “old-fashioned” way of letting HTML-type event handlers evaluate to return false still works). You can find more event object details in Chapter 29. Simulating IE4+ Syntax in NN6 With so much IE4+ DHTML-related JavaScript code already in use, scripters are certainly eager to leverage as much of their old code as possible in W3C DOM browsers such as NN6. While NN6 helps a bit by implementing the IE innerHTML property for HTML elements, this section shows you how a simple .js library can provide NN6 with a few more common convenience properties of the IE4+ object model. By linking this library into your pages, you can give NN6 the valuable HTML element properties shown in Table 14-8. Table 14-8 IE4+ HTML Element Property Simulation for NN6 Property Read Write Replaces in W3C DOM all yes no getElementsByTagName(“*”) innerText yes yes nodeValue property for text nodes; creating a text fragment node and inserting it into existing node structure outerHTML no yes (No equivalent) Scripts that make these simulations possible use the prototype inheritance behavior of static objects described earlier in this chapter. Because they require 100 Part III ✦ Document Objects Reference NN6-specific features in that browser’s implementation of JavaScript 1.5, link the .js library with the following tag: <SCRIPT LANGUAGE=”JavaScript1.5” TYPE=”text/javascript” SRC=”IE4Simulator.js”></SCRIPT> All scripts that follow belong in the .js library. They’re divided into two groups to allow for detailed discussion. The all property simulator Nearly every HTML element can be a container of other elements (with the exception of a handful of leaf nodes, such as <BR>). The all property in IE returns a collection of references to all element objects nested inside the current object, no matter how deeply nested the containment hierarchy is. That’s why the docu- ment.all reference is such a convenient way to access any element in the entire document that has an ID attribute. As illustrated earlier in the sidebar figure, the Node static object is the object from which all elements are derived. That object’s prototype is enhanced here because you have to make sure that all nodes, especially the document node, can acquire the all property. Listing 14-4a shows the segment of the library that defines the all property for the Node object prototype. Listing 14-4a: Simulator for the all Property if (!document.all) { Node.prototype.__defineGetter__(“all”, function() { if (document.getElementsByTagName(“*”).length) { switch (this.nodeType) { case 9: return document.getElementsByTagName(“*”) break case 1: return this.getElementsByTagName(“*”) break } } return “” }) Node.prototype.__defineSetter__(“all”, function() {}) } This portion of the library exhibits a rare instance in which using object detec- tion for document.all does the right thing now and in the future. The prototype should not execute if the browser loading the page already has a document.all property. The anonymous function first establishes a branch in the code only for the object model if it supports the wildcard parameter for the document.getElementsByTagName() method. The function then performs slightly different extractions depending on whether the node is the document (type 9) or an element (type 1). If the all property should be queried for any other kind of node, the returned value is an empty string. Each time the all property is accessed, the anonymous function executes to pick up all elements nested inside the current 101 Chapter 14 ✦ Document Object Model Essentials node. Therefore, the collection returned by the all property is always up to date, even if the node structure of the current object changes after the document loads. While this simulator code provides NN6 scripts with IE4-like syntax for referenc- ing elements, the collection returned by the native document.all in IE and calcu- lated document.all in NN6 may not always have an identical length — the collections are derived slightly differently. The important thing to know, however, is that by employing this prototype modifier in NN6, you have the ability to reference elements by their IDs in the form document.all.elementID. The content properties simulators The remaining code of this library lets NN6 use the same innerText and outerHTML properties as IE4 for modifying all element objects. Listing 14-4b con- tains the NN6 JavaScript code that prepares the browser to set an element object’s outerHTML property, as well as get and set the innerText properties. The code again uses anonymous functions assigned to getter and setter behaviors of proto- type properties. Because the properties here apply only to HTML elements, the static object whose prototype is being modified is HTMLElement. All specific HTML element objects inherit properties and methods from the HTMLElement object. All four proto- type adjustment blocks are nested inside a condition that makes sure the static HTMLElement object is exposed in the browser’s object model (which it is in NN6+). All functions in Listing 14-4b use the W3C DOM Range object (Chapter 19). Two of them use a Netscape-proprietary method of the Range object as a shortcut to converting a string into a node hierarchy. Listing 14-4b: Simulator for the innerText and outerHTML Properties if (HTMLElement) { HTMLElement.prototype.__defineSetter__(“innerText”, function (txt) { var rng = document.createRange() rng.selectNodeContents(this) rng.deleteContents() var newText = document.createTextNode(txt) this.appendChild(newText) return txt }) HTMLElement.prototype.__defineGetter__(“innerText”, function () { var rng = document.createRange() rng.selectNode(this) return rng.toString() }) HTMLElement.prototype.__defineSetter__(“outerHTML”, function (html) { var rng = document.createRange() rng.selectNode(this) var newHTML = rng.createContextualFragment(html) this.parentNode.replaceChild(newHTML,this) return html }) HTMLElement.prototype.__defineGetter__(“outerHTML”, function() {return ‘’}) } 102 Part III ✦ Document Objects Reference The getter function for the innerText property creates a range whose bound- aries encompass the current object. Because a range includes only the text part of a document, the adjustment of the range boundaries to the current node encom- passes all text, including text nodes of nested elements. Returning the string ver- sion of the range provides a copy of all text inside the current element. For the setter action, the anonymous function defines one parameter variable, which is the text to replace the text inside an element. With the help, again, of the Range object, the range is cinched up to encompass the contents of the current node. Those contents are deleted, and new text node is created out of the value assigned to the property (in other words, passed as a parameter to the anonymous function). With the current object no longer containing any nodes after the dele- tion, the appendChild() method inserts the new text node as a child to the current object. Setting the outerHTML property starts out the same as setting the innerText, but the new content — which arrives as a string assigned to the parameter variable — is converted into a fully formed set of nested nodes via the createContextualFragment() method. This method is invoked on any range object, but it does not affect the range to which it is attached. The value returned from the method is what’s important, containing a node whose content is already set up as genuine DOM nodes. That’s why the returned value can be passed to the replaceChild() method to replace the new content as HTML rather than plain text. But because the outerHTML property applies to the entire current element, it must use the roundabout way of replacing itself as a child of its parent. This pre- vents the accidental modification of any siblings in the process. Where to Go from Here These past two chapters provided an overview of the core language and object model issues that anyone designing pages that use JavaScript must confront. The goal here is to stimulate your own thinking about how to embrace or discard levels of compatibility with your pages as you balance your desire to generate “cool” pages and serve your audience. From here on, the difficult choices are up to you. To help you choose the objects, properties, methods, and event handlers that best suit your requirements, the rest of the chapters in Part III and all of Part IV pro- vide in-depth references to the document object model and core JavaScript lan- guage features. Observe the compatibility ratings for each language term very carefully to help you determine which features best suit your audience’s browsers. Most example listings are complete HTML pages that you can load in various browsers to see how they work. Many others invite you to explore how things work via The Evaluator (Chapter 13). Play around with the files, making modifications to build your own applications or expanding your working knowledge of JavaScript in the browser environment. 103 Chapter 14 ✦ Document Object Model Essentials The language and object models have grown in the handful of years they have been in existence. The amount of language vocabulary has increased astronomi- cally. It takes time to drink it all in and feel comfortable that you are aware of the powers available to you. Don’t worry about memorizing the vocabulary. It’s more important to acquaint yourself with the features, and then come back later when you need the implementation details. Be patient. Be persistent. The reward will come. ✦✦✦ . require 100 Part III ✦ Document Objects Reference NN6-specific features in that browser’s implementation of JavaScript 1.5, link the .js library with the following tag: <SCRIPT LANGUAGE= JavaScript1 .5”. your requirements, the rest of the chapters in Part III and all of Part IV pro- vide in-depth references to the document object model and core JavaScript lan- guage features. Observe the compatibility. ‘’}) } 102 Part III ✦ Document Objects Reference The getter function for the innerText property creates a range whose bound- aries encompass the current object. Because a range includes only the text part

Ngày đăng: 06/07/2014, 06:20

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan