Zoom in into a marker using JavaScript link - javascript

I'm a beginner in google maps and JavaScript.
I'm creating a random markers on google map using Maps API V3, I want to create a list on the side that contain all Markers Id so when i click on Marker ID it will zoom in, on the map to show the marker. specifically i want to know how to create that link in javascript
thank you

This answer is from beginner to beginner ;) I like benastan's answer for succinctness and the application of closure, still I'd like to show a more "basic" approach by writing functions.
I don't feel qualified to talk about closures and function scopes, but I can say from experience these closure "wrappers" prevent unexpected behavior from functions called within loops or within other functions. One such bug could be a loop iterator value ending up all the same value (last iteration) or undefined. (my own example)
Link to full code: http://jsfiddle.net/WaWBw/
Click on the map to place markers, and clicking on markers or links on the side zooms in.
function addMarker(pos) {
var marker = new google.maps.Marker({
map: map,
position: pos
});
markers.push(marker);
count = markers.length - 1;
addMarkerListener(marker, count, 6);
makeDiv(count, 4, "Marker #");
count++;
}
function addMarkerListener(marker, index, zoomLevel) {
google.maps.event.addListener(marker, 'click', function(event) {
zoomIn(index, zoomLevel);
});
}
function makeDiv(index, zoomLevel, content) {
document.getElementById("sidebar").innerHTML += '<div onclick="zoomIn(' + index + ',' + zoomLevel + ')">' + content + ' ' + index + '</div>';
}
function zoomIn(index, zoomLevel) {
map.setCenter(markers[index].getPosition());
map.setZoom(zoomLevel);
}

Say you have a set of lat/lng coordinates:
var coords = [[32, -70], [50, -10], [0, 20]];
Loop through the coordinates, plotting the marker on your map and generating the list items. Bind the click handler at the same time:
var tpl = 'Click here to view a point';
// Loop through coordinates.
for (var i in coords) {
// Create a closure.
(function() {
var pt = coords[i],
latlng = new google.maps.LatLng(pt[0], pt[1]),
marker = new google.maps.Marker({
position: latlng,
map: map // variable containing your google map.
}),
elm = document.createElement('li');
elm.innerHTML = tpl;
// When you click the list item, set map center to latlng of marker.
elm.onclick = function() {
map.setCenter(latlng);
};
document.body.appendChild(elm);
})();
}

Related

Iterate Over Table with jQuery and Create a New Variable from Element Value

I've iterated over a table with javascript so I can use the data as a variable for creating markers on a Google Map. My map and the code that iterates over the table both work, but I cannot figure out how to make the gridmap value available inside my marker variable. I assume I need to do a for loop around my marker variable, which I can probably figure out, I am simple stuck on taking my element variables, and making them available as variables for my markers. Below is my code, if this makes any sense. I've been at this for hours and it is 3:30am; I will refractor the question in the morning if needed. Thank you.
This is the updated and working code:
I iterated over the DOM to grab the <tr> elements from tbody only. Note the tr:gt(0) part - this skips the first header row. Then I create a new array by filtering out the markers against the gdata array. I still need to clean this up a bit add more functionality like clustering, but I am very happy at this point and hopefully this will help someone else.
<script>
function initMap() {
var map;
var table = $("table");
var labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var labelIndex = 0;
var htmlLabel = labels.split(""); // Add Labels to Html Columns for Matching
var gdata = new Array();
$("table tbody tr:gt(0)").each(function (i) {
gdata[i] = new Array();
$(this).children('td').each(function (ii) {
gdata[i][ii] = $(this).text();
});
});
var bounds = new google.maps.LatLngBounds();
var mapOptions = {
mapTypeId: 'satellite',
disableDefaultUI: true,
scrollwheel: false,
draggable: true
};
// Display a map on the page
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
map.setTilt(45);
// Multiple Markers
var markers = [
['a0', 32.840801, -117.244842],
['a10', 32.840801, -117.244842],
['a20', 32.840777, -117.244864],
['a30', 32.840758, -117.244881],
['a40', 32.840732, -117.244899],
['aa0', 32.840828, -117.244794],
['aa10', 32.840828, -117.244794],
['b0', 32.840624, -117.24493],
['b10', 32.840624, -117.24493],
['b20', 32.840594, -117.244928],
['b30', 32.840567, -117.244924],
['b40', 32.840544, -117.244918],
['b60', 32.840544, -117.244918],
['bb0', 32.840495, -117.244897],
['bb10', 32.840495, -117.244897],
['bb20', 32.840468, -117.244885],
['c0', 32.84082, -117.244712],
['c10', 32.84082, -117.244712],
['c20', 32.840815, -117.244729],
['c30', 32.840806, -117.244749],
['c40', 32.840793, -117.244767],
['c50', 32.840779, -117.244789],
['c70', 32.840755, -117.244816],
['cc0', 32.840828, -117.244661],
['cc10', 32.840828, -117.244661],
['d0', 32.840607, -117.244867],
['d10', 32.840607, -117.244867],
['d20', 32.840586, -117.24486],
['d30', 32.840567, -117.244856],
['d40', 32.840543, -117.244841],
['d50', 32.840514, -117.244824],
['dd0', 32.84046, -117.244774],
['dd10', 32.84046, -117.244774],
['e0', 32.840788, -117.244598],
['e10', 32.840788, -117.244598],
['e20', 32.840791, -117.24462],
['e30', 32.840788, -117.244644],
['e40', 32.840787, -117.244665],
['e50', 32.840783, -117.244687],
['e60', 32.84078, -117.244707],
['e70', 32.840769, -117.244729],
['ee0', 32.84078, -117.244539],
['ee10', 32.84078, -117.244539],
['f10', 32.840607, -117.244809],
['f20', 32.840586, -117.244802],
['f30', 32.840564, -117.244785],
['f40', 32.840543, -117.244765],
['f50', 32.840532, -117.244749],
['f60', 32.840519, -117.244731],
['f70', 32.840508, -117.244714],
['ff0', 32.840473, -117.244632],
['ff10', 32.840473, -117.244632],
['g0', 32.840709, -117.244468],
['g10', 32.840709, -117.244468],
['g20', 32.840718, -117.244484],
['g30', 32.840737, -117.244499],
['g40', 32.840739, -117.244515],
['g50', 32.840747, -117.244531],
['h0', 32.840681, -117.244569],
['h10', 32.840681, -117.244569],
['h20', 32.840707, -117.244574],
['i0', 32.840611, -117.24458],
['i10', 32.840611, -117.24458],
['i20', 32.840576, -117.24461]
];
var filteredMarkers = []; // the results array
for (var iii = 0; iii < gdata.length; iii++) // iterate for every marker key
{
filteredMarkers = filteredMarkers.concat(markers.filter(function (item) {
return item[0] == gdata[iii][0];
}));
}
console.log(filteredMarkers);
console.log(gdata);
console.log(markers);
// Info Window Content
var infoWindowContent = [
['<div class="">' +
'<h3>Add Code Here</h3>' +
'<p>Add Code Here</p>' + '</div>']
];
// Display multiple markers on a map
var infoWindow = new google.maps.InfoWindow(), marker, i;
for (i = 0; i < filteredMarkers.length; i++) {
var position = new google.maps.LatLng(filteredMarkers[i][1], filteredMarkers[i][2]);
bounds.extend(position);
marker = new google.maps.Marker({
position: position,
map: map,
title: filteredMarkers[i][0],
label: labels[labelIndex++ % labels.length]
});
// Allow each marker to have an info window
google.maps.event.addListener(marker, 'click', (function (marker, i) {
return function () {
infoWindow.setContent(infoWindowContent[i][0]);
infoWindow.open(map, marker);
}
})(marker, i));
// Automatically center the map fitting all markers on the screen
map.fitBounds(bounds);
}
// Override our map zoom level once our fitBounds function runs (Make sure it only runs once)
var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function (event) {
this.setZoom(24);
google.maps.event.removeListener(boundsListener);
});
}
</script>
It appears you're also using Angular and that the id='gridmap' div is returning the object name and not the content. The nature of the div content looks like the crux of problem and so would suggest looking at this SO question: How to show object property with Angularjs
From here if you can generate HTML that looks something like this below after Angular has done its thing, keeping the property out of view by inserting its elements into data tags:
<tr>
<td> ..... </td>
<td> ..... </td>
<td> ..... </td>
<td class='gridmap' data-lat='23.424' data-lng='-117.233'>a0</td>
</tr>
If you insert the whole object including curly brackets you may have to do additional JSON stringification and parsing which at this point are better avoided.
Note that HTML id labels should only used for unique DOM elements, so if you have more than one table row it should be a class (which also means adjusting your css accordingly)
Now we can use jquery data to interrogate the same HTML cell tag and pass to grLat and grLng variables :
$('tr').each(function (i) {
var $tds = $(this).find('td').eq(8), // moved the eq(8) here
gLabel = htmlLabel[i],
gridmap = $tds.text(),
grLat = Number($tds.data('lat')), // get the lat data
grLng = Number($tds.data('lng')); // get the lng data
console.log(
'Marker:' + gLabel
+ '\nRow:' + (i + 1)
+ '\nGrid Map: ' + gridmap
+ '\nGrid lat: ' + grLat
+ '\nGrid lng: ' + grLng // check components
);
var marker = new google.maps.Marker({
position: {lat: grLat, lng:grLng}, // recomposed object
map: map,
label: labels[labelIndex++ % labels.length],
animation: google.maps.Animation.DROP
});
})
This should put you in a better position to debug

Passing map object to javascript function

In order to add an offset to the center point in Google maps when a button are pressed, I try this funcion:
function offsetCenter(map, marker) {
var worldCoordinateCenter = map.getProjection().fromLatLngToPoint(marker.getPosition());
var pixelOffset = new google.maps.Point((100/scale) || 0,(0/scale) ||0)
var worldCoordinateNewCenter = new google.maps.Point(
worldCoordinateCenter.x - pixelOffset.x,
worldCoordinateCenter.y + pixelOffset.y
);
var newCenter = map.getProjection().fromPointToLatLng(worldCoordinateNewCenter);
map.setCenter(newCenter);
}
});
I call that funcion from infoWindows where map and marker are defined:
(function(marker, data) {
google.maps.event.addListener(marker, "click", function() {
info = '<h4>' + data.nombre + '</h4><h4>'+ data.offerta+'</h4><h4>'+ data.horario+'</h4><a href='+data.web+'><h4>Web</h4></a>'
+ '<input type="button" class = "launchConfirm" onclick="offsetCenter(\''+map+'\', \''+marker+'\');" value='Reset center'></input>' //this is the button inside the infowindos to re-set the map center with an offset
;
infoWindow.setContent(info);
infoWindow.open(map, marker);
map.setCenter(marker.getPosition()); //center the map to marker
map.setZoom(16); //zoom to marker
});
}
But marker and map object are not defined inside the offsetCenter function.
How can pass a map object and marker to that function?
make sure your 'map' variable and your marker manager are in scope >= function scope. this way you will not need to pass in the map.
Use a marker manager to manage your makers. you can then add a unique id to some attribute on your link. when the click comes in you can access the object to get the id, which will allow you to retrieve the maker from the manager. so the code would look something like this:
Info Window Content(shortened for brevity):
var info = '<h4>' + data.nombre + '</h4>'<input type="button" data-markerId="' + SomeMarkerManager.getMarkerId() '" onclick="offsetCenter(this);" value='Reset center'></input>'
var offsetCenter = function (element) {
// get the marker Id
var markerId = $(element).attr("data-marker-id");
// use the markerId to find your marker
var marker = SomeMarkerManager.getMarkerById(markerId);
// now you have access to your map and the clicked marker
}
P.S.
marker managers are out of the scope of this answer. Just search for google maps marker managers.

Onclick infobox - bing map api

I'm having trouble getting the infoboxes for the bing API to open on click from outside the map.
Here is the show infobox function and the function to create the pin/infobox itself:
function displayInfobox(e) {
pinInfobox.setOptions({
title: e.target.Title,
description: e.target.Description,
visible: true,
offset: new Microsoft.Maps.Point(0, 25)
});
pinInfobox.setLocation(e.target.getLocation());
}
function hideInfobox(e) {
pinInfobox.setOptions({
visible: false
});
}
function displayPinsOnMap(results) {
// Creates a collection to store multiple pins
var pins = new Microsoft.Maps.EntityCollection();
//Create the info box for pushpin
var infoboxOptions = {width: 260, height:160};
pinInfobox = new Microsoft.Maps.Infobox(new Microsoft.Maps.Location(0, 0), infoboxOptions);
infoboxLayer.push(pinInfobox);
// Create Pins
for (var i = 0; i < results.length; i++) {
//pushpin location
var position = new Microsoft.Maps.Location(results[i]["Lat"], results[i]["Lon"]);
//Create the pin
if(results[i]["DNC"] == 'DNC') {
var sppins = {htmlContent:"<img src='badsp.png' height='32px'> " };
} else {
var sppins = {htmlContent:"<img src='sppin.png' height='32px'> " };
}
var pin = new Microsoft.Maps.Pushpin(position, sppins);
pin.Title = results[i]["Business Name"];
pin.Description =results[i]["Address"] + "<br>" +
results[i]["City"] + ", " +
results[i]["StateListing"] + "<br>" +
results[i]["Phone"] +
"<br>Fax: " + results[i]["Fax"] +
"<br>Email: " + results[i]["Email"];
Microsoft.Maps.Events.addHandler(pin, 'click', displayInfobox);
function pinclick(i) {
Microsoft.Maps.Events.addHandler(results[i], 'click');
}
//Add pin to the map
map.entities.push(pin);
}
//hide box on map move
Microsoft.Maps.Events.addHandler(map, 'viewchange', hideInfobox);
//add pins/infobox
map.entities.push(pinInfobox);
}
I have a list of items pulled from a JSON file and displayed on the map. Each item creates a pin and info box as well as in a table off to the side of the map. What I need to be able to do is on click of the name of the company from the table I need it to open up the infobox associated with that company. Here is how I did it in the past with Google API - this doesn't seem to work in the same way for Bing (yes I have to use bing).
"<td>"+'<a href="#" onclick="javascript:displayInfobox(' + (i) + ');">' + results[i]["Business Name"] +'<\/a>' + "</td>"
It looks like you have copied the displayInfobox function from some code that is expecting to be trigerred when someone clicks a pushpin because that function has this code:
pinInfobox.setLocation(e.target.getLocation());
the getLocation() method exists on Bing Maps pushpin object but obviously not on your so it will be failing when it gets to that line (your using your browsers debug tools right?). You will need to change that line so that it gets the location for the infobox to show from somewhere, either by having the lat lon as some attribute on your and constructing a new Bing Maps location object using those or by looping through all the pins on the map to find that one that matches your in some way

2 Google Maps Conflicting With Each Other

I am creating a web app that has 2 instances of Google Maps API: one which has many points, and one which only has one point.
They seem to be conflicting with each other, because when I view one page before the other, the other map is not centered in the correct spot.
First Page:
Second Page:
Here is a link to my project: http://jakeserver.com/Apps/BostonLandmarks/B12/index.html
Here is the code that is generating the Google Maps:
var detailsMap = new google.maps.Map(document.getElementById("map_" + this.id), {
zoom: 10,
center: new google.maps.LatLng(landmarkList[rowCount].landmarkGPSNorth, landmarkList[rowCount].landmarkGPSWest),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var detailsInfoWindow = new google.maps.InfoWindow();
var detailsMarker, j;
detailsMarker = new google.maps.Marker({
position: new google.maps.LatLng(landmarksArray[rowCount].landmarkGPSNorth, landmarksArray[rowCount].landmarkGPSWest),
map: detailsMap,
icon: "Icons/red-pin.pdf"
});
detailsInfoWindow.setContent(landmarksArray[rowCount].landmarkName);
detailsInfoWindow.open(detailsMap, detailsMarker);
google.maps.event.addListener(detailsMarker, 'click', (function(detailsMarker, j) {
return function() {
detailsInfoWindow.open(detailsMap, detailsMarker);
}
})(detailsMarker, j));
}
document.getElementById("map_" + this.id).style.height = 300 + "px";
document.getElementById("map_" + this.id).style.width = 300 + "px";
Any ideas?
A long ago I'd a similar problem with a Ajax-Based navigation in a website, each page had a map, the first one working normally, but the next ones had the same problem you're having.
Before displaying the map you should create a new bound object. Just like this:
var bounds = new google.maps.LatLngBounds();
After that. You've to extend the bounds passing your markers positions. Like this:
bounds.extend(marker.position);
And finally, when the map is actually visible and rendered. Run the following lines.
google.maps.event.trigger(secondMapInstance, 'resize');
secondMapInstance.fitBounds(bounds);

Google Maps API - Display info for all markers with same lat/long

I am mapping some concert locations on google maps, using data from Songkick.com's API. I'm making a call to the data using jQuery. When mapping a concert, if a single venue has multiple concerts scheduled, all of the markers are placed in the exact same location. This means that only the marker of the most recent concert is visible, and the google maps infoWindow only displays the data for that most recent concert.
I would like to make it so that all concerts taking place at that exact same lat/long display their info in the infoWindow. So when you click on the marker, all scheduled shows are displayed in the infoWindow, not just the most recent show.
Here is part of my javascript:
function doSearch(locations) {
deleteOverlays();
jQuery.getJSON("http://api.songkick.com/api/3.0/search/locations.json?query=" + locations + "&apikey=XXXXXXXX&jsoncallback=?", function(data){
var id = data.resultsPage.results.location[0].metroArea.id;
jQuery.getJSON("http://api.songkick.com/api/3.0/metro_areas/" + id + "/calendar.json?apikey=XXXXXXXX&jsoncallback=?", function(data){
var bounds = new google.maps.LatLngBounds();
var point;
$.each(data.resultsPage.results.event, function(i, item) {
var event = item;
point = new google.maps.LatLng(
parseFloat(item.location.lat),
parseFloat(item.location.lng));
var marker = new google.maps.Marker({
map : map,
animation: google.maps.Animation.DROP,
position : point
});
markersArray.push(marker);
var contentString = '<p><b>' + item.displayName + '</b></p>' + '<p>' + item.location.city + '</p>';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
google.maps.event.addListener(marker, 'click', function() {
if (currentInfoWindow != null) {
currentInfoWindow.close();
}
infowindow.open(map, marker);
currentInfoWindow = infowindow;
});
To see this application in action, I have set up a temporary website.
http://129.219.78.186/~masgis/tward/songkick/Metro.html
To see what I am talking about, type in the name of a major city, and click a marker that drops. Only the most recent concert will show up.
Thanks in advance, any help is much appreciated.
It looks like the SongKick API call returns a unique ID for each venue. So here's what you can do:
Add each event object to an array.
Pull out unique venue IDs from the events in the array.
Loop through each unique venue ID, pulling out each event with that venue ID, and build the info window string by looping through this subset of events.
Build the marker using the venue info, setting the info window string to the marker.
It's a bit of JavaScript code, nested loops, and a bit of a performance hit, but it should do the trick.

Categories