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 elem
Trang 1Of 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 jslibraries 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
Trang 2Handling 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 eventobject is a property of the windowobject Therefore, your functions
have to look for the passed parameter and substitute the window.eventobject 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 falsestill 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 jslibrary 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
Trang 3NN6-specific features in that browser’s implementation of JavaScript 1.5, link the
.jslibrary with the following tag:
<SCRIPT LANGUAGE=”JavaScript1.5” TYPE=”text/javascript”
SRC=”IE4Simulator.js”></SCRIPT>
All scripts that follow belong in the jslibrary 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 allproperty 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.allreference is such a convenient way to access any element in the entire document that has an IDattribute
As illustrated earlier in the sidebar figure, the Nodestatic 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 allproperty Listing 14-4a shows the segment of the library that defines the allproperty for the Nodeobject 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.alldoes 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 allproperty should be queried for any other kind of node, the returned value is an empty string Each time the allproperty is accessed, the anonymous function executes to pick up all elements nested inside the current
Trang 4node Therefore, the collection returned by the allproperty 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.allin IE and
calcu-lated document.allin 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 innerTextand
outerHTMLproperties 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
outerHTMLproperty, as well as get and set the innerTextproperties The code
again uses anonymous functions assigned to getterand setterbehaviors 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 HTMLElementobject All four
proto-type adjustment blocks are nested inside a condition that makes sure the static
HTMLElementobject is exposed in the browser’s object model (which it is in NN6+)
All functions in Listing 14-4b use the W3C DOM Rangeobject (Chapter 19) Two
of them use a Netscape-proprietary method of the Rangeobject 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 ‘’})
}
Trang 5The getter function for the innerTextproperty 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
Rangeobject, 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 outerHTMLproperty 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 outerHTMLproperty 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 lanlan-guage 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
Trang 6The 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
Trang 8Generic HTML
Element Objects
The object model specifications implemented in Internet
Explorer 4+ and Netscape Navigator 6 both feature a
large set of scriptable objects that represent what we often
call “generic” HTML elements Generic elements can be
divided into two groups One group, such as the B and STRIKE
elements, define font styles to be applied to enclosed
sequences of text The need for these elements (and the
objects that represent them) is receding as more browsers
accommodate style sheets The second group of elements
assigns context to content within their start and end tags
Examples of contextual elements include H1, BLOCKQUOTE,
and the ubiquitous P element While browsers sometimes
have consistent visual ways of rendering contextual elements
by default (for example, the large, bold font of an <H1>tag),
the specific rendering is not the intended purpose of the tags
No formal standard dictates that text within an EM element
must be italicized: the style simply has become the custom
since the very early days of browsers
All of these generic elements share a large number of
scriptable properties, methods, and event handlers The
shar-ing extends not only among generic elements, but also among
virtually every renderable element — even if it has additional,
element-specific properties, methods, and/or event handlers
that I cover in depth in other chapters of this reference
Rather than repeat the details of these shared properties,
methods, and event handlers for each object throughout this
reference, I describe them in detail only in this chapter
(unless there is a special behavior, bug, or trick associated
with the item in some object described elsewhere) In
suc-ceeding reference chapters, each object description includes
a list of the object’s properties, methods, and event handlers,
but I do not list shared items over and over (making it hard to
find items that are unique to a particular element) Instead,
you see a pointer back to this chapter for the items in
com-mon with generic HTML element objects A dark tab at the
bottom of this chapter’s pages should make it easy to find this
chapter in a hurry
15
In This Chapter
Working with HTML element objects Common properties and methods Event handlers of all element objects
Trang 9Generic Objects
Table 15-1 lists all of the objects that I treat in this reference as “generic” objects All of these objects share the properties, methods, and event handlers described in succeeding sections and have no special items that require additional coverage elsewhere in this book
Table 15-1 Generic HTML Element Objects
Formatting Objects Contextual Objects
CENTER CITE
SPAN STRONG VAR XMP
accessKey addBehavior() onActivate all addEventListener() onBeforeCopy attributes appendChild() onBeforeCut
elementObject
Trang 10Properties Methods Event Handlers
behaviorUrns applyElement() onBeforeDeactivate
canHaveChildren attachEvent() onBeforeEditFocus
canHaveHTML blur() onBeforePaste
childNodes clearAttributes() onBlur
className cloneNode() onContextMenu
clientHeight componentFromPoint() onControlSelect
clientLeft contains() onCopy
clientTop detachEvent() onCut
clientWidth dispatchEvent() onDblClick
contentEditable fireEvent() onDeactivate
currentStyle focus() onDrag
dataFld getAdjacentText() onDragEnd
dataFormatAs getAttribute() onDragEnter
dataSrc getAttributeNode() onDragLeave
dir getBoundingClientRect() onDragOver
disabled getClientRects() onDragStart
document getElementsByTagName() onDrop
filters getExpression() onFilterChange
firstChild hasChildNodes() onFocus
height insertAdjacentElement() onHelp
hideFocus insertAdjacentHTML() onKeyDown
id insertAdjacentText() onKeyPress
innerHTML insertBefore() onKeyUp
innerText item() onLoseCapture
isContentEditable mergeAttributes() onMouseDown
isDisabled normalize() onMouseEnter
isMultiLine releaseCapture() onMouseLeave
isTextEdit removeAttribute() onMouseMove
lang removeAttributeNode() onMouseOut
Continued
elementObject