1. Trang chủ >
  2. Giáo án - Bài giảng >
  3. Tin học >

Chapter 11. JavaScript Events and the Browser

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (6.5 MB, 505 trang )


224



Part III  Integrating JavaScript into Design



element. Still, there’s nothing wrong with using it for simple scripts, as shown throughout the

book so far.

The DOM 0 event model includes several events that multiple Hypertext Markup Language

(HTML) tags raise in response to various user actions or state changes. Table 11-1 describes

each event.

Table 11-1  DOM



0 Events



Event Name



Description



onblur()



The element lost focus (that is, it is not selected by the user).



onchange()



The element has either changed (for example, a user typed into a text field)

or lost focus.



onclick()



The mouse clicked an element.



ondblclick()



The mouse double-clicked an element.



onfocus()



The element got focus.



onkeydown()



A keyboard key is pressed (as opposed to released) while the element

has focus.



onkeypress()



A keyboard key is pressed while the element has focus.



onkeyup()



A keyboard key is released while the element has focus.



onload()



The element is loaded (a document, a frameset, or an image).



onmousedown()



A mouse button is pressed.



onmousemove()



The mouse is moved.



onmouseout()



The mouse is moved off of or away from an element.



onmouseover()



The mouse is over an element.



onmouseup()



A mouse button is released.



onreset()



The form element is reset, such as when a user presses a form reset button.



onresize()



The window’s size is changed.



onselect()



The text of a form element is selected.



onsubmit()



The form is submitted.



onunload()



The document or frameset is unloaded.



Newer Event Models: W3C and Internet Explorer

The W3C codified an event model that allows powerful event handling, and almost all later

versions of major browsers support it with the notable exception of Internet Explorer prior

to version 9, which uses a different model. Because the standard W3C event model and the

earlier Internet Explorer event model differ, you must account for each in any JavaScript that

uses either event handling approach rather than only the approach provided by the DOM 0

event model.

Conceptually, the process of event handling is similar in the W3C model and Internet Explorer

models. In both models, you register the event first, associating a function with the event.







Chapter 11  JavaScript Events and the Browser



225



When a registered event gets triggered, the event’s function gets called. However, the location at which the event occurs is one important difference between them.

To understand this difference, imagine a document with a element and another

element in the body, for example, an . If a visitor moves the mouse over the image,

should the onmouseover() event be handled first within the , or within the ?

The two models diverge in determining where the event should be processed.

The W3C model supports two forms for locating where the event should be handled: Event

Capture and Event Bubbling. With Event Capture, the search for a handler begins at the top

level (the document level) and proceeds downward through the DOM tree to more specific

elements. If you used Event Capture in the example from the last paragraph, an event would

be processed first by the element and then by the element. Processing occurs

in exactly the reverse order for Event Bubbling; the element in which the event occurred gets

searched for a handler first, and the search proceeds upward from there.

As previously stated, the W3C model—and therefore all browsers that adhere to it (in other

words, all browsers except older versions of Internet Explorer)—can use both forms of event

handling (you learn about this soon), whereas older versions of Internet Explorer use only

Event Bubbling. With the W3C model, you register an event using the addEventListener()

method. With the earlier Internet Explorer model, you use attachEvent()for the same purpose. In practical terms, this means that you need to use both methods in every script you

write that handles events, choosing at runtime the one appropriate for the browser in which

the script is running. The basic structure of the addEventListener() method is this:

addEventListener(event,function,capture/bubble);



The capture/bubble parameter is a Boolean value, where true indicates that the event should

use top-down capturing and false indicates that the event should use bubbling. Here’s a typical call to the addEventListener() method for a Submit button. The call registers the submit

event, specifying a function named myFunction() (which would be defined elsewhere in the

code), and uses top-down event capturing:

window.addEventListener("submit",myFunction(),true);



To register the same event using bubbling, you write this:

window.addEventListener("submit",myFunction(),false);



The attachEvent() method used in the earlier Internet Explorer model doesn’t require the

third argument, because you don’t have to decide whether to use capturing or bubbling;

the earlier Internet Explorer model offers only bubbling.

Here’s an example of registering the submit event in earlier versions of Internet Explorer,

associating it with myFunction() by calling attachEvent():



226



Part III  Integrating JavaScript into Design

window.attachEvent("onsubmit",myFunction());



You might have noticed a subtle difference in the name of the event to which the event

handlers were added—submit, as opposed to onsubmit in the DOM Level 0 model. Many of

the events in the DOM Level 2 changed names. Table 11-2 shows the names of several DOM

Level 0 events and their W3C DOM Level 2 counterparts. Note that the DOM 2 events simply

remove the word “on” from the event name. (The earlier Internet Explorer model uses the

DOM 0 names.)

Table 11-2  DOM



0 and DOM Level 2 Events



DOM 0 Event



DOM 2 Event



onblur()



blur



onfocus()



focus



onchange()



change



onmouseover()



mouseover



onmouseout()



mouseout



onmousemove()



mousemove



onmousedown()



mousedown



onmouseup()



mouseup



onclick()



click



ondblclick()



dblclick



onkeydown()



keydown



onkeyup()



keyup



onkeypress()



keypress



onsubmit()



submit



onload()



load



onunload()



unload



Both the W3C and earlier Internet Explorer models include methods to remove event listeners. In the W3C model, the method is called removeEventListener() and takes the same three

arguments as addEventListener():

removeEventListener(event,function,capture/bubble)



The earlier Internet Explorer model uses detachEvent() for this same purpose:

detachEvent(event,function);



You might find it necessary to stop event handling from propagating upward or downward

after the initial event handler is executed. The W3C model uses the stopPropagation() method

for this purpose, whereas the earlier Internet Explorer model uses the cancelBubble property.

I provide an example of this behavior in the “Opening, Closing, and Resizing Windows” section later in this chapter.







Chapter 11  JavaScript Events and the Browser



227



A Generic Event Handler

Adding event listeners for each event that you need to handle quickly can become too

cumbersome. Instead, use a generic event handler for this purpose so that you can abstract

the cross-browser incompatibilities. Listing 11-1 shows a generic event handler. You can find

this code in the companion content, in the ehandler.js file in the Chapter11 folder.

Listing 11-1  A generic event handler.

var EHandler = {};

if (document.addEventListener) {

EHandler.add = function(element, eType, eFunc) {

if (eType == "load") {

if (typeof window.onload == "function") {

var existingOnload = window.onload;

window.onload = function() {

existingOnload();

eFunc();

} //end existing onload handler

} else {

window.onload = eFunc;

}

} else {

element.addEventListener(eType, eFunc, false);

}

};

EHandler.remove = function(element, eType, eFunc) {

element.removeEventListener(eType, eFunc, false);

};

}

else if (document.attachEvent) {

EHandler.add = function(element, eType, eFunc) {

if (eType == "load") {

if (typeof window.onload == "function") {

var existingOnload = window.onload;

window.onload = function() {

existingOnload();

eFunc();

} //end existing onload handler

} else {

window.onload = eFunc;

}

} else {

element.attachEvent("on" + eType, eFunc);

}

};

EHandler.remove = function(element, eType, eFunc) {

element.detachEvent("on" + eType, eFunc);

};

}



228



Part III  Integrating JavaScript into Design



This generic event handler creates an object called EHandler (which stands for event handler),

which then has two methods added to it, add()and remove(), both available in the W3C and

the earlier Internet Explorer models. The add method in each model determines whether the

event type is a load event, meaning that the function needs to be executed on page load. If

the function does, the add handler needs to determine whether any existing onload functions

are already defined. If they are, the handler must set the onload functions to run with the

newly defined function.

For the purposes of this chapter and the remainder of the book, I expect you to save this file

to an external JavaScript file called ehandler.js, and add the file into any JavaScript files in

need of an event handler. As a reminder, you can add an external JavaScript file like this:





Luckily, Windows Internet Explorer 9 uses the W3C compatible model; as that new browser

version becomes more popular in the market, attachEvent will slowly be replaced. However,

sites that support earlier browsers will still need to use the older Microsoft model for years to

come.

You can improve on this event handler script so that it is more suitable for situations you

might encounter when building more powerful JavaScript applications. (You can find more

information about this topic at John Resig’s website: http://ejohn.org/blog/flexible-javascriptevents/.) However, a better solution is to use a JavaScript framework or library, such as jQuery,

to abstract the event model even more.

More Information  I discuss in more depth jQuery and other JavaScript frameworks beginning with Chapter 19, “A Touch of AJAX.” For now, the simple event handler script presented in

this section suffices as an example in this book. For more advanced JavaScript programming using events, I recommend you use a library such as jQuery rather than the simple event handler

shown here.

The remainder of this chapter applies knowledge you gained about events as well as about

the Browser Object Model from Chapter 9, “The Browser Object Model”; the Document

Object Model from Chapter 10, “The Document Object Model”; and the syntax from the Part

I of the book, “JavaWhat? The Where, Why, and How of JavaScript.”



Detecting Visitor Information

JavaScript programming often requires browser detection—that is, the detection of which

browser a visitor to a website is using. For several years, browser detection was accomplished

largely by using the userAgent property of the navigator object. The userAgent property

is available through the navigator object and shows information about the user’s browser.

However, relying on the userAgent property is no longer recommended, because visitors can







Chapter 11  JavaScript Events and the Browser



229



so easily forge it. In addition, maintaining accurate userAgent information for every version of

every browser is incredibly difficult.

I personally use five different browsers of various versions. Maintaining an up-to-date list

of which browser supports which feature for just my handful of browsers is even too cumbersome. Imagine what it would be like trying to maintain JavaScript code that accounted for

every browser and every version of that browser! It would be virtually impossible. And that

doesn’t even take fake (either for malicious or other purposes) userAgent strings into account!

So I discuss the userAgent property only briefly and then move on to show the newer (and

much better) methods for determining whether the JavaScript that you’re using will work in

the visitor’s browser. This section also examines other properties of the navigator object that

are helpful, if not 100 percent reliable.



A Brief Look at the userAgent Property

As mentioned, the userAgent string is a property of the navigator object. It contains information about the user’s browser. To show the userAgent information, just type this in your

browser:

javascript:alert(navigator.userAgent);



If you’re using Windows Internet Explorer 7, you might see an alert like the one in Figure

11-1.



Figure 11-1  The userAgent property of the navigator object.



Other browsers report different information. For example, one version of Firefox reports itself

as this:

Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3



This string usually changes as each new version of a browser is released. If you tried to track

each released version of each browser, and then tried to track which version of each browser

supported which feature of JavaScript, you’d be spending a lot of time (and possibly a lot of

your employer’s or client’s time as well) maintaining that list.



230



Part III  Integrating JavaScript into Design



A much better way to track what is and is not supported in the visitor’s browser is a technique known as feature testing, discussed in the next section.



Feature Testing

Using feature testing, sometimes referred to as object detection, a JavaScript program attempts

to detect whether the browser that is visiting the webpage supports a given feature.

Fortunately, you don’t have to test whether every function and method you want to use are

supported in the visitor’s browser. The DOM Level 0 model and other earlier functions of

JavaScript are so widely supported, and their cross-browser implementations are so close,

that testing for particular features isn’t necessary. However, you must still test whether

JavaScript is available, because not all browsers support JavaScript, and not all visitors have

the JavaScript support option turned on.

The typeof operator is the primary mechanism used to implement feature testing. In general

terms, you use the operator as follows:

if (typeof featureName != "undefined") {

// Do Something Fun With That Feature

}



Try an example. To test for the existence of the getElementById() method, which indicates

that the browser supports the more advanced DOM interface, you might use this code:

if (typeof document.getElementById != "undefined") {

alert("getelembyid is supported");

} else {

alert("no getelembyid support");

}



You may be tempted to skip the use of typeof within the test, and you may see examples on

the web where a feature test looks like this:

if (document.getElementById) { ... }



Unfortunately, this method of feature testing isn’t as reliable as the typeof test. The problem

is that the shorter syntax runs the method. When you omit typeof, the method or property

being tested might return 0 or false by default, which makes the test fail; in other words, it

appears that the browser doesn’t support that method or property—when it actually does.

Therefore, testing using typeof is safer and more reliable.







Chapter 11  JavaScript Events and the Browser



231



Another way to accomplish this task that looks a bit cleaner is to use the ternary operator to

set a flag early in the code. Script that runs later on can use a standard if conditional to check

the flag, as shown here:

// test for getElmementById, set getElem to the result

var getElem = (typeof document.getElementById == "function") ? true : false;

// now you can test getElem

if (getElem) {

// We know getElementById is supported,

// so let's use it.

}



Keeping JavaScript Away from Older Browsers

One of the most discouraging problems you face as a web programmer is dealing with the

presence of older browsers. Writing webpages that have any sort of current look and feel

and still display reasonably well in older browsers is becoming increasingly difficult. What

defines an older browser? Ask three different web designers and you’ll probably get three

different answers. To me, an older browser is one that is more than three years old, though

I lean toward saying two years rather than three.

By this definition, then, Firefox 1.0 is an older browser, even though most webpages display

fine, and almost all the JavaScript code you write will probably work perfectly in that version

of Firefox. A more general rule is that any version of Internet Explorer or Netscape earlier

than version 5 tends to have many, many quirks that web designers must take into account.

Given the depressing fact that browsers even older than Microsoft Internet Explorer 5.0 are

sometimes still in use, accepting that your code might fail in these browsers is a good idea.

You can try to make your code fail gracefully; however, doing even that may not always be

possible. I recently installed a copy of Netscape 3 (which, if I remember correctly, was released

in 1997). The browser had trouble with most JavaScript, and also had problems displaying

HTML and CSS (Cascading Style Sheets) on basic websites. This was to be expected, because

that version of Netscape was released well before many of the standards in use today were

codified. The point is that no matter how hard you try, your website is probably never going

to fail gracefully in really old versions of browsers. I recommend that you choose a minimum

browser level to support—and design for that target, keeping in mind that the later the minimum level, the more visitors you shut out of the site. The goal is to strike a balance between

being a welcoming site and being a cutting-edge site.

There are two primary techniques for keeping JavaScript away from older browsers: inserting

HTML-style comments into the JavaScript, and using the tags.

To use HTML comments in your JavaScript, you surround them within marks, as

shown in this example:



Download from Wow! eBook



232



Part III  Integrating JavaScript into Design





Unfortunately, not every browser obeys these HTML comments, so you still encounter errors

sometimes. This style of commenting, or protection, is becoming less and less common. As

the old browsers slowly get cycled out, this type of workaround isn’t really necessary.

Whatever falls between the tag pairs is displayed only when the page

detects no JavaScript support in the browser. Here’s an example of

This Web Page Requires JavaScript







When visitors whose browsers don’t accept JavaScript visit the webpage, they see whatever

falls between the tag pair. In this example, they’d see the text “This

Web Page Requires JavaScript.” Note that using
Xem Thêm
Tải bản đầy đủ (.pdf) (505 trang)

×