6.4. Preventing Default Event ActionsIt is not uncommon to script an event handler to execute statements immediately prior to an element carrying out its normal activity in response to a user action. For example, a form's text field validation typically operates in response to the onsubmit event of the form element. Without any kind of event handler, a form element obeys the submit-type input button, and sends the form's contents to the URI specified by the action attribute. But if you bind an onsubmit event handler to that form element, and if the validation routines spot an error (e.g., a required text box is empty), the script can alert the user and prevent the default submission action from taking place. Many other elements and their events can benefit from this script technique. You have several ways prevent an element's default action, depending on the event binding style you use and the browsers you need to support. Some techniques work across all scriptable browsers. 6.4.1. Setting the return ValueWhen your event handlers are in the form of element attributes, you can cancel the element's default action if the last statement of the event handler assignment statement evaluates to return false. This is different from simply having the handler function end with return false. The return statement must be in the value assigned to the event handler attribute. The easiest way to implement this approach is to include a return statement in the event handler itself, while the function invoked by the handler returns true or false based on its calculations. For example, if a form requires validation prior to submission, you can have the onsubmit event handler invoke the validation routine. If the routine finds a problem somewhere, it returns false and the submission is canceled because the entire event handler expression evaluates to return false; otherwise, the function returns true and the submission proceeds as usual. Such a form element looks like the following: <form method="POST" action="http://www.megaCo.com/cgi-bin/entry" onsubmit="return validate(this);"> This technique also allows you to have a link navigate to a hardcoded URL for nonscriptable browsers, but execute a script when the user has a scriptable browser: <a href="someotherURL.htm" onclick="doNavigation( ); return false;">...</a> Here, the return false statement is set as the final statement of the event handler; it does not have to trouble the called function for a return value because all scriptable browsers are to follow the scripted navigation path. If you use object property event binding, the coding is not altogether straightforward. By and large, IE lets the return statement of the function govern the default execution, provided you return true or false. Netscape 6.2, however, doesn't obey return statements for this type of event binding due to a bug that is fixed in later versions. 6.4.2. The event.returnValue Property (IE 5 and Later)Starting with Version 5 (Windows and Mac), IE's event object has a Boolean property, returnValue, that controls whether the element's default action occurs. The default value of the property is true. But to prevent the default action, your function script sets its value to false. The following IE-only function could be invoked from the onkeypress event handler of a text box (onkeypress="numberPlease( );" or txtBoxRef.onkeypress=numberPlease;). Its job is to let only numbers appear in the field by preventing the onkeypress event from performing its default action for other characters: function numberPlease( ) { var charCode = event.keyCode; if (charCode < 48 || charCode > 57) { alert("Only whole numbers are allowed."); event.returnValue = false; } } Be careful not to confuse the event.returnValue property with the purpose of the JavaScript return statement. Use the former to control an event target's default behavior; use the latter when a function must return a value to a calling statement. 6.4.3. W3C preventDefault( ) Method (Netscape 6 and Later)Instead of using a property of its event object for this purpose, the W3C event model gives the event object the preventDefault( ) method. You can invoke this method in an event listener function to stand in the way of the event continuing to the element. The syntax for its use is not far different from the IE returnValue property. The following function is a W3C version of the numbers-only real-time input checker. Due to an egregious bug in early versions of Netscape 6, however, the preventDefault( ) method works reliably only on event listeners that are added by way of tag attributes. Therefore, for the following function to do its job effectively, it should be invoked from an input element tag's attribute (onkeypress="numberPlease(event);"): function numberPlease(evt) { var charCode = evt.charCode; if (charCode < 48 || charCode > 57) { alert("Only whole numbers are allowed."); evt.preventDefault( ); } } 6.4.4. Cross-Browser TechniquesWith the preventDefault( ) bug persisting through so many Netscape 6 editions, it is safest to stick with element tag attribute binding for preventing default actions. This means that the return statement becomes part of the value assigned to the attribute (e.g., onkeypress="return numberPlease(event)"). For good measure, the following function demonstrates branching techniques that can be used in the future for both tag attribute and object property event bindings. A little bit of additional event key code detection allows helpful noncharacter keys (arrows, Tab, and Backspace, for example) to perform their normal jobs (in Netscape 6 and later, the charCode property for noncharacter keys is 0). The function is a cross-browser, backward-compatible version of the text box filter function shown earlier. This version works even with Navigator 4: function numberPlease(evt) { evt = (evt) ? evt : ((event) ? event : null); if (evt) { var charCode = (evt.charCode || evt.charCode == 0) ? evt.charCode : ((evt.keyCode) ? evt.keyCode : evt.which); if (charCode > 13 && (charCode < 48 || charCode > 57)) { alert("Only whole numbers are allowed."); if (evt.returnValue) { evt.returnValue = false; } else if (evt.preventDefault) { evt.preventDefault( ); } else { return false; } } } } Of course, for use with tag attribute binding, the innermost segment could be compressed to a single return false statement after the alert. Copyright © 2003 O'Reilly & Associates. All rights reserved. |
|