Multiple marker google map with address input

Do you want to share WYSIWYG Web Builder tips, tricks, tutorials or useful HTML code? You can post it here...
(no questions or problems please, this section is not monitored by support).
Forum rules
This section is to share tips, tricks and tutorials related to WYSIWYG Web Builder.
Please do not post questions or problems here. They will not be answered.

PLEASE READ THE FORUM RULES BEFORE YOU POST:
viewtopic.php?f=12&t=1901
Post Reply
bowlesj
 
 
Posts: 33
Joined: Tue Aug 12, 2014 6:59 pm

Multiple marker google map with address input

Post by bowlesj »

I finally got my google map with mutliple markers page working which I had asked about on another thread. It took me a lot of Google searches to find the initial code then put it all together to get exactly what I wanted so I have dumped the final code below to save people work. If you need address input for multiple pin maps this should save you a few days of work. The only thing that is missing from this example is the PHP code for building the page from an actual database but the method to do that can be found at this link. http://www.w3schools.com/json/json_example.asp (I mention this again in #5 below). This link is the last page of a JSON tutorial.

To get this multi-pin map to work you need to;
1/ put the WWB HTML object onto your page (for those totally new to this stuff it is found in the WWB ToolBox which is on the left side ).
2/ Next you have to use the Properties window of WWB to rename the HTML id to "map_canvas". (the properties window is normally on lower right).
3/ Now dump all the code below into the Page HTML insertion point called "Between <head></head> tags".
3a/ Publish the page and set up a button to call it. You should get a map with 5 pins/markers.
(The WWB "preview in the browser" feature won't work. Probably because you need to be online.)
4/ Use Google searches to study all the commands fully until you understand them (always a wise thing to do in case problems occur). (put a comment on every line as a measure of this)
5/ Study the above page at the link I gave to try and learn how to use your PHP code to create the JSON input to the loop that puts the map pins on the map.

I have done everything except #5 and it works perfectly. I am pretty sure the code at the top will get all the source javascript and CSS properly for you.
I tested the above procedure on another page just to make sure I did not drop any code by accident and it worked perfectly (I am running Google Chrome).
I also did a test with a quote in the location field. For example "Marry's House" and it was okay (no need to escape it with \).

When this shows the map properly you can try these things.
1/ hover over each of the map markers to see the location and address information.
2/ if you click the marker it will use the window.location command to try and call a .php page. So you need to study that and modify your code if you want that type of function.
3/ try adjusting the address and the map should re-size and center perfectly on the next publish of the page and display.
For example, change "600 Young Street" to "4000 Young Street" and your map should be big enough to still show the 5 map markers.
NOTE: Every so often the page will not re-size properly when you are changing addresses like this.
It always seems to work properly if you try again. Why this happens I do not know.
4/ Try submitting only one button by moving out all but the bottom line of JSON data input (obviously comment the lines you move away).
By keeping the bottom line you avoid having to worry about the removal of the comma at the end of the line (it is already not there).
You should get a smaller zoom but not too small. If you remove the code near the bottom of the script below you will see what happens.

Code: Select all

<script type='text/javascript' src='//code.jquery.com/jquery-1.11.1.js'></script>  
<script type='text/javascript' src="http://maps.google.com/maps/api/js?sensor=false&.js"></script>

<!--  
Further tests suggest this command is not needed.
<link rel="stylesheet" type="text/css" href="/css/result-light.css">
I have commented it out because of the problems I mentioned in post #3 below.
-->

<script type='text/javascript'>//<![CDATA[ 

$(window).load(function(){
$(document).ready(function () {
    var DataCnt = 0;
    var map;
    var myOptions = {
        zoom: 1,
        center: new google.maps.LatLng(0, 0),
        mapTypeId: 'roadmap'
    };
    map = new google.maps.Map($('#map_canvas')[0], myOptions);

   //START: hard coded JSON Input Data for doing tests
   var InputData = [
       {"KeyData":"1", "LocData":"Location1,  XXX=5   Address:", "addresses":"300 Queen St W, Toronto, ON, Canada"}, 
       {"KeyData":"45", "LocData":"Location2,  XXX=15   Address:", "addresses":"194 Queen St W, Toronto, ON, Canada"}, 
       {"KeyData":"33", "LocData":"Location3,  XXX=1   Address:", "addresses":"44 King Street, Toronto, ON, Canada"}, 
       {"KeyData":"7", "LocData":"Location4,  XXX=8   Address:", "addresses":"300 Young Street, Toronto, ON, Canada"}, 
       {"KeyData":"22", "LocData":"Location5,  XXX=4   Address:", "addresses":"600 Young Street, Toronto, ON, Canada"}
   ];
   //END: hard coded JSON Input Data for doing tests

    var bounds = new google.maps.LatLngBounds(); //Create the empty bounds
    for (var x = 0; x < InputData.length; x++) {
        $.getJSON('http://maps.googleapis.com/maps/api/geocode/json?address='+InputData[x].addresses+'&sensor=false', null, function (data) {
            var p = data.results[0].geometry.location
            var latlng = new google.maps.LatLng(p.lat, p.lng);
            bounds.extend(latlng); //extend the bounds to include each marker's position

            var marker = new google.maps.Marker({
                position: latlng,
                map: map,
                title: InputData[DataCnt].LocData  + InputData[DataCnt].addresses
            });
            var EachDataKey = InputData[DataCnt].KeyData;
            google.maps.event.addListener(marker, 'click', function() {
               window.location=("frmYourPage.php?GoogleMarkerKey=" + EachDataKey); //Call a page with the record key inside the google marker
					//alert("whatever you want to alert about the button");
            }); 
            DataCnt = DataCnt + 1;
        });
    }

   if (bounds != undefined) {
      map.fitBounds(bounds); //now fit the map to the newly inclusive bounds
   }
	//START: code that resizes your map a bit bigger if you have only one marker and it is way too small. Saves the viewer from having to zoom out
   var listener = google.maps.event.addListener(map, "idle", function() { 
     if (map.getZoom() > 16) map.setZoom(13); 
     google.maps.event.removeListener(listener); 
   });
	//END: code that resizes your map a bit bigger if you have only one marker and it is way too small. Saves the viewer from having to zoom out
});
});//]]>  

</script>
Last edited by bowlesj on Tue Oct 14, 2014 3:02 pm, edited 21 times in total.
User avatar
Pablo
 
Posts: 22422
Joined: Sun Mar 28, 2004 12:00 pm
Location: Europe
Contact:

Re: Multiple marker google map with address input

Post by Pablo »

Thanks for sharing your solution!
bowlesj
 
 
Posts: 33
Joined: Tue Aug 12, 2014 6:59 pm

Re: Multiple marker google map with address input

Post by bowlesj »

I am posting this reply to let people know the types of problems that could happen with the script I posted (and solutions).
I tried the script I posted in post #1 on my notebook from a different site. It was not working.
I use google chrome and I pressed F12 to debug. Debugging is under the source section.
These are the commands having problems and the errors.
<link rel="stylesheet" type="text/css" href="/css/result-light.css">
Error: Failed to find resource. The server responded with a status of 404 (not found)

var p = data.results[0].geometry.location
Error: Uncaught Type Error: Cannot read property 'geometry' of undefined.
I tried the first version of this script on the site where I got it and it is also not working. I know I had this working on my notebook earlier this week at this site as well. I will try the script again at home since it was working fine last night and all the versions I created working toward the final script were working consistently for days (not getting these errors). So I went home, tried the script on my desktop and it works than also from home I tried the script from my notebook and it does not work. I will try to figure out the problem and post the solution if/when I find it.

A bit later I try it from my notebook at home and it starts working all of a sudden. Seems rather strange and it is also not good. I can build my website without Google maps but it will be much harder on the users. So I will probably build it so they can use Google maps and when it is not working they can use the site without the maps.

UPDATE: later it occurred to me that it might be best to grab the map coordinates at the point in time that the database address is updated and put them directly on the database. This way they would always be available (no need to worry about problems at a different server) and the loop to load the map should be a bit faster. In other words only get the coordinates once. I will be setting that up this week and post a second version of the above code but with coordinates. Interestingly enough most of the code examples I found with Google searches were with coordinates and maybe this is the reason why.
bowlesj
 
 
Posts: 33
Joined: Tue Aug 12, 2014 6:59 pm

Re: Multiple marker google map with address input

Post by bowlesj »

After having the problems mentioned in the above post I did a lot of google searches and put together two samples that use coordinates rather than addresses to build the very same map as the example in the first post to this thread. In the end the original and the two sets of code I have included below seem to be working fine (running all about the same speed from what I can tell and working equally well on my notebook offsite and on my desktop). I have only run them on Google Chrome so I can't speak for other browsers. On occasion I will get a blank map but a 2nd attempt seems to resolve it.

Although I have been programming 34+ years and worked with 11 languages before deciding to set up a website I have to admit I am still don't have a good handle on some of the variations in functions that Javascript and jQuery can do. I have never seen a language that appears to have 6 ways to create a function before. So I do not know which of the following approaches is best. If anyone is an expert and wants to explain the differences and the advantages/disadvantages that would be greatly appreciated.

The instruction for installing both of these are basically the same as in post #1. The test data tables are set up differently.

These commands should go in the head section. The rest seems to work equally well in the head or body while running in my localhost environment.

Code: Select all

<script type="text/javascript" src='//code.jquery.com/jquery-1.11.1.js'></script>  
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&.js"></script>
This stylesheet command is not needed for any of the versions of creating the map from what I can see. I see no difference in how the map looks.
I just tried street view and it appears okay without the stylesheet command below

Code: Select all

<link rel="stylesheet" type="text/css" href="/css/result-light.css">
I am probably going to tackle driving one of these versions with a MySql database today. I did a google search "Google Map multiple markers coordinates versus addresses" and found no useful hits. So I may just take the easy route and use the one in the first post unless I can find a reason to use one of the options below.

Code: Select all

<script type="text/javascript" src='//code.jquery.com/jquery-1.11.1.js'></script>  
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&.js"></script>

<script type='text/javascript'>//<![CDATA[ 
$(window).load(function(){
$(document).ready(function () {
    var map;
    var myOptions = {
        zoom: 1,
        center: new google.maps.LatLng(0, 0),
        mapTypeId: 'roadmap'
    };
    map = new google.maps.Map($('#map_canvas')[0], myOptions);

   //START: JSON data for testing
	var J_Data = [
       {"J_Key":"2", "J_Loc":"Loc1 Address=", "J_Adr":"300 Queen St W, Toronto, ON, Canada", "J_Lat":"43.649375", "J_Lng":"-79.39339249999999"}, 
       {"J_Key":"45", "J_Loc":"Loc2 Address=", "J_Adr":"194 Queen St W, Toronto, ON, Canada", "J_Lat":"43.6505479", "J_Lng":"-79.38838799999999"}, 
       {"J_Key":"33", "J_Loc":"Loc3 Address=", "J_Adr":"44 King Street, Toronto, ON, Canada", "J_Lat":"43.7029671", "J_Lng":"-79.5192685"}, 
       {"J_Key":"7", "J_Loc":"Loc4 Address=", "J_Adr":"300 Young Street, Toronto, ON, Canada", "J_Lat":"43.65647939999999", "J_Lng":"-79.3810225"}, 
       {"J_Key":"22", "J_Loc":"Loc5 Address=", "J_Adr":"600 Young Street, Toronto, ON, Canada", "J_Lat":"43.6656275", "J_Lng":"-79.3848651"}
   ];
   //END: JSON data for testing

   var bounds = new google.maps.LatLngBounds(); //Create the empty bounds
   for (var x = 0; x < J_Data.length; x++) {

      //START: Some copy commands that were part of trying to get this to work. The extra fields may not be needed.
      var EachDataKey = J_Data[x].J_Key;
      var EachLoc = J_Data[x].J_Loc;
      var EachLat = J_Data[x].J_Lat;
      var EachLng = J_Data[x].J_Lng;
      var EachAdr = J_Data[x].J_Adr;
      //START: Some copy commands that were part of trying to get this to work. The extra fields may not be needed.

      var latlng = new google.maps.LatLng(EachLat, EachLng);
      bounds.extend(latlng); //extend the bounds to include each marker's position
      var marker = new google.maps.Marker({
         position: latlng,
         map: map,
         id: x,
         title: EachLoc  + EachAdr
      });
      google.maps.event.addListener(marker, 'click', (function(marker, x) {
          return function() {
               alert("Key=" + J_Data[x].J_Key + "  Loc=" + J_Data[x].J_Loc + "  Lat=" + J_Data[x].J_Lat + "  Lng=" + J_Data[x].J_Lng);
               //window.location=("frmXXXScheduleQuery.php?GoogleMapKey=" + J_Data[x].J_Key);
          }
      })(marker, x)); 
   }

   if (bounds != undefined) {
      map.fitBounds(bounds); //now fit the map to the newly inclusive bounds
   }
	
   //START: Code to increase map size if only 1 marker is on the page
   var listener = google.maps.event.addListener(map, "idle", function() { 
     if (map.getZoom() > 16) map.setZoom(13); 
     google.maps.event.removeListener(listener); 
   });
   //END: Code to increase map size if only 1 marker is on the page

});
});//]]>  
</script>

Code: Select all

<script type="text/javascript" src='//code.jquery.com/jquery-1.11.1.js'></script>  

<script>
jQuery(function($) {
    // Asynchronously Load the map API 
    var script = document.createElement('script');
    script.src = "http://maps.googleapis.com/maps/api/js?sensor=false&callback=initialize";
    document.body.appendChild(script);
});

function initialize() {
    var map;
    var bounds = new google.maps.LatLngBounds();
    var mapOptions = {
        mapTypeId: 'roadmap'
    };
                    
    // Display a map on the page
    map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);


    //START: Info Window Content code you might want to use ===========================================
    /*
    var infoWindowContent = [
        ['<div class="info_content">' +
           '<h3>London Eye</h3>' +
              '<p>The London Eye is a giant Ferris wheel situated</p>' +
        '</div>'],
        ['<div class="info_content">' +
           '<h3>Palace of Westminster</h3>' +
              '<p>The Palace of Westminster is the meeting.</p>' +
        '</div>']
    ];
    var infoWindow = new google.maps.InfoWindow(), marker, i;
    */
    //END: Info Window Content code you might want to use ===========================================

    // Multiple Markers
    var markers = [
        ["2","Location1","  Address=", "300 Queen St W, Toronto, ON, Canada", 43.649375,-79.39339249999999],
        ["45","Location2","  Address=", "194 Queen St W, Toronto, ON, Canada", 43.6505479,-79.38838799999999],
        ["33","Location3", "  Address=", "44 King Street, Toronto, ON, Canada", 43.7029671,-79.5192685],
        ["7","Location4", "  Address=", "300 Young Street, Toronto, ON, Canada", 43.65647939999999,-79.3810225],
        ["22","Location5", "  Address=", "600 Young Street, Toronto, ON, Canada", 43.6656275,-79.3848651],
    ];
                        
    // Loop through our array of markers & place each one on the map  
    for( i = 0; i < markers.length; i++ ) {
        var position = new google.maps.LatLng(markers[i][4], markers[i][5]);
        bounds.extend(position);
        
        marker = new google.maps.Marker({
            position: position,
            map: map,
            title: markers[i][1] + markers[i][2] + markers[i][3]
        });
        
        google.maps.event.addListener(marker, 'click', (function(marker, i) {
            return function() {
					//START: code that I was using during debugging
               var EachDataKey = markers[i][0];
               var EachLoc = markers[i][1];
               var EachLat = markers[i][4];
               var EachLng = markers[i][5];
               var Message = EachDataKey + " - " + EachLoc + "  Lat=" + EachLat + "  Lng=" + EachLng;
					//END: code that I was using during debugging
               alert(Message);
               //window.location=("frmXXXScheduleQuery.php?GoogleMapKey=" + EachDataKey);
               //START: code to create a content popup window
               //infoWindow.setContent(infoWindowContent[i][0]);
               //infoWindow.open(map, marker);
               //END: code to create a content popup window
            }
        })(marker, i));

        // Automatically center the map fitting all markers on the screen
        map.fitBounds(bounds);
    }

   var listener = google.maps.event.addListener(map, "idle", function() { 
     if (map.getZoom() > 16) map.setZoom(13); 
     google.maps.event.removeListener(listener); 
   });
    
}
</script>
bowlesj
 
 
Posts: 33
Joined: Tue Aug 12, 2014 6:59 pm

Re: Multiple marker google map with address input

Post by bowlesj »

I just found out that the google map script in post number 1 works perfectly if called from a different page than itself. However if you refresh the page or call the page from itself (even with a different set of addresses) it does not work. However both of the versions which are based upon coordinates do work if you refresh the page or call the page again from itself. I am on a google maps forum to try and find a solution to the problem.
bowlesj
 
 
Posts: 33
Joined: Tue Aug 12, 2014 6:59 pm

Re: Multiple marker google map with address input

Post by bowlesj »

Considering the problem mentioned in the post immediately above I decided to put the map coordinates on my database so I could use the 2nd set of code above which allows me to change the city at the top of the page and produce a new map on that same page. It also allows me to simply refresh the page if it appears blank which it does on occasion (the refresh should fix it).

Related to getting the address coordinates for placement on the database, when the user enters or updates the address information they are forced to click a button to create a map so they can verify it. I did this because Google will at times surprise you if there is more than one street with the same name in a city. I was lucky to hit this problem almost immediately. The button click calls the function below which gets the coordinates for putting on the MySql database. It uses these coordinates to also displays the map for user verification. To get it to work I had to delay the code that produces the map since it was running too fast to pick up the coordinate data that had been placed on the screen in hidden fields within the form. I used a 500 millisecond delay. I used my own CSS to hide those lat/lng fields on the form. These fields are in the form so I can submit the coordinates for the database update.

I cleaned up this code a bit. I did it carefully. I believe it should still work. You just have to insert the ExitBoxes on your page, the HTML from the WWB tool box for the map and the button to test it. I restricted my cleanup a bit so there is some code I used for debugging still in the sample below. I was using Google chrome F12 source section to debug.

I am finished all the google map work now. Later I will test all this code on other browsers. I probably won't post here again unless problems show up and these scripts needs adjustment.

Code: Select all

<script type='text/javascript' src='//code.jquery.com/jquery-1.11.1.js'></script>  
<script type='text/javascript' src="http://maps.google.com/maps/api/js?sensor=false&.js"></script>

<style>
#Editbox_Lat {
   visibility: hidden;
}

#Editbox_Lng {
   visibility: hidden;
}

</style>


<script>
function funcSetCoordinatesShowMap() {
   //START: set long and lat
   var lat1;
   var lng1;
      var user1Location = document.getElementById("Editbox_JL_Address1").value + " " + document.getElementById("Editbox_JL_Address2").value;
      var geocoder = new google.maps.Geocoder();
      //convert location into longitude and latitude
      geocoder.geocode({
          address: user1Location
      }, function(locResult) {
          var lat1 = locResult[0].geometry.location.lat();
          var lng1 = locResult[0].geometry.location.lng();
          document.getElementById('Editbox_Lat').value = lat1;
          document.getElementById('Editbox_Lng').value = lng1;
      });
   //END: set long and lat
//START: Original Map Drawing with JSON and MapCoordinates but with a timer delay which gives time to fill out the coordinate fields
   setTimeout(function(){
    var DataCnt = 0;
    var map;
    var marker;
    var myOptions = {
        zoom: 1,
        center: new google.maps.LatLng(0,0),
        mapTypeId: 'roadmap'
    };
    map = new google.maps.Map($('#map_canvas')[0], myOptions);



   var FullAddress = document.getElementById("Editbox_JL_Address1").value + " " + document.getElementById("Editbox_JL_Address2").value;
   var MyKey = document.getElementById('Editbox_fldJL_Key').value;
   var MyLoc = document.getElementById('Editbox_fldJL_Name').value;
   var MyAdr = FullAddress;

	//START: define the JSON with temp values avoiding complex parsing problems - can be done because only one record is going into the JSON
   var J_Data = [
      {
         "J_Key":"TempKey",
         "J_Loc":"TempName",
         "J_Adr":"TempAdr",
         "J_Lat":"0",
         "J_Lng":"0",
      }
   ];
	//END: define the JSON with temp values avoiding complex parsing problems - can be done because only one record is going into the JSON

	//START:: load the one element JSON table
   J_Data[0].J_Key = MyKey;
   J_Data[0].J_Loc = MyLoc;
   J_Data[0].J_Adr = MyAdr;
   J_Data[0].J_Lat = document.getElementById('Editbox_Lat').value;
   J_Data[0].J_Lng = document.getElementById('Editbox_Lng').value;
	//END: load the one element JSON table

	//Debugging with Google Chrome F12 just to make sure the JSON was actually getting loaded.
   var MyLat = J_Data[0].J_Lat;
   var MyLng = J_Data[0].J_Lng;
   var MyLength = J_Data.length;

    var bounds = new google.maps.LatLngBounds(); //Create the empty bounds
   for (var x = 0; x < J_Data.length; x++) {

      //START: of commands that are probably not needed.
      var EachLoc = J_Data[x].J_Loc;
      var EachAdr = J_Data[x].J_Adr;
      var EachLat = J_Data[x].J_Lat;
      var EachLng = J_Data[x].J_Lng;
      //END: of commands that are probably not needed.

      var latlng = new google.maps.LatLng(EachLat, EachLng);
      bounds.extend(latlng); //extend the bounds to include each marker's position
      var marker = new google.maps.Marker({
         position: latlng,
         map: map,
         id: x,
         title: EachLoc  + EachAdr
      });

      google.maps.event.addListener(marker, 'click', (function(marker, x) {
          return function() {
               alert("Key=" + J_Data[x].J_Key + "  Loc=" + J_Data[x].J_Loc + "  Lat=" + J_Data[x].J_Lat + "  Lng=" + J_Data[x].J_Lng);
               //window.location=("frmXXXScheduleQuery.php?GoogleMapKey=" + J_Data[x].J_Key);
          }
      })(marker, x)); 
   }

   map.fitBounds(bounds); //now fit the map to the newly inclusive bounds

   //START: code to resize the map if there is only one marker on it - in this example there always is one marker and it still needs to use this code
   var listener = google.maps.event.addListener(map, "idle", function() { 
     if (map.getZoom() > 16) map.setZoom(13); 
     google.maps.event.removeListener(listener); 
   });
   //END: code to resize the map if there is only one marker on it - in this example there always is one marker and it still needs to use this code


},500)
//END: Original Map Drawing with JSON and MapCoordinates but with a timer delay which gives time to fill out the coordinate fields
} //End of funcSetCoordinatesShowMap() which has a timer call at the end

</script>
Post Reply