Once a document gets loaded, JavaScript uses a host of events for interacting with the user. The nature of this interaction is asynchronous because we do not know the sequence of input that the user can provide in advance and we simply need to wait for input from the user. Once the user provides an input, we can use events to detect the type of input and then act upon the input.
Simply put, an event is an occurrence of a specific action. As an example, if the user were to click the mouse, then this would constitute an action. To make the interaction more meaningful, the JavaScript program must act when an event occurs and this is where, we need an event handler. An event handler is usually a function that gets invoked when the event-of-interest occurs.
Since events can happen in association with various elements of an HTML page, it is usually more meaningful to explicitly attach an event to a specific element/object. Let us consider an example. When the user clicks a mouse, she can click the mouse on a link and in this case, the link element becomes the object of the mouseclick. Along the same lines, the user can click the mouse on an image (instead of a link) and in this case, the image becomes the object of the event. Thus, besides events and handlers, the third important associated concept is that of of the object associated with an event.
Like implementation of browser-related methods, browsers from different vendors have not been consistent in terms of providing methods to define registration and handling of events. This motivated W3C to provide a specification that defines a common interface for registration and handling of events; the current speficitaion is Document Object Model (DOM) Level 2 Events Specification. We recommend the readers to view the specification here: http://www.w3.org/TR/DOM-Level-2-Events/ . Further, W3C is actively working on the next version of this draft (DOM Level 3 Events). As of this writing, this document was in the "Last Call" working draft and should soon move to the finalized "Recommendation" state.
We should also mention that different browsers also support their own set of events that are specific to them. In this chapter, we would mainly focus only on the events that are common to different browsers.
We need to register various events on a page. These event registrations need to take into account both the object of the event and the event itself. For example, if a user were to click on an image, then we might want to enlarge the image. Now, in this case, the even is a mouseclick and it occurs in association with an image. Association is important since if the user were to click the mouse on any other location of the page, other than the image, then we would not register that click event and hence would not enlarge the image.
There are several methods to adding event handlers. In the following two sections, we discuss two of these.
Earlier, it was a common practice to add the event directly to the HTML element. For the sake of completeness, we provide these methods here -- though, these should no longer be used!
In this approach, we identify the event object and then in its HTML tag, we can add the event along with the handler. Now, the handler code can be written directly in the HTML form tag itself or we can use a JavaScript function to handle that code.
Let us demonstrate this using a simple HTML form. This form consists of two elements. First, it has a set of checkbox elements that are present to indicate if a given task is completed or not. The second element is a submit element; this element appears as a button that the user can click once he has provided all the information.
In this example, we focus on the onsubmit event. The onsubmit event is triggered when the user clicks the submit button of the form; usually, with the submit process, the form data is sent from the client to the server. Thus, the onsubmit event provides us an option (via a handler) to potentially process data or do validation before it is forwarded to the server. The associated object for onsubmit event is the form element itself and so we add this event handler (onsubmit) to the form tag itself.
For onsubmit event, we add a simple JavaScript code that alerts a message when the form is submitted -- this code is the handler code and if it is non-trivial, then we can always use a function and call the function instead of explicitly writing the code after the onsubmit event handler.
<!doctype html> <html> <head> <h2> A Wizard Form </h2></head> <body> <!-- This provides lightweight CSS design --> <style type="text/css"> .classForm {border: 2px solid black; border-radius: 12px; padding: 5px; width: 18em;} </style> <!-- This is a simple HTML form --> <form id="idForm" onsubmit='alert("Submitting the form...")'> <div class="classForm"> <b> Form: To-Do List </b><br> Check mark completed tasks: <br> <input type="checkbox" id="idCheckboxSpells"> Practice Spells <br> <input type="checkbox" id="idCheckboxDragon"> Visit Bilbo Baggins <br> <input type="checkbox" id="idCheckboxWand"> Repair broken staff <br> <br> <input type="submit" id="idSubmitButton" value="Click to Submit"> <br> </div> </form> <body> </html>
If we were to submit the above form, then we would see an alert box saying "Submitting the form...".
Today, a more preferred way to add event handlers is to separate their implementation from the HTML code. For this purpose, JavaScript provides addEventListener() method, that can be invoked on the event object outside of the HTML code. This function takes three arguments: the type of the event, the event handler, and a boolean to indicate if the event is a capturing event. JavaScript also provides us with a method to remove an existing event: removeEventListener(). Like addEventListener(), this method also takes three arguments with the same values. We provide below the signatures of these two methods.
obj.addEventListener(eventType, eventHandler, boolCapturingEvent); obj.removeEventListener(eventType, eventHandler, boolCapturingEvent);
Using addEventListener(), let us rewrite the previous example. With this approach, the native HTML code is untouched. Since we can separate the JavaScript code using a file (via the src attribute of the script), this can provide a very clean way of segregating HTML code and JavaScript code as well. Note that we must pass a function name to the addEventListener and removeEventListener instead of actual code.
Yet another way to attach an event handler is to attach it directly. Thus, we can call "elem.onsubmit = alertSubmit" for the onsubmit event directly.
Here is a re-write of the above example using the addEventListener() call.
<!doctype html> <html> <head> <h2> A Wizard Form </h2></head> <body> <!-- This provides lightweight CSS design --> <style type="text/css"> .classForm {border: 2px solid black; border-radius: 12px; padding: 5px; width: 18em;} </style> <!-- This is a simple HTML form --> <form id="idForm"> <div class="classForm"> <b> Form: To-Do List </b><br> Check mark completed tasks: <br> <input type="checkbox" id="idCheckboxSpells"> Practice Spells <br> <input type="checkbox" id="idCheckboxDragon"> Visit Bilbo Baggins <br> <input type="checkbox" id="idCheckboxWand"> Repair broken staff <br> <br> <input type="submit" id="idSubmitButton" value="Click to Submit"> <br> </div> </form> <script type="text/javascript"> function alertSubmit() { alert("Submitting the form..."); } window.onload = ( function() { var elem = document.getElementById("idForm"); elem.addEventListener("submit", alertSubmit, true); }); </script> <body> </html>
The behavior remains identical in both cases.
We should note that addEventListener() is not implemented in Internet Explorer till (and including) version 8. Instead, it provided attachEvent() and detachEvent() as counterparts of addEventListener() and removeEventListener(). To handle old Internet Explore based browser, we can always check if the method defined and then invoke them. We provide below a rewrite of the above JavaScript code so that it can handle various browsers.
<script type="text/javascript"> function alertSubmit() { alert("Submitting the form..."); } function addThisEvent(obj, eventType, eventHandler, capturingType) { var newEventType = "on" + eventType; if (obj.addEventListener) { obj.addEventListener(eventType, eventHandler, capturingType); } else if (obj.attachEvent) { obj.attachEvent(eventType, eventHandler); } else if (obj[newEventType]) { obj[newEventType] = eventHandler; } } window.onload = ( function() { var elem = document.getElementById("idForm"); addThisEvent(elem, "submit", alertSubmit, false); }); </script>
If the above code to handle browser-incompatibility, makes you cringe, then you are not alone! In fact, for these very reasons, cross-browser libraries (like jQuery) are now widely used. For adding an event listener, jQuery provides bind() method and for removing an event listener, it provides unbind() method. Thus, with this library, we simply need to call bind()/unbind() methods and underneath, jQuery would transparently handle the correct method for the browser being used! We recommend the reader to refer to our jQuery module for more details.
JavaScript events are objects and hence, they carry attributes as well. Two of these attributes are cancellable and bubble.
When an event fires as a result of some action (on the part of user or otherwise), then the event would be followed by the result of that action. However, for certain events, it is possible for the event handler to cancel the result of that action. For this the convention is that the handler should return a value of false. On the other hand, if the handler returns a value of true, then even if the event is cancellable, then the cancellation would be ignored.
Since a single event can be associated with multiple elements on a page, events, after they happen, typically start from one element in the DOM tree and travel upwards till they reach the document object. This property is known as the bubble property and this property is usually true for most of the events.
DOM/JavaScript support many types of events. The popular of those are HTML form events, window events, mouse events, and keyboard events.
HTML form events allow us to register for events like user submitting the form, user resetting the form, user providing an input etc. Since HTML forms are a vehicle to send user input data to a server, these events can be used to validate the user input before handing it off to the server.
Window events enable us to register for events like window loading being complete, window coming into focus or getting blurred, re-sizing or scrolling of the window.
Mouse events deal with clicks of the mouse. These include single click, double click, mouse release, holding the mouse, or the popular hovering effect.
Keyboard events provide events when a user presses a key, release a key, or when holds the key down. We can use these events to trigger a handler when the user provides an input from the keyboard.
In addition to mouse, keyboard, form, and document events, W3C also provides standards for yet another key-area: touch-related events. This is an important effort since with the advent of modern touch devices, like mobile phones, tablets etc, it becomes important to define consistent interfaces that can be used by all vendors.
These events relate to various touch events like when a finger (or stylus) is placed on the screen, when it is removed from the screen, or when the finger (or styles) moves on the screen. The next important construct is to define a focus area on the screen and then keep events when the finger (or stylus) moves into that area or when it moves out of that area. The specification also takes into account the case when the user's touch event is canceled or aborted.
The current recommendation for Touch Events by W3C is "Touch Events version 1" and was recommended in December 2011. For more details, we invite the reader to refer to this location: http://www.w3.org/TR/touch-events/ . We should also mention that W3C is also working on the latest version of Touch Events "Touch Events version 2" and it can be found here: http://dvcs.w3.org/hg/webevents/raw-file/default/touchevents.html