Reputation: 3343
I'm having some difficulties with passing functions around. I have this code:
var options = [
{ name: "menu 1", func: function (element) { $(element).css("color", "Red"); } },
{ name: "menu 2", func: function (element) { alert("menu 2"); } },
{ name: "menu 3", func: function (element) { alert("menu 3"); } }
];
// This basically creates a div with ul, and li element for each object in options,
// and attaches click event to each li that should fire provided func.
(function menuMaker(options) {
var menuDiv = $("<div id='test' />");
var menuUl = $("<ul>");
menuDiv.append(menuUl);
for (var i = 0; i < options.length; i++) {
var li = $("<li>" + options[i].name + "</li>");
// **li.click(function () { options[i].func(menuDiv); });**
//>> The line above gives "options[i] is undefined" error. Looks like a scoping issue.
var userFunc = options[i].func;
**li.click(function(){ userFunc(menuDiv);});**
//>> The line above always fires the last function (alert("menu 3"))
menuUl.append(li);
}
$(document.body).append(menuDiv);
})(options);
and I'm getting those errors I've commented. Any ideas what am I doing wrong ?
Thanks !
Upvotes: 0
Views: 112
Reputation: 107
Remove the "options" argument from "(function menuMaker(options) { ". The options variable is already set outside of the function. By adding it as an argument the function looks for the argument of "options" and not the predefined variable of options.
Im not great at explaining stuff, but as for passing the function through the for loop and to each individual click event, create an empty function like below, that way it doesnt reference the last value used.
Tested! Works!
var options = [
{ name: "menu 1", func: function (element) { $(element).css("color", "Red"); } },
{ name: "menu 2", func: function (element) { alert("menu 2"); } },
{ name: "menu 3", func: function (element) { alert("menu 3"); } }
];
(function menuMaker() {
var menuDiv = $('<div id="test" />'),
menuUl = $('<ul />').appendTo(menuDiv);
for (var i=0; i<options.length; i++) {
(function() {
var func = options[i].func;
$('<li>' + options[i].name + '</li>')
.click(function(){ func(menuDiv); })
.appendTo(menuUl);
})();
}
$(document.body).append(menuDiv);
})();
Upvotes: 1
Reputation: 36999
Try this, which iterates over the array adding <li>
elements. The function to be called is assigned to the local 'func' variable and then used within the click handler function.
$.each(options, function() {
var func = this.func;
menuUl.append(
$('<li>').text(this.name).click(function () {
func(menuDiv);
})
);
});
Upvotes: 1
Reputation: 15552
The problem is indeed a scoping one. The for loop does not create a new scope, so you have to create one inside it like:
for (var i=0; i<10; i++) {
(function(i) {
// "i" will be local here, and be accessible
// form any function defined inside this closure
})(i);
}
Upvotes: 1