Javascript Guide - Events
You can now also navigate the guide through the table of contents.
In the previous post I've mentioned that events are the only part of the DOM that shines. We will now find out why.
What are Events?
Events are a tool with which we can ask the page to do stuff when something happens to it, for example, to run a function when a certain element is clicked, or when a certain input box losses focus.
There is a very long list of valid events, from element clicking, to key pressing, to focusing and blurring and much more. In the end of this article I will add some links for you to read about them.
Another important note about events is, that when an event code runs, it's this points to the elements firing the event.
There are 3 standard ways with which we can attach an event to an element:
-
The Wrong way - inline scripting
This is the worst way we can attach events to elements, and from legacy reasons (alongside bad guides) it is also the most common. This method uses standard HTML properties to assign inline scripts to that element.
You see, each valid event has an attribute with it name, following the
on
word. So, for theclickevent, we can use theonclickattribute.<div onclick="javascript:console.log('I am using inline scripting')">click me!</div>click me!The reason we treat this one as a bad idea is the same reason as always - it uses inline scripting, which is bad for performance, it doesn't scale, and it is a nightmare to maintain.
Also, note that any valid JS command is valid here, and that includes function calls and even lambdas.
-
The Better Way - DOM attributes
This way uses the same basic concept of the previous one, only that it doesn't use inline scripting. Since all event attributes are valid ones, all DOM elements have access to them, and so we can assign them events.
var el = document.getElementById('ex1'); el.onclick = function(){ console.log('I am a little better than my previous brother!'); }run code click me!The downside for this method (which is actually shares with the previous one) is that we cannot use it to attach multiple functions to the same event. Since it uses the attribute system, each time we assign an event, we overwrite it's previous value. This becomes a big problem on large scale websites.
-
The right way - through the DOM events interface
You see, the DOM provides us with a great interface for adding events, that allows us to attach multiple events of the same type to the same element:
var el = document.getElementById('ex2'); el.addEventListener('click',function(e){ console.log('i am one correct event!'); },false); el.addEventListener('click',function(e){ console.log('i am another correct event!'); },false);run code click me!As you can see, we use the actual event name, no
oninvolved. For now, we are going to ignore theearguments that is passed to the function, as well as the 3rd boolean argument.The downside? IE comes with a non standard events API with different names and different behaviors. You can read about it here.
In fact, there isn't an easy way to solve this in a full way, but here is a crude attempt:
var addEvent = (function(){ //we use a self executing function, that will run once, //returning the right function dpending on browser compaitibility if (document.addEventListener) return function(el,event,func){ el.addEventListener(event,func,false); } if (document.attachEvent) return function(el,event,func){ var ev_func = function(e){ e = e || window.event; func.apply(e.target,[e]); } el.attachEvent('on'+event,ev_func); } })(); var el = document.getElementById('ex3'); addEvent(el,'click',function(e){ console.log('cross-browser baby!'); });run code click me!OK, so that was a lot of code, and it uses some mixed patterns, such as a self-executing lambda, returning complex data and so on, so lets break it up:
- We want to create a function that will add events cross-browser -
addEvent, that will receive an element, event name and a function, and attach the event to the element. - Since our code will be ran in one browser at a time, we don't need it to run every time someone adds an event, so use the self-executing lambda to check which method to use, and return the right function. That returned value will be assigned to
addEvent. - The way we check the right API is by checking if a property exists. When we try to access a non-existent property of an object, it will return
undefined, which is falsy. - The IE event model has many differences (which are details at the above link), and we try to address the major ones. It's fine if you don't understand some of it, just the principles used.
- The important thing is, that we now have a function that will work on all major browsers (remember that
console.logdoes not exist on IE6-7, so that part is not cross-browser).
- We want to create a function that will add events cross-browser -
I will add this note - event handling is yet another thing done right by all libraries. So although it is important that we understand the concepts, the exact methods are not that important.
Now that we know the tool with which we add events to our elements, we can start learning about some of the more advanced features of events - event bubbling.
Event Bubbling
When an element fires an event, the process doesn't end there. When the event is fired, it will start "bubbling", firing on all the element's parent chain, until stopped, on until it reaches the document node.
And the example:
var el = document.getElementById('parent1');
addEvent(el,'click',function(){
console.log('I Bubbled Up!');
this.style.background = '#cfa';
});
This is a very important aspect, as it allows us to register events to a parent node instead of a very long list of it's child nodes.
You should know that not all events bubble down, and that behavior is not even fully cross browser. To read more on event bubbling, go here.
The Event object
As you might have notices, when I supplied function when adding events, all these functions expected an e argument, and we even took the while to make that cross browser.
The event object is an object that contain various information about the state of the browser when the even was fired - such as mouse location, key pressed an so forth.
It is yet another thing that IE does differently than the W3C standard. Instead of going through everything, I am going to point you again to the authority on cross-browser compatibility - quirksmode.
Further Reading
Most of the stuff I explained on this page were derived from PPK's excellent guide to events on Quirks Mode. This is a must read, and by now, It is something that I exect of you to start doing. You have sufficient knowledge for that now.
There are just 2 more posts to go. Next post - AJAX - and some other small stuff that I haven't yet addressed.