2

EDITED: The problem is with the function 'find_callback', I want to insert each of the responses to a global array named responseArray. the response is an array of objects.

I'm trying to add markers to the Waze implementation of OpenLayers from an array of searches. I want to run multiple searches, accumulating the results. I use 3 functions, onInit(), find_callback() and addPoint(). Calling the 'find_callback' function overrides the previous markers. If I run a single search:

g_wzae_map.find('THE LOCATION', 'find_callback');

The response:

/* array of search results (up to 10) sorted by relevancy */
[ {
    //bounds that contain the this map feature (set map to this extent for closest zoom)
    "bounds":{"bottom":32.0880470275879,
    "left":34.7883338928223,
    "right":34.7912673950195,
    "top":32.0854721069336},
    //location of the feature
    "location":{"lat":32.08560397003471,"lon":34.78999763465419},
    //name of feature
    "name":"Street, City"
  },
  //up to 9 more results
  // ...
]

The code as it is

function addPoint(response){
    var first_result = response;
    var lon = first_result.location.lon;
    var lat = first_result.location.lat;
    map.setCenter(new OpenLayers.LonLat(lon,lat));

    var markersPoint = new OpenLayers.Layer.Markers( "Markers" );
    markersPoint.addMarker(
        new OpenLayers.Marker(
            new OpenLayers.LonLat(
                lon,
                lat
                ),
            icon.clone()
            )
        );
    g_waze_map.map.addLayer(markersPoint);

    map.addPopup(
        new OpenLayers.Popup.FramedCloud(
            "point_"+first_result.location.lat,
            new OpenLayers.LonLat(lon,lat),
            null,
            "<div style='font-family:Arial,sans-serif;font-size:0.8em;'>"
            +first_result.name+"<div>",
            anchor=null,
            true,
            null
            )
        );

}


//called when map loads
function onInit(){
    map = g_waze_map.map;

    size    = new OpenLayers.Size(15, 20);
    offset  = new OpenLayers.Pixel(-(size.w/2), -size.h);
    icon    = new OpenLayers.Icon('http://www.waze.co.il/images/home.png',size,offset);         

    // array for the points
    responseArray = new Array();
    // find callback
   find_callback = function(response){
        for (var i=0, length = response.length; i<length; i++){
            responseArray.push(response[i]);
        }
        // alert(responseArray[0]); // working, getting an object
    }
    // alert(responseArray[0]); // not working, getting 'undefined'

    //search API example, calls 'find_callback' when search returns
    g_waze_map.find('Turin','find_callback');
    g_waze_map.find('Rome','find_callback', true);
    // adding the points
    for (var i=0, length = responseArray.length; i<length; i++){
        addPoint(responseArray[i]);
    }
};

Thanks!

Sophia Gavish
  • 467
  • 2
  • 8
  • 16
  • 1
    Don't use for in to loop arrays. Try `for (var i=0, length = response.length; i – Hemlock Jan 02 '11 at 13:30
  • Hi, does it matters? Anyway I changed the for loop but it can't get the responseArray outside of the function 'find_callback'. When I checking it inside 'find_callback' outside of the loop it is fine, but when I'm trying to get it from the function onInit() I get 'undefined'. – Sophia Gavish Jan 02 '11 at 16:14
  • @Sophia: additional properties set on an array are included in `for in` loops. This is a problem if you're using a JS library such as [Prototype](http://www.prototypejs.org/api/array), which adds many additional methods to arrays. Also, [globals are evil](http://www.google.com/search?sourceid=chrome&ie=UTF-8&q=globals+are+bad). Instead, use [closures](http://jibbering.com/faq/notes/closures/) (if you need a simpler explanation, try [Morris Johns's](http://blog.morrisjohns.com/javascript_closures_for_dummies.html)). – outis Jan 02 '11 at 17:10
  • ... Is there supposed to be a difference between the two `find_callback` functions? – outis Jan 02 '11 at 17:11
  • 1
    ... [Code samples](http://sscce.org/) should be self-contained (without being too verbose), so that the exact behavior you're experiencing can be reproduced. See if you can produce a sample without a dependency on Waze. If you can, you know the problem doesn't lie there. – outis Jan 02 '11 at 17:22
  • Each find_callback used for the find function. I have a list of search items that I need to display on a Waze map. The find function cannot get an array but a string so this is why I call it more then once – Sophia Gavish Jan 02 '11 at 17:52
  • each response contains array of objects. I can display all of them on the map but when it called on the 2nd time it displayed only the last markers. – Sophia Gavish Jan 02 '11 at 17:57
  • The sample is a little too verbose (I doubt we need the full implementation of `addPoint`, for one). Did you mean to set `responseArray` to an `Object`, or do you want an array? `Object` doesn't have a `push` method. – outis Jan 03 '11 at 01:59
  • It was a mistake, I want it to be an array. but it does not push the object to the array. I also moved the function find_callback inside closures. – Sophia Gavish Jan 03 '11 at 04:36

1 Answers1

1

g_waze_map.find() is asynchronous, which is why it uses a callback to process results. When find returns, the search results probably aren't available. Instead of calling addPoint from onInit, call it directly in find_callback.

find loads search results in another page, which might be storing the results as a global variable that gets clobbered when later calls reload the page (see why globals are bad?). If that's the case, you can move all but the first call to find to the find callback.

//called when map loads
function onInit(){
    var map = g_waze_map.map;

    var size    = new OpenLayers.Size(15, 20);
    var offset  = new OpenLayers.Pixel(-(size.w/2), -size.h);
    var icon    = new OpenLayers.Icon('http://www.waze.co.il/images/home.png',size,offset);         

    function addPoint(response){
        var first_result = response;
        var lon = response.location.lon;
        var lat = response.location.lat;
        //g_waze_map.map.setCenter(new OpenLayers.LonLat(lon,lat));

        var markersPoint = new OpenLayers.Layer.Markers( "Markers" );
        markersPoint.addMarker(
            new OpenLayers.Marker(
                new OpenLayers.LonLat(lon, lat),
                icon.clone()
        )   );
        g_waze_map.map.addLayer(markersPoint);

        g_waze_map.map.addPopup(
            new OpenLayers.Popup.FramedCloud(
                "point_"+lat, new OpenLayers.LonLat(lon,lat), null,
                "<div style='font-family:Arial,sans-serif;font-size:0.8em;'>"+response.name+"<div>",
                null, true, null
         )  );
    }

    // array for the points; this could be dropped
    var responseArray = [];
    function addPoints(response) {
        // if you want to save the responses for other purposes
        Array.push.apply(responseArray, response);
        for (var i=0, length = response.length; i<length; i++){
            addPoint(response[i]);
        }
    }

    var terms = ['Rome'];
    window.find_callback = function(response){
        addPoints(response);
        if (terms.length) {
            g_waze_map.find(terms.pop(),'find_callback', true);
        }
    }

    g_waze_map.find('Turin','find_callback');
};
Community
  • 1
  • 1
outis
  • 75,655
  • 22
  • 151
  • 221
  • The problem is that it is overrides the previous layers with the find function. for instance, find has many results, I can add many markers in one call from the callback function, but on the second .find call it overrides the previous results. This is why I tried to get all the results into one array. – Sophia Gavish Jan 03 '11 at 06:02
  • @Sophia: are you sure that's what's happening? Did you use an interactive debugger to observe the behavior? My tests on the Waze [example page](http://www.waze.co.il/test_api/) suggest otherwise. A link to a live page of your own would help to reproduce the behavior you describe. `addPoint` should also be moved into the function, and all the variables should be declared local with `var`. – outis Jan 03 '11 at 10:24
  • I will check it, but it the example page does not work as it should. It is displaying only the last query, the last .find call. – Sophia Gavish Jan 03 '11 at 18:26
  • The find_callback must be global or outside the onInit() function. Otherwise it will not find it. This is why the size, offset, icon need to be global. The problem is with the .find() function that overrides the previous markers from the previous .find. Each call can get many points but it can't call more then one .find because it will override the points. – Sophia Gavish Jan 03 '11 at 18:43
  • @Sophia: I see about `find_callback` needing to be global, since it's passed by name to another page to call. However, that doesn't mean it's true of other variables. I'm still not seeing `find` losing points, which is why I need that sample page of your own. Just a guess, but your issue could be because `find` isn't [reentrant](http://stackoverflow.com/questions/2799023/what-exactly-is-a-reentrant-function); perhaps it's using a global (or object property) to store responses. If that's the case, it's time for [CPS](http://marijnhaverbeke.nl/cps/). – outis Jan 03 '11 at 20:32
  • I will use OpenStreetMap instead. The documentation is limited in Waze. Thanks for the help, I really appreciate it! – Sophia Gavish Jan 05 '11 at 16:15