views:

79

answers:

1

I have a little trouble understanding scope and lifetime using javaScript and jQuery. I have a function that takes an array of custom objects (gps is an array of groups)

var currentGroup;
for(var index = 0, length = gps.length; index < length; ++index)
{
    currentGroup = gps[index];
    var newGroup = $('<li id="groupno-' + currentGroup.getID() + '"><span class="group">Group ' + currentGroup.getID() +'</span></li>');

    newGroup.hover(
        function() {newGroup.find("span.group").append(GetGroupActionsContainer(currentGroup.getID()));},
        function() {newGroup.find("span.group > .GroupActionsContainer").remove();}
    );

    gl.append(newGroup);
    gl.treeview({
        add: newGroup
    });
}

So this looks through gps and retreives the currentGroup as an object. Then it creates a new object (confusingly named newGroup at the moment, going to rename it) which is a jQuery object holding a li.

gl is a <ul> on the page.

The problem: This function correctly adds new <li> to the <ul> represented by gl - my list shows all elements. But the hover only applies to the last element: if I have 2+ items and I hover over any of them, I see the icons created by the hover function on the last <li>.

Does anyone know what could be wrong here? I'm guessing that somehow, .hover doesn't apply to the object but to some reference that gets updated while iterating through the loop, but that's pure guessing.

+3  A: 

The newGroup being captured in your hover functions references the last one created in the loop. Use $(this) inside your hover function to reference the hovered element.

newGroup.hover(
    function() {
        var $this = $(this);
        var groupID = $this.attr('id').replace( /groupno-/, '');
        $this.find("span.group").append(GetGroupActionsContainer(groupID));
    },
    function() { $(this).find("span.group > .GroupActionsContainer").remove(); }
);
tvanfosson
$(this) did the trick! I now have some other problem (currentGroup.getID() resolves to the last item in the loop as well), but I think I roughly understand how this works now. Thanks!
Michael Stum
Now I think I understand. As the hover function is a "function pointer" it gets evaluated on hovering, so the inner variable (newGroup and currentGroup.getID()) refer to the object that is current on hover, not the one that was current on creation. Makes sense and hopefully is correct :)
Michael Stum
Yep. I've updated the example to show how to get the group id from the li element directly.
tvanfosson
Thanks. I've "solved" it before by putting the 2 "var newGroup" and "newGroup.hover" lines into a new function (function CreateNewGroup(group)" that takes currentGroup as a parameter and returns newGroup. That works as I guess it makes copies of the objects, but I'll have a look at your edit tomorrow as well.
Michael Stum