Reputation: 201
I'm having a problem writing an handler for dynamically generated elements in DOM.
My object is composed with a few attributes and some methods
function JMaze(c,r,selector) {
this.maze = new Array();
this.content = new Array();
this.c = c;
this.r = r;
this.x = 0;
this.y = 0;
this.selector = selector; //need a DOM place to fit with the maze
this.bookmark = "Home";
//...other methods...
this.goTo = function(event){
console.log("HERE");
var maze = this.maze;
var bookmark = this.bookmark;
var start, destination;
for (i = 0; i < c; i++)
for (j = 0; j < r; j++)
if (maze[i][j].id == bookmark)
start = maze[i][j];
for (i = 0; i < c; i++) {
for (j = 0; j < r; j++) {
if (maze[i][j].id == event.data.id)
destination = maze[i][j];
}
}
var p = this.findShortestPathAndGo(start,destination);
this.renderMaze(p);
};
this.showMenu = function() {
var content = this.content;
var div = "<div class=\'jMenu\'>";
$.each(content, function(index, value) {
div += "<div menuval=\'" + value.id + "\'>" + value.id + "</div>";
});
div += "</div>";
$( "body" ).append(div);
$.each(content, function(index, value) {
$("[menuval='" + value.id + "']").on(
"click", //event
{id: value.id}, //data
**this.goTo** //handler
);
});
};
};
When I call showMenu everything works fine, and the block near the end does what expected binding the click on DOM objects with attribute menuval with the right value. BUT when i click, and the handler is called, Chrome debug says this
locating the error in jquery.min.js:3.
Actually, it never gets into goTo function.
Someone around may know why?
Thanks in advance.
Upvotes: 0
Views: 127
Reputation: 101
First, you need to keep a reference to the JMaze
object if you want to use it inside the callback, like this:
var that = this;
Then, you need to ensure JMaze.goTo
has the appropriate context, meaning this
will be a reference to the JMaze
object, you can do it by using the jQuery.proxy
function, like this:
$.proxy(that.goTo, that);
So, to put it together:
this.showMenu = function() {
var that = this;
var content = this.content;
var div = "<div class=\'jMenu\'>";
$.each(content, function(index, value) {
div += "<div menuval=\'" + value.id + "\'>" + value.id + "</div>";
});
div += "</div>";
$( "body" ).append(div);
$.each(content, function(index, value) {
$("[menuval='" + value.id + "']").on(
"click", //event
{id: value.id}, //data
$.proxy(that.goTo, that) //handler
);
});
};
You can see it working here. I added some basic data just to test it.
I highly suggest you to take advantage of jQuery's way of creating new DOM elements on the fly (docs) and rewrite the entire function like this:
this.showMenu = function () {
var that = this;
var div = $('<div/>').addClass('jMenu');
$.each(this.content, function (index, value) {
$('<div/>')
.attr('menuval', value.id)
.text(value.id)
.appendTo(div)
.on('click', { id: value.id }, $.proxy(that.goTo, that));
});
$('body').append(div);
};
Upvotes: 2
Reputation: 782158
You can't pass this.goTo
as a value. Binding a method to an object only works when you actually call the function, e.g. this.goTo()
, not when you just refer to it as a value.
Also, inside $.each()
, this
is the current element of the iteration, it's not the JMaze
object.
Try:
var self = this;
$.each(content, function(index, value) {
$("[menuval='" + value.id + "']").on(
"click", //event
{id: value.id}, //data
function() {self.goTo();} //handler
);
});
Upvotes: 0