1. Trang chủ
  2. » Công Nghệ Thông Tin

JavaScript Bible, Gold Edition part 89 ppsx

10 234 0
Tài liệu đã được kiểm tra trùng lặp

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

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 86,61 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

For the form object, however, the capture-type event listener is directed to one function, while a bubble-type listener for the same object is directed at a separate function.. Listing 2

Trang 1

Listing 29-7 is a simplified example that demonstrates how a click event aimed at

a button can be both captured and allowed to bubble Most event handling func-tions are assigned inside the init()function Borrowing code from Listing 29-5, event handlers are assigned to the window, document, and BODY objects as prop-erty assignments These are automatically treated as bubble-type event listeners Next, two objects — the documentand a form — are given capture-type event listen-ers for the clickevent The documentobject event listener invokes the same function as the bubble-type event handler (the alert text includes some asterisks to remind you that it is the same alert being displayed in both the capture and bubble phases of the event) For the form object, however, the capture-type event listener

is directed to one function, while a bubble-type listener for the same object is directed at a separate function In other words, the form object invokes one func-tion as the event trickles down to the target and another funcfunc-tion when the event starts bubbling back up Many of the event handler functions dynamically read the

eventPhaseproperty of the event object to reveal which phase of event propaga-tion is in force at the instance the event handler is invoked

Listing 29-7: NN6 Event Capture and Bubble

<HTML>

<HEAD>

<TITLE>W3C DOM Event Propagation</TITLE>

<SCRIPT LANGUAGE=”JavaScript”>

function init() { // using old syntax to assign bubble-type event handlers window.onclick = winEvent

document.onclick = docEvent document.body.onclick = docBodEvent // turn on click event capture for two objects document.addEventListener(“click”, docEvent, true) document.forms[0].addEventListener(“click”, formCaptureEvent, true) // set event listener for bubble

document.forms[0].addEventListener(“click”, formBubbleEvent, false) }

function winEvent(evt) { alert(“Event is now at the window object level (“ + getPhase(evt) + “).”) }

function docEvent(evt) { alert(“Event is now at the **document** object level (“ + getPhase(evt) +

“).”) } function docBodEvent(evt) { alert(“Event is now at the BODY level (“ + getPhase(evt) + “).”) }

function formCaptureEvent(evt) { alert(“This alert triggered by FORM only on CAPTURE.”) }

function formBubbleEvent(evt) { alert(“This alert triggered by FORM only on BUBBLE.”) }

// reveal event phase of current event object function getPhase(evt) {

switch (evt.eventPhase) {

Trang 2

case 2:

return “AT TARGET”

break

case 3:

return “BUBBLING”

break

default:

return “”

}

}

</SCRIPT>

</HEAD>

<BODY onLoad=”init()”>

<H1>W3C DOM Event Propagation</H1>

<HR>

<FORM>

<INPUT TYPE=”button” VALUE=”Button ‘main1’” NAME=”main1” onClick=

“alert(‘Event is now at the button object level (‘ + getPhase(event) +

‘).’)”>

</FORM>

</BODY>

</HTML>

If you want to remove event capture after it has been enabled, use the

removeEventListener()method on the same object as the event listener that

was originally added (see Chapter 15) And, because multiple event listeners can be

attached to the same object, specify the exact same three parameters to the

removeEventListener()method as applied to the addEventListener()method

Preventing NN6 event bubbling or capture

Corresponding to the cancelBubbleproperty of the IE4+ eventobject is an

event object method in the W3C DOM The method that prevents propagation in

any event phase is the stopPropagation()method Invoke this method anywhere

within an event listener handler function The current function executes to

comple-tion, but the event propagates no further

Listing 29-8 extends the example of Listing 29-7 to include two checkboxes that

let you stop propagation type at the FORM element in your choice of the capture or

bubble phase

Listing 29-8: Preventing Bubble and Capture

<HTML>

<HEAD>

<TITLE>W3C DOM Event Propagation</TITLE>

<SCRIPT LANGUAGE=”JavaScript”>

function init() {

// using old syntax to assign bubble-type event handlers

window.onclick = winEvent

Continued

Trang 3

Listing 29-8 (continued)

document.onclick = docEvent document.body.onclick = docBodEvent // turn on click event capture for two objects document.addEventListener(“click”, docEvent, true) document.forms[0].addEventListener(“click”, formCaptureEvent, true) // set event listener for bubble

document.forms[0].addEventListener(“click”, formBubbleEvent, false) }

function winEvent(evt) {

if (evt.target.type == “button”) { alert(“Event is now at the window object level (“ + getPhase(evt) + “).”)

} } function docEvent(evt) {

if (evt.target.type == “button”) { alert(“Event is now at the **document** object level (“ + getPhase(evt) + “).”)

} } function docBodEvent(evt) {

if (evt.target.type == “button”) { alert(“Event is now at the BODY level (“ + getPhase(evt) + “).”) }

} function formCaptureEvent(evt) {

if (evt.target.type == “button”) { alert(“This alert triggered by FORM only on CAPTURE.”)

if (document.forms[0].stopAllProp.checked) { evt.stopPropagation()

} } } function formBubbleEvent(evt) {

if (evt.target.type == “button”) { alert(“This alert triggered by FORM only on BUBBLE.”)

if (document.forms[0].stopDuringBubble.checked) { evt.preventBubble()

} }

} // reveal event phase of current event object function getPhase(evt) {

switch (evt.eventPhase) { case 1:

return “CAPTURING”

break case 2:

return “AT TARGET”

break case 3:

return “BUBBLING”

Trang 4

return “”

}

}

</SCRIPT>

</HEAD>

<BODY onLoad=”init()”>

<H1>W3C DOM Event Propagation</H1>

<HR>

<FORM>

<INPUT TYPE=”checkbox” NAME=”stopAllProp”>Stop all propagation at FORM<BR>

<INPUT TYPE=”checkbox” NAME=”stopDuringBubble”>Prevent bubbling past FORM

<HR>

<INPUT TYPE=”button” VALUE=”Button ‘main1’” NAME=”main1” onClick=

“alert(‘Event is now at the button object level (‘ + getPhase(event) +

‘).’)”>

</FORM>

</BODY>

</HTML>

Redirecting NN6 events

The mechanism for sending an event to an object outside the normal

propaga-tion pattern in NN6 is similar to that of IE4+, although with different syntax In place

of the IE4+ fireEvent()method, NN6 uses the W3C DOM dispatchEvent()

method The sole parameter of the method is an event object, such as the current

event object Listing 29-9 is the same as the IE4+ Listing 29-6, but with just a few

modifications to run in the NN6 event model Notice that the dispatchEvent()

method passes the current event object as its sole parameter

Listing 29-9: Cancelling and Redirecting Events in NN6+

<HTML onClick=”revealEvent(‘HTML’, event)”>

<HEAD>

<TITLE>Event Cancelling & Redirecting</TITLE>

<SCRIPT LANGUAGE=”JavaScript”>

// display alert with event object info

function revealEvent(elem, evt) {

var msg = “Event (from “ + evt.target.tagName + “ at “

msg += evt.clientX + “,” + evt.clientY + “) is now at the “

msg += elem + “ element.”

alert(msg)

}

function init() {

document.onclick = docEvent

document.body.onclick = docBodEvent

}

function docEvent(evt) {

revealEvent(“document”, evt)

}

Continued

Trang 5

Listing 29-9 (continued)

function docBodEvent(evt) { revealEvent(“BODY”, evt) }

function buttonEvent(form, evt) { revealEvent(“BUTTON”, evt) // redirect if checked

if (form.redirect.checked) { document.body.dispatchEvent(evt) }

// cancel if checked

if (form.bubbleCancelState.checked) { evt.stopPropagation()

} }

</SCRIPT>

</HEAD>

<BODY onLoad=”init()”>

<H1>Event Cancelling & Redirecting</H1>

<HR>

<FORM onClick=”revealEvent(‘FORM’, event)”>

<P><BUTTON NAME=”main1” onClick=”buttonEvent(this.form, event)”>

Button ‘main1’

</BUTTON></P>

<P><INPUT TYPE=”checkbox” NAME=”bubbleCancelState”

onClick=”event.stopPropagation()”>Cancel Bubbling at BUTTON<BR>

<INPUT TYPE=”checkbox” NAME=”redirect” onClick=”event.stopPropagation()”> Redirect Event to BODY</P>

</FORM>

</BODY>

</HTML>

Referencing the event object

While there may be essentially three different event object models in today’s browsers, the way your scripts access those objects is divided into two camps: the

IE way; and the NN (and W3C) way I start with the simpler, IE way

IE4+ event object references

In IE4+, the eventobject is accessible as a property of the windowobject: window.event

But, as you are well aware, the windowpart of references is optional, so your scripts can treat the eventobject as if it were a global reference:

event.propertyName

Thus, any statement in an event handler function can access the eventobject without any special preparation or initializations

Trang 6

The situation is a bit more complicated in the NN4+ event model In some cases

you must explicitly pass the event object as a parameter to an event handler

func-tion, while in other cases, the event object is delivered as a parameter

automati-cally The difference depends on how the event handler function is bound to the

object

Using the original way of binding event handlers to objects — via an attribute in

the element’s tag — you must specify the event object as a parameter by passing

eventas a parameter, as in

onClick=”doSomething(event)”

This is the only time in the NN4+ model that you see an explicit reference to the

event(lowercase “e”) object as if it were a global reference This reference does

not work in any other context — only as a parameter to an event handler function If

you have multiple parameters, the eventreference can go in any order, but I tend

to put it last:

onClick=”doSomething(this, event)”

The function definition that is bound to the element should therefore have a

parameter variable in place to “catch” the event object parameter:

function doSomething(widget, evt) { }

You have no restrictions on how you name this parameter variable In some

examples of this book, you may see the variable assigned as eventor, more

com-monly, evt When working with cross-browser scripts, avoid using eventas a

parameter variable name so as not to interfere with IE’s eventproperty

Other ways of binding event handler functions to objects — via property

assign-ments and the addEventListener()method in NN6+ — assign references of those

handlers to the desired objects in the document, as in either of the following:

document.forms[0].someButton.onclick = doSomething

document.getElementById(“myButton”).addEventListener(“click”, doSomething, false)

Event binding through these approaches prevents explicit passage of your own

parameters to the invoked functions But the NN4+ browsers automatically pass as

the sole parameter a reference to the event object created in response to the user

or system action that triggered the event This means that your functions should

“receive” the passed event object in a parameter variable:

function doSomething(evt) { }

Recall that the event object contains a reference to the object that was the target

of the event From that, you can access any properties of that object, such as the

form object that contains a form control object

You can see the way the event object is passed as a parameter in Listing 29-9 For

all event handlers that are assigned by reference (both to an event handler property

of an object and to an addEventListener()method call), the functions have a

parameter variable in place to act as a reference to the event object for statements

within the function If you need to invoke other functions from there, you can pass

the event object reference further along as needed The event object retains its

prop-erties as long as the chain of execution triggered by the event action continues

Trang 7

event Object Compatibility

Despite the incompatible ways that NN and IE event objects arrive at an event handler function, you can easily stuff the object into one variable that both browser types can use For example, the following function fragment receives an event object from NN but also accommodates the IE eventobject:

function doSomething(evt) { evt = (evt) ? evt : (window.event) ? window.event : “”

if (evt) { // browser has an event to process

} }

If an event object arrives as a parameter, it continues to be available as evt; but

if not, the function makes sure that a window.eventobject is available and assigns

it to the evtvariable; finally, if the browser doesn’t know about an eventobject, the evtvariable is made an empty string Processing continues only if evtcontains

an event object

That’s the easy part The madness comes in the details: reading properties of the event object when the property names can vary widely across the three event object models Sections later in this chapter provide details of each property and method of all three event object models, but seeing an overview of the property ter-minology on a comparative basis is helpful Table 29-2 lists the common informa-tion bits and acinforma-tions you are likely to want from an event object and the property

or method names used in the three event object models

Table 29-2 Common event Object Properties and Methods

Target element target srcElement target

X coordinate in element n/a † offsetX n/a †

Y coordinate in element n/a † offsetY n/a †

positioned element

positioned element

X coordinate on page pageX n/a † pageX

Y coordinate on page pageY n/a † pageY

X coordinate in window n/a clientX clientX

Y coordinate in window n/a clientY clientY

X coordinate on screen screenX screenX screenX

Trang 8

Y coordinate on screen screenY screenY screenY

Shift key pressed modifiers shiftKey shiftKey

Alt key pressed modifiers altKey altKey

Ctrl key pressed modifiers ctrlKey ctrlKey

Previous Element n/a fromElement relatedTarget

Next Element n/a toElement relatedTarget

Cancel bubbling n/a cancelBubble preventBubble()

Prevent default action return false returnValue preventDefault()

†Value can be derived through calculations with other properties.

As you can see in Table 29-2, properties for the IE4+ and NN6 event objects have

a lot in common This is good news, especially as the installed base of NN4 users

diminishes over time The primary incompatibility is how to reference the element

that is the intended target of the event This, too, can be branched in your code to

achieve a common variable that references the element For example, embedded

within the previous function fragment can be a statement, such as the following:

var elem = (evt.target) ? evt.target : evt.srcElement

Each event model has additional properties that are not shared by the other

Details about these are covered in the rest of this chapter

Dueling Event Models

Despite the sometimes widely divergent ways event object models treat their

properties, accommodating a wide range of browsers for event manipulation is not

difficult In this section, you see two scripts that examine important event

proper-ties The first script reveals which, if any, modifier keys are held down during an

event; the second script extracts the codes for both mouse buttons and keyboard

keys Both scripts work with all browsers that have event objects, including NN4 If

your audience no longer uses NN4, you can eliminate the code branches that

sup-port it

Cross-platform modifier key check

Listing 29-10 demonstrates branching techniques for examining the modifier

key(s) being held down while an event fires Details of the event object properties,

such as modifiersand altKey, can be found later in this chapter To see the page

in action, click a link, type into a text box, and click a button while holding down

any combination of modifier keys A series of four checkboxes representing the four

modifier keys is at the bottom As you click or type, the checkbox(es) of the

pressed modifier key(s) become checked

Trang 9

Listing 29-10: Checking Events for Modifier Keys

<HTML>

<HEAD>

<TITLE>Event Modifiers</TITLE>

<SCRIPT LANGUAGE=”JavaScript”>

function checkMods(evt) { evt = (evt) ? evt : (window.event) ? window.event : “”

if (evt) { var elem = (evt.target) ? evt.target : evt.srcElement var form = document.output

if (evt.modifiers) { form.modifier[0].checked = evt.modifiers & Event.ALT_MASK form.modifier[1].checked = evt.modifiers & Event.CONTROL_MASK form.modifier[2].checked = evt.modifiers & Event.SHIFT_MASK form.modifier[3].checked = evt.modifiers & Event.META_MASK } else {

form.modifier[0].checked = evt.altKey form.modifier[1].checked = evt.ctrlKey form.modifier[2].checked = evt.shiftKey form.modifier[3].checked = false }

} return false }

</SCRIPT>

</HEAD>

<BODY>

<H1>Event Modifiers</H1>

<HR>

<P>Hold one or more modifier keys and click on

<A HREF=”javascript:void(0)” onMouseDown=”return checkMods(event)”>

this link</A> to see which keys you are holding.</P>

<FORM NAME=”output”>

<P>Enter some text with uppercase and lowercase letters:

<INPUT TYPE=”text” SIZE=40 onKeyUp=”checkMods(event)”></P>

<P><INPUT TYPE=”button” VALUE=”Click Here With Modifier Keys”

onClick=”checkMods(event)”></P>

<P>

<INPUT TYPE=”checkbox” NAME=”modifier”>Alt

<INPUT TYPE=”checkbox” NAME=”modifier”>Control

<INPUT TYPE=”checkbox” NAME=”modifier”>Shift

<INPUT TYPE=”checkbox” NAME=”modifier”>Meta

</P>

</FORM>

</BODY>

</HTML>

Because all three event handlers call the same checkMods()function, branching

is needed only in this function Notice, though, that branching is done by object detection, rather than navigator.userAgentdetection This method makes the most sense for this example, because the scripts rely on the existence of particular objects and properties for their proper execution For NN4, the event object is

Trang 10

the event object property for each of three modifiers.

Cross-platform key capture

To demonstrate keyboard events in both browsers, Listing 29-11 captures the

key character being typed into a text box, as well as the mouse button used to click

a button As with Listing 29-10, NN4 has a very different way of getting this

informa-tion compared to IE4+ and NN6 In this arena, however, NN6 continues to support

the NN4 syntax as well, so you can use the old or new syntax as you like Whereas

NN4 combines the features of key character code and mouse button into one event

object property (depending upon the event type), newer browsers have entirely

separate properties for these values Listing 29-11 is written such that NN6 follows

the NN4 syntax path, but even if the NN4 syntax should disappear in a future NN

version, the browser would follow the new syntax path without blinking an eye

Listing 29-11: Checking Events for Key and Mouse Button

Pressed

<HTML>

<HEAD>

<TITLE>Button and Key Properties</TITLE>

<SCRIPT LANGUAGE=”JavaScript”>

function checkWhich(evt) {

evt = (evt) ? evt : (window.event) ? window.event : “”

if (evt) {

var thingPressed = “”

var elem = (evt.target) ? evt.target : evt.srcElement

if (evt.which) {

thingPressed = evt.which

} else {

if (elem.type == “textarea”) {

thingPressed = evt.keyCode } else if (elem.type == “button”) {

thingPressed = evt.button }

}

status = thingPressed

}

return false

}

</SCRIPT>

</HEAD>

<BODY>

<H1>Button and Key Properties</H1> (results in the status bar)

<HR>

<FORM>

<P>Mouse down atop this

<INPUT TYPE=”button” VALUE=”Button” onMouseDown=”checkWhich(event)”>

this link</A> or this

<INPUT TYPE=”button” VALUE=”Button” onMouseDown=”checkWhich(event)”>

Continued

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