Reputation: 1823
The idea is that I want to loop through these objects and build an HTML structure which will be added to the page. I thought it would be cleaner to do it all in the chain, but apparently I'm not understanding something about the context of this
as it evolves through inner loops. I've looked a bit at jQuery.proxy()
a bit, but I'm not sure I understand how to apply it here. Maybe there is another way altogether of doing what I'm trying to do here...
var obj = [
{"id":1213854620001,"name":"item 1","URL":"1213897576001.jpg"},
{"id":1213854619001,"name":"item 2","URL":"1213890384001.jpg"},
{"id":1213854618001,"name":"item 3","URL":"1213890378001.jpg"},
{"id":1213854616001,"name":"item 4","URL":"1213897663001.jpg"},
{"id":1213854615001,"name":"item 5","URL":"1213897554001.jpg"}
];
$(function() {
if(obj.length) {
$("<ul/>",{id:"myID"}).append(function(){
var that = document.createDocumentFragment();
$.each(obj,function(index,dataObj){
$("<li/>",{data:{dataID:dataObj.id},text:dataObj.name}) // this === obj[index] === dataObj, shouldn't it be the [object HTMLLIElement]
.live("click",function(event) {
openVideo($(event.target).data(dataID));
})
.append(function() {
return $("<img/>",{src:dataObj.thumbnailURL})[0];
})
.appendTo(that);
});
return that;
}).appendTo("body");
}
});
function openVideo(str) {
//console.log(str);
}
The implicit question becomes, why is that
empty after my loop? and how can I build this HTML structure with nested loops?
Using the suggestions from the comments, and answers, I built this, which seems to work exactly as it should, reads a little cleaner, and lets jQuery do all the javascript (e.g. documentFragment
creation, and manipulation, etc):
$(function() {
if(obj.length) {
$("<ul/>",{id:"myID"})
.delegate("li","click",function(){openVideo($(this).data("dataID"));})
.append(function() {
var that = $(this);
$.each(obj,function(index,dataObj) {
$("<li/>",{data:{dataID:dataObj.id},text:dataObj.name}).each(function() {
$("<img/>",{src:dataObj.URL}).appendTo(this);
that.append(this);
})
});
}).appendTo("body");
}
});
Upvotes: 1
Views: 2093
Reputation: 83366
this
changes meaning as you step into new nested functions. It does not change meaning when you call $()
to create a new element.
So immediately inside of
$.each(obj, function(index, dataObj) {
this
is the current object over which your looping. Once you get here:
.live("click",function(event) { // <------ inside of nested function
openVideo($(event.target).data(dataID));
})
this
is the element on which you clicked.
But calling
$("<li/>",{data:{dataID:dataObj.id},text:dataObj.name})
to create a new li
element does not set this
to the newly created element.
Also, if you want to save the meaning of this
even inside of nested functions, the standard way is to save it to a new variable.
$.each(obj, function() {
var self = this;
Now self
can be used instead of this
as the item you're currently "on" anywhere in your loop, even in nested function handlers. Or you can pass index and dataObjects to the each function - same effect.
EDIT
As a comment pointed out, you're using live incorrectly. If you're using jQuery 1.7, you'll want:
$(document).on("click", "li", function(event) {
openVideo($(this).data(dataID));
});
in your document.ready
handler. If all li's that will be clicked will be in a certain div, than select on that div instead of document
. If you don't want this click handler to apply to all li's, but only some, then decorate all the li's you want this click handler to apply to with a css class, then instead of passing the filter "li" to on
, you'd pass li.yourClass
Upvotes: 4
Reputation:
$.each
sets this
for the inner function to be the element iterated (and yes, this
is one of the complicated things in Javascript, but your comment can be explained by just referencing each
behaviour).
Upvotes: 1
Reputation: 1214
The thing is, in prototype based languages, which javascript is one, functions are objects, and objects have properties. So when you use the 'this' keyword, it reverts to the scope of the current prototype. Inside of an 'inline function' (which is actually not a concept in javascript since functions are just objects), this refers to the function.
Upvotes: 0