LA.NET [EN]

Jul 30

Today we’re going to start talking about JQuery event’s propagation. Before delving into JQuery’s behavior, I guess that we need to make a small detour and talk about JAvascript and DOM events levels compatibility. By now, most of us have already heard the terms DOM level 0 event compatible or DOM level 2 event compatible. But what does this mean? The first thing you should keep in mind is that there are several levels and that each level specifies several features that should be implemented by all compatible browsers.

The first level is know as DOM Level 0 and was based on the event model introduced by the first browsers (notice that there really isn’t a DOM level 0 standard). Currently, this level is supported by all existing browsers. Level 0 gives you two options for handling events. You can hook up an event and a function by using an attribute on the form onXXX, where XXX is the event you want to handle. Take a look at the following snippet:

<input type="button" value="Say hi!" id="bt" onclick="sayHi()" />
<script type="text/javascript">
 function sayHi(evt) {
  alert("hi!");
 }
</script>

I guess that we’ve all written this code in the past, right? Not really good quality code, but hey, it works in all browsers, right? The second option for this level relies on the mappings that exist between HTML attributes and properties on JS objects that represent HTML elements (we’ve already talked about this in a previous post). The next snippet is equivalent to the previous one, but relies on JS code:

<input type="button" value="Say hi!" id="bt" />
<script type="text/javascript">
 $("#bt")[0].onclick =  function(evt) {
                          alert("hi!");
                         }
</script>

Now, even though this option is better than the previous one (notice that we removed the JS code from the markup), there are still some problems. For instance,if anyone else hooks an event that has been previously set,it will end up removing the previous handler.

Even at this level, there are still some differences between browsers. For instance, if you look at the previous examples, you’ll notice that the function receives an evt parameter. That parameter should automatically references the event object that contains information about the current event. Unfortunately, IE doesn’t comply with this and you’ll find a reference to the current event object on the window’s event property.

Now, level 0 event introduced another very interesting feature: event bubbling. Whenever an event is generated at an element, it will propagate until it reaches the top level element. That’s why it’s called bubbling: it goes in a bottom-up direction. Take a look at the following example:

<div id="top">
    <div id="inner">
        <p id="paragraph">Just some text</p>
    </div>
</div>
<script type="text/javascript">
    $("*").each(function() {
        this.onclick = function(evt) { alert(this.id); };
    });
</script>

The previous example will use DOM 0 level code for setting up the click event of all existing DOM nodes. If you run the code, you’ll see that you’ll get an alert starting and the p element and then the event will propagate until it reaches the top HTML element (to see this you’ll probably need to replace the this.id with this.tagName expression in the alert invocation).

Now, this is really cool because it means you can handle a specific event by hooking up that event at a top level. Cancelling the default bubbling is possible: just call the event’s stopPropagation method.

function(evt) { alert(this.id); evt.stopPropagation();  };

Notice that this really isn’t a level 0 feature (in fact, it’s a level 2 feature). As you might expect by now, IE uses a different method for cancelling propagation: the event’s cancelBubble property must be set to true (don’t forget that in IE you need to use window.event to get to the event object).

There’s still one more thing you need to know before we call it a day: some events have predefined default actions assigned to them. I guess that the most known example is submitting a form. Form submission generates a submit event which, by default, ends up sending the form’s data through a post or get request. Notice that this will happen even if you set up an event handler:

<form method="post" id="frm">
    ´<input type="submit" value="submit form" />
</form>
<script type="text/javascript">
    $("#frm")[0].onsubmit = function(evt) {
        alert("submitting");
        //how to cancel default action?
    };
</script>

If you run the previous code, you’ll always get a post request. The question is: how can I cancel that form submission? In these cases, most people will simply return false from this method. By doing that, you’re saying that you’re not interesting in getting the default behavior associated with that event. DOM 2 level introduces a preventDefault method you can use to signal the cancellation of the default action associated with an event. Notice that this method won’t cancel event bubbling. I guess that we’re already starting to go into DOM level 2 event land, so we’ll stop here. On the next post we’ll look at what DOM level 2 introduced so that we can finally take a look at how JQuery protects us from knowing all this stuff. Keep tuned!

5 comments so far

  1. Pedro Lamas
    2:00 pm - 7-30-2009

    Event bubbling can be cancelled thru the following function:

    function stopPropagation(e)
    {
    e = e||event;
    e.stopPropagation? e.stopPropagation() : e.cancelBubble = true;
    }

    Use this like “return stopPropagation(evt);” instead of “return false;” on your own sample!

  2. luisabreu
    9:03 pm - 7-30-2009

    Hello Pedro. Yes, my code could be improved (though I just want to present the current status so that people understand what they will need to know if they”re not using JQUery). btw, why return instead of a simple method call?

  3. Pedro Lamas
    11:22 pm - 7-30-2009

    My method was a bit longer than the one I posted, it also checked some conditions before aborting the method, so I when I removed the checking, I forgot I dind”t have to do a return 😉

  4. Phillip
    3:12 am - 7-31-2009

    Definitly perfer the lighter one!!!

    The dark one isn”t too bad at home to read, but at work because the monitor is a little bit old i cant read anything without highlighting the code snipit.

    Cheers.

  5. bandsxbands
    8:20 pm - 2-7-2010

    It”s interesting to see just how pervasive digital memory has become in our every day lives. It seems like everytime I turn my head, I see something with a card slot or USB jack . I guess it makes sense though, considering how much more afforable memory has become as of late…Ahhh, I shouldn”t be complaining. I can”t make it through a day without using my R4 / R4i!(Submitted by S3 for R4i Nintendo DS.)