Reputation: 32776
I'm trying to do something i've done numerous times. I can't figure out why this isn't working. No matter how i write the jQuery code, it doesn't work. menuitems[i].action()
just does NOT work. Below is Example 1 in which this example, no matter what item is clicked it returns the last item's action (in this example it's the alert('Forward!')
). The 2nd returns undefined property. The full error below.
My jQuery plugin is called like this (examples below are what happen with this same call):
$('p').contextMenu([
{
name:'Back',
action:function(){
alert('Back!');
},
icon:'http://cdn.iconfinder.net/data/icons/crystalproject/16x16/actions/agt_back.png'
},
{
name:'Forward',
action:function(){
alert('Forward!');
},
icon:'http://cdn.iconfinder.net/data/icons/crystalproject/16x16/actions/agt_forward.png'
}
]);
Example 1:
for (i in menuitems){
$('<li/>',{
'html':'<img src="'+menuitems[i].icon+'">'+menuitems[i].name,
'class':o.itemClass,
'click':function(){
menuitems[i].action();
}
}).appendTo('.'+o.listClass);
}
This returns an alert with Forward! no matter which item, Back or Forward, is clicked.
Example 2:
var len = menuitems.length;
for (var i = 0; i < len; i++){
$('<li/>',{
'html':'<img src="'+menuitems[i].icon+'">'+menuitems[i].name,
'click':function(){
menuitems[i].action();
},
'class':o.itemClass
}).appendTo('.'+o.listClass);
}
I get:
Uncaught TypeError: Cannot read property 'action' of undefined
Other random things i tried were detaching the click and reattaching it outside of that appendTo()
block, changed action()
to newtest()
to make sure it wasn't conflicting with any built in keywords. I also tried doing a $('body').append('<li>{blah blah}</li>').find('li').click(function(){/*blah blah*/});
but it still returned the same thing. I'm outta ideas!
Upvotes: 11
Views: 113327
Reputation: 3836
I had same problem with 'parallax' plugin.
I changed jQuery librery version to *jquery-1.6.4*
from *jquery-1.10.2*.
And error cleared.
Upvotes: 0
Reputation: 1983
The problem is that "i" is incremented, so by the time the click event is executed the value of i equals len. One possible solution is to capture the value of i inside a function:
var len = menuitems.length;
for (var i = 0; i < len; i++){
(function(i) {
$('<li/>',{
'html':'<img src="'+menuitems[i].icon+'">'+menuitems[i].name,
'click':function(){
menuitems[i].action();
},
'class':o.itemClass
}).appendTo('.'+o.listClass);
})(i);
}
In the above sample, the anonymous function creates a new scope which captures the current value of i, so that when the click event is triggered the local variable is used instead of the i from the for loop.
Upvotes: 16
Reputation: 641
Usually that problem is that in the last iteration you have an empty object or undefine object. use console.log() inside you cicle to check that this doent happend.
Sometimes a prototype in some place add an extra element.
Upvotes: 0