/* * Name: * event_handler.js * * Description: * Defines generic, cross-browser functions for dynamically registering and unregistering * JavaScript events on HTML DOM objects. * * Pre-conditions: * None * * Post-conditions: * Defines the following functions: * - registerEvent Associate a JavaScript event with an object. * - unregisterEvent Dissociate a JavaScript event from an object. * - getEventTarget Obtain the target of an event, given its implicit event argument. * * Log: * Randall Betta 08/25/2006 * - Creation * */ /* * Name: * registerEvent * * Description: * Attaches a JavaScript event to the given HTML DOM element. In event models that support * both options, events are fired in the bubbling phase by this function, not the capturing * phase. Note that, under some schemes, multiple events (even duplicates) may be assigned to * an object, and all will fire, so be sure to unregister any unneeded events! * * Pre-conditions: * obj REQUIRED The DOM object to which the given event should be attached. * eventName REQUIRED The name of the event as a string. May optionally include the on- prefix. * handler REQUIRED A callback for the handler function. (NOT a string, NO parentheses!) * * Post-conditions: * Returns true on successful event attachment, false otherwise. * * Log: * Randall Betta 08/25/2006 * - Creation * */ function registerEvent(obj, eventName, handler) { var eventWithOn; var eventWithoutOn; // Define two forms of the event name: one with a leading on- prefix, the other without it. eventWithOn = (eventName.match(/^on/)) ? eventName : 'on' + eventName; eventWithoutOn = eventName.replace(/^on/, ''); // Determine if the browser supports the Microsoft model or the W3C model for event attachment. if (obj.addEventListener) { // If: the W3C addEventListener method is defined. // // Use the W3C model. // // The event names should be lowercase without the on- prefix in W3C-compliant implementations. eventName = eventWithoutOn.toLowerCase(); // Fire events during the bubbling phase; this must match the detachment function! obj.addEventListener(eventName, handler, false); return true; } else if (obj.attachEvent) { // Else if: the Microsoft attachEvent method is defined. // // Use the Microsoft model. // // The event names should be lowercase with the on- prefix in Microsoft's implementation. eventName = eventWithOn.toLowerCase(); obj.attachEvent(eventName, handler); return true; } else { // Else: fall back on the traditional model. // // Use the traditional event registration model. // // The event names should be lowercase with the on- prefix in the traditional implementation. eventName = eventWithOn.toLowerCase(); obj[eventName] = handler; return true; } // End else: use the traditional model. } // End function: registerEvent /* * Name: * unregisterEvent * * Description: * Detaches a JavaScript event from the given HTML DOM element. * * Pre-conditions: * obj REQUIRED The DOM object from which to remove the given event. * eventName REQUIRED The name of the event as a string. May optionally include the on- prefix. * handler REQUIRED A callback for the handler function. (NOT a string, NO parentheses!) * * Post-conditions: * Returns true on successful event detachment, false otherwise. * * Log: * Randall Betta 08/25/2006 * - Creation * */ function unregisterEvent (obj, eventName, handler) { // Define two forms of the event name: one with a leading on- prefix, the other without it. eventWithOn = (eventName.match(/^on/)) ? eventName : 'on' + eventName; eventWithoutOn = eventName.replace(/^on/, ''); // Determine if the browser supports the Microsoft model or the W3C model for event detachment. if (obj.removeEventListener) { // If: the W3C model is supported. // // Use the W3C event detachment model. // // The event names should be lowercase without the on- prefix in the W3C implementation. eventName = eventWithoutOn.toLowerCase(); // The original attachment function is presumed here to have // specified that events fire during the bubbling phase. This must // match the actual value used during event attachment! obj.removeEventListener(eventName, handler, false); return true; } else if (obj.detachEvent) { // Else if: the Microsoft model is supported. // // Use the Microsoft event detachment model. // // The event names should be lowercase with the on- prefix in the Microsoft implementation. eventName = eventWithOn.toLowerCase(); obj.detachEvent(eventName, handler); return true; } else { // Fall back on the traditional event model. // // Use the traditional model. // // The event names should be lowercase with the on- prefix in the traditional implementation. eventName = eventWithOn.toLowerCase(); obj[eventName] = null; return true; } // End else: use the traditional model. } // End function: unregisterEvent /* * Name: * getEventTarget * * Description: * Every event handler should take a single argument, which will either be made null by IE or set * to an event object by W3C-compliant browsers. Given this object, this function returns a reference * to the target element of the event. * * Pre-conditions: * eventObj REQUIRED The implicit event object passed to an event handler (may possibly be null). * * Post-conditions: * Returns a reference to the target of the event whose implicit event object is passed in as an argument. * Returns false on failure. * * Log: * Randall Betta 08/25/2006 * - Creation * */ function getEventTarget(eventObj) { var targetObj; // // Obtain a reference to the proper event-describing object. // // Under Internet Explorer, no implicit event object is passed to event handler. Instead, the // window.event object holds data for the last event to be raised. eventObj = (eventObj) ? eventObj : window.event; if (!eventObj) { // If: the event object can't be found. // Indicate failure. return false; } // End if: the event object can't be found. // // The event-describing object is known by this point. Obtain a reference to the DOM object that // was the original target of the event. // // W3C-compliant browsers call the event's object "target." IE calls it "srcElement." targetObj = (eventObj.target) ? eventObj.target : eventObj.srcElement; if (!targetObj) { // If: the target object can't be found. // Indicate failure. return false; } // End if: the target object can't be found. // Under Safari, a bug can cause events that fire on text element to store their target element // as the text node in the DOM, rather than its containing HTML node. Fix this. targetObj = (targetObj.nodeType == 3) ? targetObj.parentNode : targetObj; return targetObj; } // End function: getEventTarget