views:

170

answers:

3

I'm currently working on a Google Maps project and am implementing a search function. In my search function I'm trying to have content on the side listing which search makers that were just added to the map correspond to each hall. However in assembling this string I run into a problem where my side_bar_html variable will not output if I do not alert the data first.

Here is my searchMap function. The variable is declared as such: var side_bar_html = "";

function searchMap(term, map) {

closeSearch();  

searchCount = 0;
searchMarkers = [];

var request = GXmlHttp.create();

    request.open("GET", "admin/search.php?s=" + term, true);

    request.onreadystatechange = function() {

    if (request.readyState == 4) {

        var xmlDoc = GXml.parse(request.responseText);
  var points = xmlDoc.documentElement.getElementsByTagName("point");

  var polygonsToShow = [];
  for (var i = 0; i < points.length; i++) {                         
   var lat = parseFloat(points[i].getAttribute("lat"));
   var lng = parseFloat(points[i].getAttribute("lng"));
   var pid = points[i].getAttribute("id");
   for(var j = 0; j < polygons.length; j++) {
    if(polygons[j].vt_bid == pid) {
     polygonsToShow.push(j);
    }
   }
   var point = new GLatLng(lat,lng);   
   var pname = points[i].getAttribute("name");
   var curMarker = createSearchMarker(point, pid, pname,getLetter(i));     
   map.addOverlay(curMarker);
  }
  //olays.buildings.checked = false; : Figure out some way to uncheck the buildings overlay checkbox?
  for(var k = 0; k < polygons.length; k++) {
   polygons[k].hide();
  }

  for(var l = 0; l < polygonsToShow.length; l++){ 
   polygons[polygonsToShow[l]].show();
  }
    }
}

request.send(null);
alert(side_bar_html); //side_bar_html will be empty unless I alert the variable


searchResults = new HtmlControl('<div style="background-color:white; border:solid 1px grey; padding:2ex; overflow:auto; width:125px; margin:1px;  font-size:14px;"><img align="right" style="cursor: pointer;" src="http://www.thebort.com/maps/images/close.gif" onclick="closeSearch()"><strong>Search</strong><br/>' + side_bar_html + '</div>', {selectable:true});
map.addControl(searchResults, new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(20, 70)));

}

And the function to create a search marker:

function createSearchMarker(point, id, pname, letIcon) {
    var marker = new GMarker(point,letIcon);
    GEvent.addListener(marker, "click", function() {         
        marker.openInfoWindowHtml('<a href="#" onclick=\'tb_show("' + pname + '","admin/get_info.php?b=' + id + '&KeepThis=true&TB_iframe=true&height=400&width=600",false); return false;\'>' + pname + '</a>');

     });

side_bar_html = side_bar_html + '<a href="javascript:clickSearch(' + searchCount + ')">' + String.fromCharCode("A".charCodeAt(0) + searchCount) + ': ' + pname + '</a><br>';
marker.vt_id = id;
    searchMarkers.push(marker);
searchCount++;

    return marker;
 }

I would like to keep code exposure for this project at a minimum right now so if anything needs expounding please let me know. Thanks!

+3  A: 

So my understanding of your problem is that side_bar_html is set during the onreadystatechange function call, but you're not seeing it being set unless you alert it.

Here's what's probably happening: the Ajax request takes some time to happen. When you call req.send(null) then that kicks off the request, but your onreadystatechange function won't get called until sometime later, after your web browser has made the request and gotten back a response.

So when you immediately try to use the side_bar_html value, it doesn't work because the response hasn't come back yet. However, when you alert the value, the time it takes to perform the alert gives the browser time to get a response and set the side_bar_html value appropriately.

Your underlying problem is that Ajax is asynchronous (which is there the A comes from) and you're trying to use it synchronously (meaning that you assume that things will always happen in a particular order). Your best bet is to put the code that uses side_bar_html in your onreadystatechange function, so that it doesn't get used before it's set.

Eli Courtwright
A: 

How would you suggest allowing time for the request to work or how to check for when it is done?

bharatk
Use the "add comment" link on the answer you're replying to. And you'll know when it's done because your readystatechange handler will run - build the string, then trigger whatever additional logic you need.
Shog9
I've added a paragraph to my answer explaining that I think you should put the code that uses side_bar_html into your onreadystatechange function.
Eli Courtwright
Awesome, you nailed it.
bharatk
A: 

add the code below to the end of your onreadystatechange function (within the if statement checking for a value of 4). e.g:

request.onreadystatechange = function() {

if (request.readyState == 4) {

    var xmlDoc = GXml.parse(request.responseText);
            var points = xmlDoc.documentElement.getElementsByTagName("point");

            var polygonsToShow = [];
            for (var i = 0; i < points.length; i++) {                                                       
                    var lat = parseFloat(points[i].getAttribute("lat"));
                    var lng = parseFloat(points[i].getAttribute("lng"));
                    var pid = points[i].getAttribute("id");
                    for(var j = 0; j < polygons.length; j++) {
                            if(polygons[j].vt_bid == pid) {
                                    polygonsToShow.push(j);
                            }
                    }
                    var point = new GLatLng(lat,lng);                       
                    var pname = points[i].getAttribute("name");
                    var curMarker = createSearchMarker(point, pid, pname,getLetter(i));                             
                    map.addOverlay(curMarker);
            }
            //olays.buildings.checked = false; : Figure out some way to uncheck the buildings overlay checkbox?
            for(var k = 0; k < polygons.length; k++) {
                    polygons[k].hide();
            }

            for(var l = 0; l < polygonsToShow.length; l++){ 
                    polygons[polygonsToShow[l]].show();
            }

            searchResults = new HtmlControl('<div style="background-color:white; border:solid 1px grey; padding:2ex; overflow:auto; width:125px; margin:1px;  font-size:14px;"><img align="right" style="cursor: pointer;" src="http://www.thebort.com/maps/images/close.gif" onclick="closeSearch()"><strong>Search</strong><br/>' + side_bar_html + '</div>', {selectable:true});
            map.addControl(searchResults, new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(20, 70)));
}
Jared