views:

171

answers:

1

I've got the following simple script:

var fruits = new Array("apple","orange","lemon");

$("#fruit_canvas").append("Mouse over these fruits:");

for(var i = 0; i < fruits.length; i++)
{
    var fruit = fruits[i];
    var html = "<div id='fruit" + i + "'>" + fruit + "</div>";
    var fruitdiv = $(html);
    $("#fruit_canvas").append(fruitdiv);

    google.maps.event.addDomListener($(fruitdiv)[0], 'mouseover', function() {
        $("#result_canvas").append("Mouse over " + fruit);
    });

    google.maps.event.addDomListener($(fruitdiv)[0], 'mouseout', function() {
        $("#result_canvas").empty();
    });
}

It loops through a simple array, uses jQuery to make a div out of each element, and appends it to another div. A Google Maps DOM listener is then added to each appended div. That all works fine, but the DOM listener only seems to be aware of the last element of the array, i.e., it always returns "lemon" as the fruit, no matter which appended div you mouseover.

To see what I mean, go to http://www.pinksy.co.uk/maptest.html and hover over each of the divs.

I'm sure it's something obvious to do with how I'm passing the DOM element to the DOM listener, but I'm not sure how!

I've also tried it without jQuery, but get the same results:

document.getElementById('fruit_canvas2').appendChild(document.createTextNode("Mouse over these fruits:"));

for(var i = 0; i < fruits.length; i++)
{
    var fruit = fruits[i];
    var div = document.createElement('div');
    div.innerHTML = fruit;
    document.getElementById('fruit_canvas2').appendChild(div);

    google.maps.event.addDomListener(div, 'mouseover', function() {
        document.getElementById('result_canvas2').appendChild(document.createTextNode("Mouse over " + fruit));
    });

    google.maps.event.addDomListener(div, 'mouseout', function() {
        var cell = document.getElementById('result_canvas2');

        if(cell.hasChildNodes())
        {
            while(cell.childNodes.length >= 1)
            {
                cell.removeChild(cell.firstChild);       
            } 
        }
    });
}

Thanks in advance...

+2  A: 

The problem you're having is one of scope. When you create the listener, the fruit does have the correct value, but when its executed, it takes the last state of fruit in your case, lemon.

What you have to do is simple, you need to create a delegate you can do that like this:

var someFunction = (function(vars) {
    return function() {
        //Do something with vars...
    };
})(vars);

And what you store in someFunction will keep the value of vars at the time of declaration. You're code using that would look like this:

var fruits = new Array("apple","orange","lemon");

$("#fruit_canvas").append("Mouse over these fruits:");

for(var i = 0; i < fruits.length; i++)
{
    var fruit = fruits[i];
    var html = "<div id='fruit" + i + "'>" + fruit + "</div>";
    var fruitdiv = $(html);
    $("#fruit_canvas").append(fruitdiv);

    var mouseoverListener = (function(fruit) {
        return function() {
            $("#result_canvas").append("Mouse over " + fruit);
        };
    })(fruit);
    google.maps.event.addDomListener($(fruitdiv)[0], 'mouseover', mouseoverListener);

    google.maps.event.addDomListener($(fruitdiv)[0], 'mouseout', function() {
        $("#result_canvas").empty();
    });
}
Juan
Wow! Thanks Juan! I'm embarrassed to say it, but delegates is something I'd never heard of before! I knew it was bound to be something to do with scope! Works perfectly now! http://www.pinksy.co.uk/maptest.html
pinksy
Please accept this answer
plexer
Your welcome, I didn't know they by name until a few days ago, but I used them in JS every once in a while, its incredibly useful.
Juan