Jordi Boggiano | Liip AG

JavaScript Events and Scopes

Who am I?

Events

Listening

ECMAScript in all browsers but IE

node.addEventListener("click", function() {
    alert("clicked ECMA");
}, false);
            

IE Only (<=8)

node.attachEvent("onclick", function() {
    alert("clicked IE");
});
            

Conclusion? Don't bother...

JS Frameworks to the rescue!

jQuery

$(node).click(function(e) {
    alert("clicked jQ");
});
$(node).bind("custom", {optional: "dataobj"}, function(){});
            

YUI3

var handleClick = function(e, someArg) {
    alert("clicked YUI");
};
Y.on("click", handleClick, node, someArg);
            

Namespacing / Categories

jQuery

$(node).bind("click.category", function(){ alert('clicked'); });

// unbind with e.g.:
$(node).unbind("click.category");
// stackable like css classes
$(node).unbind(".stacked.categories");
            

YUI3

Y.on("category|click", handleClick, node);

// detach all with e.g.:
Y.detach("category|*");
// or...
Y.detach("click", handleClick, node);
            

Dispatching

Plain JS createEvent

var e = document.createEvent('MouseEvents');
e.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);

if (node.dispatchEvent(e)) {
    alert("not canceled");
    alert(e.type);
}
            

jQuery

$(node).click();
$(node).trigger("click", [data]);
$(node).triggerHandler("click", [data]);
            

YUI3

Y.one('.selector').simulate("click", {obj: "foo"});
            

Event Phases

Capture

Note: The propagation stops at the event target

Bubbling

Handling

Receiving the event object

function clickHandler(e) {
    // e = event object
}
            

Stopping the event

$('.red .yellow', slide).click(function (e) {
    alert('yellow');
});

$('.red .green', slide).click(function (e) {
    // stops the bubbling process to red*
    e.stopPropagation();
    alert('green');
});

$('.red', slide).click(function (e) {
    // blocks propagation to red2
    e.stopImmediatePropagation();
    alert('red1');
});
$('.red', slide).click(function (e) {
    alert('red2');
});
            
RED
YELLOW
GREEN

Preventing the default behavior

function clickHandler(e) {
    alert('clicked: '+e.data);
    return false;
}
function clickHandler2(e) {
    alert('clicked: '+e.data);
}
$('a', slide).bind('click', 'link', clickHandler);
$('input', slide).bind('click', 'button', clickHandler2);
$(slide).bind('click', 'slide', clickHandler);
            

Test link

Preventing the default behavior

function clickHandler(e) {
    e.preventDefault();
    alert('blocked: '+e.data);
}
$('a', slide).bind('click', 'link', clickHandler);
$(slide).bind('click', 'slide', clickHandler);
            

Test link

return false;

What is this?

function clickHandler(e) {
    // e.target = node that triggered the event
    alert('target: '+$(e.target).attr('class'));
    // e.currentTarget = node we're listening to
    alert('currentTarget: ' + $(e.currentTarget).attr('class'));
    // this = e.currentTarget
    alert('this: '+$(this).attr('class'));
}
$('.red', slide).click(clickHandler);
            
RED
GREEN

In YUI this is wrapped in a YUI.Node, in jQuery it is a standard DOM Node.

Scoping

Scoping: Basic Closures

var test = 'foo';
function foo() {
    test = 'bar';
    alert(test);
}
foo();
alert(test);
            
var test = 'foo';
function foo() {
    var test = 'bar';
    alert(test);
}
foo();
alert(test);
            

Variable hoisting: scoping issues

var test = 'foo';
function foo() {
    alert(test);
    test = 'bar';
    alert(test);
}
foo();
            
var test = 'foo';
function foo() {
    alert(test);
    var test = 'bar';
    alert(test);
}
foo();
            

Variable hoisting: scoping issues

var test = 'foo';
function foo() {
    alert(test);
    var test = 'bar';
    alert(test);
}
foo();
            

What JS sees:

var test = 'foo';
function foo() {
    var test;
    alert(test);
    test = 'bar';
    alert(test);
}
foo();
            

Variable hoisting: functions

function foo() {
    return 'foo';
}
var foo = 'bar';
alert(foo);
alert(foo());
            

Variable hoisting: functions

function foo() {
    return 'foo';
}
var foo = 'bar';
alert(foo);
alert(foo());
            

What JS sees:

var foo;
foo = function () {
    return 'foo';
}
foo = 'bar';
alert(foo);
alert(foo());
            

Scoping: Adv. Closures (= Lexical Scoping)

var adder = (function () {
    var total, innerFunction;
    total = 0;
    innerFunction = function (number) {
        total += number;
        return total;
    }
    return innerFunction;
}());

alert(adder(2));
alert(adder(2));
alert(total);
            

Thank you.

Questions?

References & Links