Solved

Show/hide markers on google maps

Posted on 2015-02-19
15
570 Views
Last Modified: 2015-02-24
Hi
I am trying to get markers to show/hide markers from multiple arrays based on user choice.  I have got places priced at 0, <5, >5 <10, and >10 which i want people to be able to hide/show.... to begin with I want to show <5 only.

This is what I have so far
//arrays to populate map with title | lat | lon| price
var venues  = [["Everyone Active Hartham Leisure Centre", 51.800052, -0.077467, 4.2],
                ["Gordons Gym", 51.480226, 0.069589, 3.5],
                ["The Concorde Club", 51.48808, -0.40301, 4.5],
                ["Croydon High Sports Club", 51.341246, -0.061708, 4.5],
                ["Everyone Active Northolt Leisure Centre", 51.548934, -0.375026, 3.9],
                ["Everyone Active Central Park Leisure Centre", 51.602689, 0.228719, 3.8],
                ["Heston Community Sports Hall", 51.480955, -0.365949, 4.3],
                ["Everyone Active Westminster Lodge Leisure Centre", 51.750365, -0.34032, 4.1],
                ["Everyone Active Hornchurch Sports Centre", 51.563842, 0.207556, 3.8],
                ["Everyone Active Watford Woodside Leisure Centre", 51.69484, -0.386208, 4.1],


var bikes =[["River Street , Clerkenwell", 51.52916347, -0.109970527, 0],
                ["Phillimore Gardens, Kensington", 51.49960695, -0.197574246, 0],
                ["Christopher Street, Liverpool Street", 51.52128377, -0.084605692, 0],
                ["St. Chad's Street, King's Cross", 51.53005939, -0.120973687, 0],
                ["Sedding Street, Sloane Square", 51.49313, -0.156876, 0],
                ["Broadcasting House, Marylebone", 51.51811784, -0.144228881, 0],
                ["Charlbert Street, St. John's Wood", 51.53430039, -0.1680743, 0]]



//set venues on map
var map = new google.maps.Map(document.getElementById('map'), {
                    zoom: 14,
                    mapTypeId: google.maps.MapTypeId.ROADMAP
                });

                var center;
                navigator.geolocation && navigator.geolocation.getCurrentPosition(showPosition, showError) == undefined && showError();

                var infowindow = new google.maps.InfoWindow();
                var directionsService = new google.maps.DirectionsService();
                var directionsDisplay = new google.maps.DirectionsRenderer();
                directionsDisplay.setMap(map);

                var marker, i;

				var image_loc = "/images/mapicons/", image_low = image_loc + "markerlow.png", image_med = image_loc + "markermed.png", image_high = image_loc + "markerhigh.png";


                for (i = 0; i < venues.length; i++) {

                    marker = new google.maps.Marker({
                    position: new google.maps.LatLng(venues[i][1], venues[i][2]),
                    map: map,
                    icon: (Math.round(venues[i][3]) < 5) ? image_low : ((Math.round(venues[i][3]) > 10) ? image_high : image_med)
        });

                google.maps.event.addListener(marker, 'mouseover', (function (marker, i) {
                        return function () {
                        infowindow.setContent(venues[i][0] + '<br/>Price: £' + venues[i][3] + '<br><a href="javascript:calcRoute(' + i + ')">How do I get there?</a><br>View on <a href="http://maps.google.com/maps?q=' + venues[i][1] + ',' + venues[i][2] + '">Google Maps</a>');
                        infowindow.open(map, marker);
                    }
                })(marker, i));
                }

///show bikes

				for (i = 0; i < bikes.length; i++) {
					
					var marker = new google.maps.Marker({
                        position: new google.maps.LatLng(bikes[i][1], bikes[i][2])
                    });
					markers.push(marker);					
				}
				
				function showHideMarker(ele){
					setAllMap(null);
					marker = markers[ele];
					marker.setMap(map);
					map.setCenter(new google.maps.LatLng(bikes[ele][1], bikes[ele][2]));
					infowindow.setContent(bikes[ele][0] + '<br/><a href="javascript:calcRoute(' + i + ')">How do I get there?</a><br>View on <a href="http://maps.google.com/maps?q=' + bikes[ele][1] + ',' + bikes[ele][2] + '">Google Maps</a>');
					infowindow.open(map, marker);
					google.maps.event.addListener(infowindow, 'closeclick', function() {  
						setAllMap(null); 
					});
                                            
				}
				
				function setAllMap(val) {
				  for (var i = 0; i < markers.length; i++) {
					markers[i].setMap(val);
				  }
				}
				
				function showAllMarkers() {
					document.getElementById('showAll').disabled = true;
					document.getElementById('removeAll').disabled = false;
					for (var j = 0; j < markers.length; j++) {						
						google.maps.event.addListener(markers[j], 'mouseover', (function (marker, j) {
							return function () {
							infowindow.setContent(bikes[j][0] + '<br/><a href="javascript:calcRoute(' + i + ')">How do I get there?</a><br>View on <a href="http://maps.google.com/maps?q=' + bikes[j][1] + ',' + bikes[j][2] + '">Google Maps</a>');
							infowindow.open(map, marker);
							}
						})(markers[j], j));
					}
					for (var i = 0; i < bikes.length; i++) {
					   bounds.extend(new google.maps.LatLng(bikes[i][1], bikes[i][2]));
					}
					map.fitBounds(bounds);
					setAllMap(map);
				}
				
				function removeAllMarkers() {
					document.getElementById('showAll').disabled = false;
					document.getElementById('removeAll').disabled = true;
					setAllMap(null);
				}

Open in new window


The icons appear on the initial page load but I can't then add in the second array "bikes". Eventually I will want to show/hide based on price but we can get onto that later!

thanks for your help
0
Comment
Question by:lz7cjc
  • 8
  • 7
15 Comments
 
LVL 38

Expert Comment

by:Tom Beck
Comment Utility
See if this gets close. You can add any number of arrays to the mix. No need for separate logic for each array.

http://jsfiddle.net/tommyBoy/0sm2hf17/
0
 

Author Comment

by:lz7cjc
Comment Utility
Looks great on jsfiddle but when I copy/paste over to my local dev environment, the map doesn't appear. I have tried including
<script src="http://maps.google.com/maps/api/js?sensor=true"></script>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=places"></script>

Open in new window


but the map still doesn't appear. It doesn't look like this needs any external libraries but there is clearly something missing; any idea what it might be?

thanks
0
 
LVL 38

Expert Comment

by:Tom Beck
Comment Utility
Make sure your map container div appears in the markup before the script, it has id="map" and it has dimensions.
0
 

Author Comment

by:lz7cjc
Comment Utility
thanks - that works now - why does the HTML come before the js? What determines which comes first?
0
 

Author Comment

by:lz7cjc
Comment Utility
when i try to integrate this with my existing code I am unable to center the map on my current location when it initially loads and to display all the venues by default with their own icon.  

this was my attempt:
var map = new google.maps.Map(document.getElementById('map'), {
                    zoom: 14,
                    mapTypeId: google.maps.MapTypeId.ROADMAP
                });

                var center;
                navigator.geolocation && navigator.geolocation.getCurrentPosition(showPosition, showError) == undefined && showError();

                var infowindow = new google.maps.InfoWindow();
                var directionsService = new google.maps.DirectionsService();
                var directionsDisplay = new google.maps.DirectionsRenderer();
                directionsDisplay.setMap(map);

                var marker, i, markers = [];

				var image_loc = "/images/mapicons/", image_low = image_loc + "markerlow.png", image_med = image_loc + "markermed.png", image_high = image_loc + "markerhigh.png";


                for (i = 0; i < arrays[venues].length; i++) {

                    marker = new google.maps.Marker({
                    position: new google.maps.LatLng(arrays[venues][i][1], arrays[venues][i][2]),
                    map: map,
                    icon: (Math.round(arrays[venues][i][3]) < 5) ? image_low : ((Math.round(arrays[venues][i][3]) > 10) ? image_high : image_med)
        });

                google.maps.event.addListener(marker, 'mouseover', (function (marker, i) {
                        return function () {
                        infowindow.setContent(arrays[venues][i][0] + '<br/>Price: £' + arrays[venues][i][3] + '<br><a href="javascript:calcRoute(' + i + ')">How do I get there?</a><br>View on <a href="http://maps.google.com/maps?q=' + arrays[venues][i][1] + ',' + arrays[venues][i][2] + '">Google Maps</a>');
                        infowindow.open(map, marker);
                    }
                })(marker, i));
                }

Open in new window


The code that follows then has
setmarkers()
createMarker()
calcRoute()
codeAddress()

thanks
0
 
LVL 38

Expert Comment

by:Tom Beck
Comment Utility
The coding for the initialization of the map needs to follow the <div id="map"> in the markup because the markup is interpreted by the browser in order, from top to bottom. If this line of script: var map = new google.maps.Map(document.getElementById('map') is read by the browser before <div id="map"> in the markup, the browser does not know what 'map' refers to.

I don't know where you are getting this piece of code:
var center;
                navigator.geolocation && navigator.geolocation.getCurrentPosition(showPosition, showError) == undefined && showError();
But it's not even valid javascript.

You can use this. You first must check if the geolocation service will even work because not all devices have that capability.

if (navigator.geolocation) {
	navigator.geolocation.getCurrentPosition(function (position) {
		initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
        });
}

Open in new window


initialLocation variable holds the coordinates.

The sequence of events to get all markers plus the current location to display on load should be.

Initialize the map
geocode all addresses
add in the current location (if available)
set markers / create markers / set icons
fit all markers in the map viewport (bounds.extend() and map.fitBounds())

Don't know what you expect with calcRoute(). Route from what to what?
0
 

Author Comment

by:lz7cjc
Comment Utility
ok - so I have created the following function from the code you supplied together with a safety net in case the location can't be picked up from the device:

				function findme() {
					if (navigator.geolocation) {
						navigator.geolocation.getCurrentPosition(function (position) {
						return google.maps.LatLng(position.coords.latitude, position.coords.longitude);
 						});
					} else {
	 					return google.maps.LatLng(51.501364,-0.14189);
					}
				}

Open in new window


I then replaced
center: new google.maps.LatLng(arrays['venues'][0][1], arrays['venues'][0][2]),

Open in new window

with
center: findme()

Open in new window

but still get the map centering on the first item in the array
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 38

Expert Comment

by:Tom Beck
Comment Utility
This line, center: new google.maps.LatLng(arrays['venues'][0][1], arrays['venues'][0][2]), as it appears in my original code, is just a starting point for the initializing the map. It gets overridden by bounds.extend() and map.fitBounds().

See if I have this right. All markers in the array plus the user's current location should appear in the map on load. Then re-center the map on the user's current location. The problem i see with that is, if the user is not somewhere near the middle of the other locations, the map would need to be zoomed out to still include the other markers. Taken to the extreme, if the user is in another country for example, you would wind up with a map of the world where a dozen or so markers are clumped over London.

It's asking for trouble, but let's assume it could be made to work. First you need to correct your findme() function. You have an unnamed function inside a named function. You cannot return a value from the inside function to the outer one in that manner, so do this:
function findme() {
		var initialLocation = new google.maps.LatLng(51.501364,-0.14189);
		if (navigator.geolocation) {
			navigator.geolocation.getCurrentPosition(function (position) {
		            initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
		        });
		} 
		return initialLocation;
	}

Open in new window

The next problem is fitBounds(). It runs asynchronously so you cannot reset the map center until it's finished. The only way I can think to check if it's finished is to add a listener to the bounds_changed event. Keep checking with a setInterval() function until it stops firing. Or, just wait 2 seconds or something before re-centering. Seems like a hack though.

The next problem is if the user's location is not near the middle of the markers and you center the map on that without adjusting the zoom, the markers could be outside the map viewport once again. So what do you do, run map.fitBounds() again? That would change the map center again.

The only way to get this to work would be to include all markers and the user's location in a map, get the coordinates of the map corners, find the corner furthest from the user's location and adjust the zoom to include an area the radius of that distance from the user's location. That's a lot of programming!
0
 

Author Comment

by:lz7cjc
Comment Utility
hmmm thanks for this comprehensive explanation. The only users of this map will be in London - it is a targeted audience for a specific purpose where they will be looking for venues close to their current location, which we can assume is within the London area.

Given those assumptions do we have to use  bounds.x? If we are centering on current location or default location and zoomed to 14, isn't that enough information to set up the map?

I tried removing the bounds.x references and corrected my function but this stopped the map from displaying so I am going to need something a little more sophisticated than that as a solution. What would you suggest?
thanks
0
 
LVL 38

Expert Comment

by:Tom Beck
Comment Utility
A new version of my jsfiddle example.

https://jsfiddle.net/tommyBoy/L9605cab/1/

This example does not include bounds.extend() and map.fitBounds().

Without bounds.extend() and map.fitBounds() you will be guessing at the required zoom level to contain all the markers plus the user's location. For my example, zoom level 9 seems to work best. I came up with a set of coordinates that lands approximately in the center of the clump of markers as the default map center in case findme() comes up empty.

I cannot test the geolocate function on the device I'm using. Even if I could, I'd have to zoom out to a map of the world to see a marker placed where I am (USA).

The example pre-selects "all" for both activities and price so that all markers display on initial load.

My concern for you still is that if the user's location is near the London area but somewhere on the perimeter of the clump of markers and you center the map there, some of the markers will be off the map. To do this right you need more programming as I described in my last post. Maybe you can post another question focused on that.
0
 

Author Comment

by:lz7cjc
Comment Utility
thanks Tom
I'll look to integrate that now and come back to you - for V1 I am not concerned about where they are since the functionality is all about what is near them when they fire up the map.
0
 

Author Comment

by:lz7cjc
Comment Utility
Hi Tom
I have managed to get everything working except the "mylocation" piece. I am displaying a compass in my browser toolbar so it knows to use it, but the code is going into the "else" taking my default value.

I have checked on fiddle and it is doing the same thing

Any ideas?
0
 
LVL 38

Accepted Solution

by:
Tom Beck earned 500 total points
Comment Utility
Try this one. I made many changes, so don't assume anything. The setMarkers() will have to wait upon the success of the geolocation function. Otherwise, the map finishes before the geolocator.

The example is provided as a guide. It is not a highly refined piece of script. It should not be used as is on a live site. Refinements will be up to you or a paid professional.

http://jsfiddle.net/tommyBoy/L9605cab/4/
0
 

Author Comment

by:lz7cjc
Comment Utility
thanks Tom - this is now working as expected. As you suggest it is pretty slow which wasn't a problem before. I will see what I can do to optimise since got no budget to pay for someone; hence my learning as I go... thanks for all your help; really appreciate it.
0
 
LVL 38

Expert Comment

by:Tom Beck
Comment Utility
You are at the mercy of the geolocator and geocode services provided by Google. Nothing else in the script would make it slow.

Thanks for the points.
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

A publishing tool, a Version Control System, or a Collaboration Platform! These can be some of the defining words for the two very famous web-hosting Git repositories: Bitbucket and Github. Git is widely used amongst the programmers and developers f…
Use these top 10 tips to master the art of email signature design. Create an email signature design that will easily wow recipients, promote your brand and highlight your professionalism.
This video teaches users how to migrate an existing Wordpress website to a new domain.
Wufoo.com provides powerful tools for surveying targeted groups, and utilizing data from completed surveys to find trends, discover areas of demand or customer expectation, and make business decisions on products or services.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now