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

JavaScript Bible, Gold Edition part 89 ppsx

10 234 0

Đ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

Nội dung

728 Part III ✦ Document Objects Reference 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 document and a form — are given capture-type event listen- ers for the click event. The document object 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 function when the event starts bubbling back up. Many of the event handler functions dynamically read the eventPhase property 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) { 729 Chapter 29 ✦ Event Objects case 1: return “CAPTURING” break 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 cancelBubble property of the IE4+ event object 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 730 Part III ✦ Document Objects Reference 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” 731 Chapter 29 ✦ Event Objects break default: 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 732 Part III ✦ Document Objects Reference 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 event object is accessible as a property of the window object: window.event But, as you are well aware, the window part of references is optional, so your scripts can treat the event object as if it were a global reference: event.propertyName Thus, any statement in an event handler function can access the event object without any special preparation or initializations. 733 Chapter 29 ✦ Event Objects NN4+ (W3C) event object references 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 event as 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 event reference 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 event or, more com- monly, evt. When working with cross-browser scripts, avoid using event as a parameter variable name so as not to interfere with IE’s event property. 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. 734 Part III ✦ Document Objects Reference 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 event object: 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.event object is available and assigns it to the evt variable; finally, if the browser doesn’t know about an event object, the evt variable is made an empty string. Processing continues only if evt contains 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 actions 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 Property/Action NN4 IE4+ NN6 Target element target srcElement target Event type type type type X coordinate in element n/a † offsetX n/a † Y coordinate in element n/a † offsetY n/a † X coordinate in layerX x layerX positioned element Y coordinate in layerY y layerY 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 735 Chapter 29 ✦ Event Objects Property/Action NN4 IE4+ NN6 Y coordinate on screen screenY screenY screenY Mouse button which button button Keyboard key which keyCode keyCode 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 modifiers and 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. 736 Part III ✦ Document Objects Reference 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.userAgent detection. 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 737 Chapter 29 ✦ Event Objects passed as a parameter (evt) whose modifiers property is Bitwise ANDed with an Event object constant for each modifier key. For IE4+ and NN6, the script checks 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 . Propagation</TITLE> <SCRIPT LANGUAGE= JavaScript > function init() { // using old syntax to assign bubble-type event handlers window.onclick = winEvent Continued 730 Part III ✦ Document Objects Reference Listing. checked. 736 Part III ✦ Document Objects Reference Listing 29-10: Checking Events for Modifier Keys <HTML> <HEAD> <TITLE>Event Modifiers</TITLE> <SCRIPT LANGUAGE= JavaScript > function. 728 Part III ✦ Document Objects Reference Listing 29-7 is a simplified example that demonstrates how

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