Page 1 of 1

Event Delegation Rate Topic: -----

#1 andrewsw  Icon User is online

  • Fire giant boob nipple gun!
  • member icon

Reputation: 3466
  • View blog
  • Posts: 11,759
  • Joined: 12-December 12

Posted 27 December 2012 - 05:39 PM

Event Delegation in Javascript.

Event delegation has two related meanings. In languages other than JS a delegate is an object that is created specifically to respond to an event on an object (or objects). The simpler JS meaning for this tutorial is the following:

Quote

We attach an event to a parent element and, when the event occurs, we discover which specific child-element was the target of the event.


People commonly loop through rows of a table, or list-items, attaching an event (such as click) to each row/td or item. Depending on how the event is attached, each element may obtain their own copy of the event. This is inefficient and can largely be avoided.

The following example attaches the click event to the (parent) ol-element. When this is clicked we respond to the event BUT ONLY FOR LI-ITEMS. The counter confirms that there is only one instance of the alertText() function.

<!DOCTYPE html>
<html>
<head>
<title>Some Title</title>
<script type="text/javascript">
var addEvent = function (elem, eventType, func) {
    if ( elem.addEventListener )
        addEvent = function (elem, eventType, func) {
            elem.addEventListener(eventType, func, false);
        };
    else if ( elem.attachEvent )
        addEvent = function (elem, eventType, func) {
            elem.attachEvent('on' + eventType, func);
        };
    addEvent(elem, eventType, func);
};

var delegateEvent = function (elem, childElems, eventType, func) {
    addEvent(elem, eventType, function (e) {
        var evt = e || window.event;
        var elem = evt.target || evt.srcElement;
        if ( elem.nodeName.toLowerCase() == childElems.toLowerCase() ) {
            func(elem);
        }
    });
}

function alertText(obj) {
    this.counter = this.counter || 1;
    alert(counter++ + ' hits :' + obj.innerHTML);
}
function init() {
    delegateEvent(document.getElementById('thelist'), 'li', 'click', alertText);
}

addEvent(window, 'load', init);
</script>
</head>
<body>
<ul id="thelist">
    <li>The first line</li>
    <li>.. and the second one</li>
    <li>just a third..</li>
    <li>and finally, a fourth.</li>
</ul>
</body>
</html>


Below is an expanded version that also passes arguments to the delegated event:

It will highlight rows as you mouseover them using a supplied colour argument, also (optionally) displaying the row number ("Row 1", etc.). When the mouse moves out the previous background colour is re-instated and the temporary title ("Row 1", etc.) is removed.

<!DOCTYPE html>
<html>
<head>
<title>Highlight Rows</title>
<style type="text/css">
    table {
        background-color: lightgreen;
    }
</style>
<script type="text/javascript">
var addEvent = function (elem, eventType, func) {
    if ( elem.addEventListener )
        addEvent = function (elem, eventType, func) {
            elem.addEventListener(eventType, func, false);
        };
    else if ( elem.attachEvent )
        addEvent = function (elem, eventType, func) {
            elem.attachEvent('on' + eventType, func);
        };
    addEvent(elem, eventType, func);
};

var delegateEvent = function (elem, childElems, eventType, func, args) {
    addEvent(elem, eventType, function (e) {
        var evt = e || window.event;
        var elem = evt.target || evt.srcElement;
        if ( elem.nodeName.toLowerCase() === childElems.toLowerCase() ) {
            func(elem, args);
        }
    });
};

function highlightRows(obj, args) {
    if (args && args.over && args.over === true) {
        obj.prevColour = obj.parentNode.style.backgroundColor;
        obj.parentNode.style.backgroundColor = args.colour;
        if (args.index && obj.title=="")
            obj.title = "Row " + obj.parentNode.rowIndex;
    } else {
        obj.parentNode.style.backgroundColor = obj.prevColour;
        if (obj.title.indexOf("Row ") + 1)
            obj.title = "";
    }
}

function init() {
    delegateEvent(document.getElementById('thetable'), 'td', 'mouseover',
                  highlightRows, {'colour': 'lightblue', 'over': true, 'index': true});
    delegateEvent(document.getElementById('thetable'), 'td', 'mouseout',
                  highlightRows, {'over': false});
}

addEvent(window, 'load', init);
</script>
</head>
<body>
<table id="thetable" summary="highlight demo">
    <tr><td>Just one</td><td>.. no another</td></tr>
    <tr><td>Second</td><td>.. no another</td></tr>
    <tr style="background-color: yellow;"><td>A third</td><td>.. no another</td></tr>
    <tr><td>Fourth for luck</td><td>.. no another</td></tr>
</table>
</body>
</html>


If the background colours were set using a stylesheet, rather than inline, then it would not be necessary to store the 'prevColour': setting the colour to "" would set the rows back to their original colours.

Is This A Good Question/Topic? 0
  • +

Replies To: Event Delegation

#2 andrewsw  Icon User is online

  • Fire giant boob nipple gun!
  • member icon

Reputation: 3466
  • View blog
  • Posts: 11,759
  • Joined: 12-December 12

Posted 14 January 2013 - 02:30 AM

In my first code example this.counter should be alertText.counter otherwise this refers to the window object:

function alertText(obj) {
    alertText.counter = alertText.counter || 1;
    alert(alertText.counter++ + ' hits :' + obj.innerHTML);
}


Apologies for the slight correction. Andy.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1