Events

Binding Events with Javascript

There are four ways to respond to an event.

  1. Element Attribute e.g. <button id="myBtn" onclick="doThis();">
  2. Object Property e.g. document.getElementById("myBtn").onclick = doThis;
  3. W3C Listeners e.g. document.getElementById("myBtn").addEventListener("click", doThis, false);
  4. IE Attachments e.g. document.getElementById("myBtn").attachEvent("onclick", doThis);

Using the first method is quick and dirty, but doesn't follow unobtrusive Javascript and is less flexible. The second method is cross-browser and is good for standard DOM events, however you can only attach one function to the element this way.

The most flexible method, and only way if you are generating your own events, is to use a combination of methods 3 and 4 because Microsoft uses a non-standard way to bind events.

jQuery Events

The previous section talked about pure JavaScript for handling events; it’s also possible to bind events using jQuery.

One-Time Events

Sometimes an event need only be called once in your page. For example, clicking a thumbnail which loads and plays a video file or clicking a "more" icon which retrieves and displays extra content via Ajax. However, you've probably defined an event handler which is called every time that action occurs. At best, it's a little inefficient and the browser is retaining unnecessary resources. At worst, your handler could do something unexpected or reload data which is already available.

Fortunately, it's relatively easy to create one-time event handlers in JavaScript. The process:

  1. A handler is assigned to an event, such as clicking an element.
  2. When the element is clicked, the handler runs.
  3. The handler is removed. Further clicks on that element will no longer call the function.

jQuery

Let's look at the simplest solution first. If you're using jQuery, there's a little-known one() event binding method which implements one-time events.

$("#myelement").one( "click", function() {

  alert("You'll only see this once!");

});

It’s used identically to other jQuery event methods. For more information, refer to api.jquery.com/one/.

Plain Javascript

Refer to the original article that describes One-time events.

Custom Events

In the example above, all the events were getting bound to DOM elements, which are smart enough to know about standard mouse and keyboard events. If you want to place a listenener on one of your own objects, then you'll need to create a custom event handler.

http://www.nczonline.net/blog/2010/03/09/custom-events-in-javascript/

http://www.codeproject.com/Articles/13914/Observer-Design-Pattern-Using-JavaScript Very in depth article on creating the Observer pattern.

Example

 

The HTML code that creates the above example is shown here.

<div class="callout"><div id="lcd"></div> <button id="updateBtn">Update</button></div>
<p><button onClick="alert(model.curTime);">Show Last Time</button></p>

<script type="text/javascript" src="../scripts/common.js"></script>
<script type="text/javascript" src="scripts/EventExample.js"></script>

<script type="text/javascript">
    var model = new EventExample.Model('Click Update for current time.');
    var view = new EventExample.View(document.getElementById('lcd'),document.getElementById('updateBtn'));
    // ------------ BEGIN CONTROLLER CODE
     view.addListener("updateRequested",function() {
         model.updateTime();
     });
     model.addListener("newTime",function(evt) {
         view.content(evt.curTime);
     });
     // ------------ END CONTROLLER CODE
</script>

Click the filename to download/view the external scripts:

Deferreds and Promises

Resources

Wrangle Async Tasks With JQuery Promises tutorial

Promises/A specification

jQuery Tutorial page

jQuery Deferred API

Event Capturing and Bubbling

DOM Elements are nested in each other. For example, the <body> can contain a <div> and that can contain a <section> and that can contain a <h1>.

<body>
	<div>
		<section>
			<h1> ... </h1>
			<p> ... </p>
			<img>
		</section>
	</div>
</body>

When, typically, a mouse event fires (such as onClick or onMouseOut) it will try to execute ALL event handlers in the hierarchy. Let us say that the mouse is hovering over the <section> element in the code above and the user then mouses over the <div>. When the mouse leaves the <section> element the MouseOut event fires, which begins the event processing.

First, that event goes through the Capturing Phase for W3C browsers (in other words, IE8 and older does not have a Capturing phase). This is mostly a non-issue because it is pretty rare to use that phase anyway. Capturing means the MouseOut (capture) event is fired for every parent DOM element starting at the top. So, in this example, first <body>, then <div>, and lastly <section>.

Now we begin the Bubbling Phase. During this phase, there are three properties of the Event Object that are most interesting. Event.relatedTarget (IE8 calls it toElement), Event.target (IE8 calls it srcElement), and Event.currentTarget (IE8 uses the "this" object). The following table shows the order and value of the variables as it bubbles up the DOM tree.

Element target currentTarget relatedTarget
<section> section section div
<div> section div div
<body> section body div

Event.target is the DOM element that initiated the Event process, therefore it stays the same.

Event.currentTarget is the handler that is actively being processed. If there is an event handle on <section> and <div>, they will be called.

Event.relatedTarget depends on the type of MouseEvent that is triggered. For MouseOut, it is the DOM object that the mouse rolled into.