views:

61

answers:

3

I have some Google Maps JS that plots a number of markers on a map. However, when loading the markers I noticed that the images were not loading in time and so the markers were not being placed. To get around this I modified my function that returned a map marker as follows:

function newGoogleMapPin(type){
    var imgpath = "img/gmapicons/"+type+".png";
    var img = new Image();
        img.src = imgpath;
    var imgloaded = false;

    while(imgloaded == false) {
        img.onload = function() {
            imgloaded = true;
        }
    }

    return new google.maps.MarkerImage(imgpath, new google.maps.Size(img.width, img.height));
}

Problem being is imgloaded is never set to true, Am I misunderstanding closures? (I guess so!)

+3  A: 

You have to keep in mind that JavaScript is fundamentally single-threaded, and this single thread is actually shared between JavaScript execution and browser rendering. Therefore your while loop will block the thread, and will loop forever.

while(imgloaded == false) {
    // onload will never get called:
    img.onload = function() {
        imgloaded = true;
    }
}
Daniel Vassallo
hmmm, I see, can you see a way around this?
Sergio
@Sergio: I've used custom images for Google Markers (both in the v2 and v3 API) and never had any problems. At most, if there is a big latency to the server serving the image, the markers will show on the map a bit later. However, this is handled automatically, and there should be no need to do something like you were doing. You might also be able to load the images sometime earlier, so that they will already be in the browser cache, but in general, you won't need to.
Daniel Vassallo
A: 

imgloaded in your code is a local variable (in the scope of newGoogleMapPin function). Thus, the imgloaded variable set in the onload callback is another variable. The first variable is always false in this case, which is causing an infinite loop.

To resolve the issue declare it as a global variable outside the function block.

Makram Saleh
You can use `imgloaded` inside that function, that's how closures work (but you're right that it cannot be accessed outside `newGoogleMapPin`).
Marcel Korpel
@Makram: "Thus, the `imgloaded` variable set in the `onload` callback is another variable." ... Well, that's not true. JavaScript has lexical scoping.... In addition, global variables rarely resolve issues.
Daniel Vassallo
this is the correct outcome for the wrong reasons. making the variable global won't change anything.
lincolnk
+1  A: 

All you are doing in your while loop is setting the onload handler of the image to a function. The function never actually gets called.

You should just set the onload handler once, and have the handler do whatever's required with the image (add the pin).

Something like this:

function newGoogleMapPin(type){
    var imgpath = "img/gmapicons/"+type+".png";
    var img = new Image();
    img.src = imgpath;
    img.onload = function() {
       new google.maps.MarkerImage(imgpath, new google.maps.Size(img.width, img.height));
    }
}
jhurshman
I think the OP is using the return value of this function to keep a reference to the marker. It won't be possible if he uses the method you suggested.
Daniel Vassallo
I'll give this method a shot as I don't technically need a reference to the marker.
Sergio