Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
184
rated 0 times [  190] [ 6]  / answers: 1 / hits: 138385  / 15 Years ago, thu, august 27, 2009, 12:00:00

I've created a Javascript object via prototyping. I'm trying to render a table dynamically. While the rendering part is simple and works fine, I also need to handle certain client side events for the dynamically rendered table. That, also is easy. Where I'm having issues is with the this reference inside of the function that handles the event. Instead of this references the object, it's referencing the element that raised the event.



See code. The problematic area is in ticketTable.prototype.handleCellClick = function():



function ticketTable(ticks)
{
// tickets is an array
this.tickets = ticks;
}

ticketTable.prototype.render = function(element)
{
var tbl = document.createElement(table);
for ( var i = 0; i < this.tickets.length; i++ )
{
// create row and cells
var row = document.createElement(tr);
var cell1 = document.createElement(td);
var cell2 = document.createElement(td);

// add text to the cells
cell1.appendChild(document.createTextNode(i));
cell2.appendChild(document.createTextNode(this.tickets[i]));

// handle clicks to the first cell.
// FYI, this only works in FF, need a little more code for IE
cell1.addEventListener(click, this.handleCellClick, false);

// add cells to row
row.appendChild(cell1);
row.appendChild(cell2);


// add row to table
tbl.appendChild(row);
}

// Add table to the page
element.appendChild(tbl);
}

ticketTable.prototype.handleCellClick = function()
{
// PROBLEM!!! in the context of this function,
// when used to handle an event,
// this is the element that triggered the event.

// this works fine
alert(this.innerHTML);

// this does not. I can't seem to figure out the syntax to access the array in the object.
alert(this.tickets.length);
}

More From » oop

 Answers
1

You need to bind handler to your instance.



var _this = this;
function onClickBound(e) {
_this.handleCellClick.call(cell1, e || window.event);
}
if (cell1.addEventListener) {
cell1.addEventListener(click, onClickBound, false);
}
else if (cell1.attachEvent) {
cell1.attachEvent(onclick, onClickBound);
}


Note that event handler here normalizes event object (passed as a first argument) and invokes handleCellClick in a proper context (i.e. referring to an element that was attached event listener to).



Also note that context normalization here (i.e. setting proper this in event handler) creates a circular reference between function used as event handler (onClickBound) and an element object (cell1). In some versions of IE (6 and 7) this can, and probably will, result in a memory leak. This leak in essence is browser failing to release memory on page refresh due to circular reference existing between native and host object.



To circumvent it, you would need to either a) drop this normalization; b) employ alternative (and more complex) normalization strategy; c) clean up existing event listeners on page unload, i.e. by using removeEventListener, detachEvent and elements nulling (which unfortunately would render browsers' fast history navigation useless).



You could also find a JS library that takes care of this. Most of them (e.g.: jQuery, Prototype.js, YUI, etc.) usually handle cleanups as described in (c).


[#98826] Friday, August 21, 2009, 15 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
calicinthias

Total Points: 447
Total Questions: 101
Total Answers: 118

Location: Botswana
Member since Sat, Dec 31, 2022
1 Year ago
calicinthias questions
Sun, Jan 2, 22, 00:00, 2 Years ago
Wed, Jan 13, 21, 00:00, 3 Years ago
Mon, Aug 10, 20, 00:00, 4 Years ago
;