Google Maps panTo conflicts with addListener - javascript

I have a function that recenters the map around the marker when clicked.
google.maps.event.addListener(marker, 'click', function() {
map.panTo(marker.getPosition());
});
However, this obviously affects the addListener I have when getting the markers:
google.maps.event.addListener(map, 'idle', function() {
$.get("/map.json", function(galleries) {
var bounds = map.getBounds();
for (var i = 0; i < galleries.length; i++) {
var latitude = galleries[i].latitude;
var longitude = galleries[i].longitude;
var position = new google.maps.LatLng(latitude, longitude)
if (bounds.contains(position)){
bindInfobox(map, galleries[i]);
}
}
});
Is there a way to make an exception to the addListener, or another easy way around this? Thanks!

A quick workaround can be remove the event listener before you pan your map and then add the event listener again once the map has finished panning.
// add map idle event at load time
google.maps.event.addListener(map, 'idle', mapIdle);
//remove map idle event and then re-attach the event
google.maps.event.addListener(marker, 'click', function () {
google.maps.event.clearListeners(map, 'idle');
google.maps.event.addListenerOnce(map, 'idle', function () {
//add the idle event once the map has finised panning
google.maps.event.addListener(map, 'idle', mapIdle);
});
map.panTo(marker.getPosition());
});
function mapIdle() {
$.get("/map.json", function (galleries) {
var bounds = map.getBounds();
for (var i = 0; i < galleries.length; i++) {
var latitude = galleries[i].latitude;
var longitude = galleries[i].longitude;
var position = new google.maps.LatLng(latitude, longitude)
if (bounds.contains(position)) {
bindInfobox(map, galleries[i]);
}
}
});
}

Related

javascript event function being called multiple times

I am integrating maps on a webpage with Overlapping Marker Spiderfier on google maps. I added a click listener on the marker as below.
$scope.setMarkers = function() {
for (var i = 0; i < $scope.markers.length; i++) {
$scope.markers[i].setMap($scope.map);
$scope.oms.addMarker($scope.markers[i]);
var marker = $scope.markers[i];
var iw = new google.maps.InfoWindow({
content: ""
});
$scope.oms.addListener('click', function(marker) {
iw.setContent(marker.desc);
iw.open($scope.map, marker);
});
}
};
and it works fine but jshint is giving me error for making function inside loop. So i changed it to.
$scope.setMarkers = function() {
for (var i = 0; i < $scope.markers.length; i++) {
$scope.markers[i].setMap($scope.map);
$scope.oms.addMarker($scope.markers[i]);
$scope.addMarkerEventListener(i);
}
};
$scope.addMarkerEventListener = function(i) {
var marker = $scope.markers[i];
var iw = new google.maps.InfoWindow({
content: ""
});
$scope.oms.addListener('click', function(marker) {
iw.setContent(marker.desc);
iw.open($scope.map, marker);
});
};
now when I am clicking on the marker its opening upto 90 info windows one behind another(i have 90 markers in an array). What am i missing.
you add the same listener each time you add a marker(Note that a listener will not overwrite previously added listeners).
It's sufficient to add 1 listener and to use 1 InfoWindow(except you want to have multiple InfoWindow's open at the same time).
Your first attempt works as expected because you overwrite iw inside the loop.
Possible solution:
//create a single InfoWindow-instance
$scope.iw = new google.maps.InfoWindow();
//add a single click-listener
$scope.oms.addListener('click', function (marker) {
$scope.iw.close();
$scope.iw.setContent(marker.desc);
$scope.iw.open($scope.map, marker);
});
//the loop
for (var i = 0; i < $scope.markers.length; ++i) {
$scope.markers[i].setMap($scope.map);
$scope.oms.addMarker($scope.markers[i]);
}
Demo: http://jsfiddle.net/doktormolle/qoko4425/

IE Issue of Google Maps Marker Animation

I am using google maps api v3.
The Below code i am trying to run , It is working on all Browsers except IE.
Can u please suggest any changes needed to work in IE.
Fiddle Link
My Code is :
var map;
var mapOptions = { center: new google.maps.LatLng(0.0, 0.0), zoom: 2,
mapTypeId: google.maps.MapTypeId.ROADMAP };
var markers = [];
function initialize() {
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
from1 = new google.maps.LatLng(0,0);
to1 = new google.maps.LatLng(30,12);
from2 = new google.maps.LatLng(-30,15);
to2 = new google.maps.LatLng(10,-100);
from3 = new google.maps.LatLng(0,-50);
to3 = new google.maps.LatLng(0,50);
addMarker(from1,to1);
addMarker(from2,to2);
addMarker(from3,to3);
}
function addMarker(pos, dest) {
var marker = new google.maps.Marker({
map: map,
position: pos,
destination: dest
});
google.maps.event.addListener(marker, 'click', function(event) {
fromLat = this.position.lat();
fromLng = this.position.lng();
toLat = this.destination.lat();
toLng = this.destination.lng();
// store a LatLng for each step of the animation
frames = [];
for (var percent = 0; percent < 1; percent += 0.01) {
curLat = fromLat + percent * (toLat - fromLat);
curLng = fromLng + percent * (toLng - fromLng);
frames.push(new google.maps.LatLng(curLat, curLng));
}
move = function(marker, latlngs, index, wait, newDestination) {
marker.setPosition(latlngs[index]);
if(index != latlngs.length-1) {
// call the next "frame" of the animation
setTimeout(function() {
move(marker, latlngs, index+1, wait, newDestination);
}, wait);
}
else {
// assign new route
marker.position = marker.destination;
marker.destination = newDestination;
}
}
// begin animation, send back to origin after completion
move(marker, frames, 0, 20, marker.position);
});
markers.push(marker);
}
google.maps.event.addDomListener(window, 'load', initialize);
After some fiddling it looks like a typing issue. Because you haven't implicitly declared the variable frames as a var ie is unsure that it is an array, thus the error "Object does not support method push".
You simply need to change:
frames = [];
to:
var frames = [];
Tested in ie 8- 10.

Google V3 Add click Listner

I am new to JavaScript, i want to migrate from Google V2 to Google v3, for this i am just changing methods which are used in V2 slightly all are working but when i am trying to change the addListener from V2 to V3 i am facing problems like in v2 same listener is used to put the marker on the map but when it comes to V3 i am not able to put a marker on the map.Here i am posting v2 code and V3 code.Please help me to over come the problem. V2 is :
GEvent.addListener(map, "click", function(marker, point) {
console.debug('after Click map is '+map+' marker is '+marker+' point is '+point);
if (marker) {
if(PolygonMarkers.length == 1){ //Only one marker in the array
map.removeOverlay(PolygonMarkers[0]);
map.removeOverlay(PolygonMarkers[0]);
PolygonMarkers = [];
if(Polygon){map.removeOverlay(Polygon)};
} else{ /*More then one marker*/
var RemoveIndex = -1;
var Remove;
//Search for clicked Marker in PolygonMarkers Array
for(var m=0; m<PolygonMarkers.length; m++)
{
if(PolygonMarkers[m].getPoint().equals(marker.getPoint()))
{
RemoveIndex = m; Remove = PolygonMarkers[m];
break;
}
}
//Shift Array elements to left
for(var n=RemoveIndex; n<PolygonMarkers.length-1; n++)
{
PolygonMarkers[n] = PolygonMarkers[n+1];
}
PolygonMarkers.length = PolygonMarkers.length-1 //Decrease Array length by 1
map.removeOverlay(Remove); //Remove Marker
geofencedetails.drawPolygon(); //Redraw Polygon
}
allMarkers = PolygonMarkers;
} else {
// Adds a new Polygon boundary marker
var markerOptions = { icon: icon, draggable: true };
var marker = new GMarker(point, markerOptions);
PolygonMarkers.push(marker); //Add marker to PolygonMarkers array
map.addOverlay(marker); //Add marker on the map
GEvent.addListener(marker,'dragstart',function(){ //Add drag start event
marker.setImage(icon.image);
polygon_resizing = true;
});
GEvent.addListener(marker,'drag',function(){
geofencedetails.drawPolygon();
}); //Add drag event
GEvent.addListener(marker,'dragend',function(){ //Add drag end event
marker.setImage(icon.image);
polygon_resizing = false;
geofencedetails.drawPolygon();
});
geofencedetails.drawPolygon();
allMarkers = PolygonMarkers;
}
});`
and V3 is
google.maps.event.addListener(map, "click", function(marker, point) {
if (marker) {
//console.debug('marker '+marker.toSource());
if(PolygonMarkers.length == 1){ //Only one marker in the array
map.removeOverlay(PolygonMarkers[0]);
map.removeOverlay(PolygonMarkers[0]);
PolygonMarkers = [];
if(Polygon){
map.removeOverlay(Polygon)
};
}else { /*More then one marker*/
//console.debug('PolygonMarkers.length is '+PolygonMarkers.length);
var RemoveIndex = -1;
var Remove;
//Search for clicked Marker in PolygonMarkers Array
for(var m=0; m<PolygonMarkers.length; m++){
//console.debug('PolygonMarkers['+m+'] '+PolygonMarkers[m]);
if(PolygonMarkers[m].getPosition().equals(marker.getPosition())){
//console.debug('Both are equal ');
RemoveIndex = m;
Remove = PolygonMarkers[m];
break;
}
}
//Shift Array elements to left
for(var n=RemoveIndex; n<PolygonMarkers.length-1; n++){
PolygonMarkers[n] = PolygonMarkers[n+1];
}
PolygonMarkers.length = PolygonMarkers.length-1 //Decrease Array length by 1
/*map.removeOverlay(Remove); //Remove Marker*/
for (var i = 0; i < allMarkers.length; i++ ) {
allMarkers[i].setMap(null);
}
geofencedetails.drawPolygon(); //Redraw Polygon
}
allMarkers = PolygonMarkers;
} else {
//console.debug('In else block');
// Adds a new Polygon boundary marker
var markerOptions = { icon: icon, draggable: true };
//console.debug('1');
var marker = new GMarker(point, markerOptions);
//console.debug('2');
PolygonMarkers.push(marker); //Add marker to PolygonMarkers array
//console.debug('3');
map.addOverlay(marker); //Add marker on the map
//console.debug('4');
GEvent.addListener(marker,'dragstart',function(){ //Add drag start event
//console.debug('5');
marker.setImage(icon.image);
//console.debug('6');
polygon_resizing = true;
});
GEvent.addListener(marker,'drag',function(){
geofencedetails.drawPolygon();
}); //Add drag event
GEvent.addListener(marker,'dragend',function(){ //Add drag end event
marker.setImage(icon.image);
polygon_resizing = false;
geofencedetails.drawPolygon();
});
geofencedetails.drawPolygon();
allMarkers = PolygonMarkers;
}
});
You need to bind the click event to the marker instead of the map.
google.maps.event.addListener(marker, "click", function(event) { .... } );
UI events within the Google Maps API V3 typically pass an event
argument, which can be accessed by the event listener, noting the UI
state when the event occurred. For example, a UI 'click' event
typically passes a MouseEvent containing a latLng property denoting
the clicked location on the map. Note that this behavior is unique to
UI events; MVC state changes do not pass arguments in their events.

How to create new object and store the old in array each time when button clicked? OOP JavaScript

How to each time when click "Create New Poly" button, store last object in array and create a new clean object to draw new separated polyline on the map. I'd like to keep the functionality of the old polylines. Now it is not possible to clean the object. Simplified example presented bellow.
HTML:
<button onclick="create()">Create New Poly</button>
<div id="map" style="width: 500px; height: 400px;"></div>
JS:
var map;
var listener;
var polys = [],
poly = {};
create = function() {
poly = new Poly();
if ( !! listener) google.maps.event.removeListener(listener);
listener = google.maps.event.addListener(map, 'click', function(e) {
poly.addPoint(e.latLng);
});
}
function Poly() {
this.markers = [];
this.setMap(map);
polys.push(this);
}
Poly.prototype = new google.maps.Polyline();
Poly.prototype.addPoint = function(p) {
var m = poly.createMarker(p);
poly.markers.push(m);
poly.getPath().push(p);
}
Poly.prototype.createMarker = function(p) {
var marker = new google.maps.Marker({
position: p
});
marker.setMap(this.getMap());
return marker;
}
$(function() {
map = new google.maps.Map(document.getElementById('map'), {
center: new google.maps.LatLng(48.864715, 10.546875),
zoom: 4,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
});
Demo: JSFIDDLE
Even after doing what Ben Davis suggested http://jsfiddle.net/LxGmR/ it still exhibits the problem.
Which I think is due to all the Ploy objects sharing the same prototype: Poly.prototype = new google.maps.Polyline();. I think the fix is that each new Ploy object needs its own prototype google.maps.Polyline instance.
Which after testing, I have found to be true: http://jsfiddle.net/uhZFE/
Then I looked up how to do this without the wrapper function, I used the method described in the SO answer https://stackoverflow.com/a/6519265/388787 (http://javascript.crockford.com/prototypal.html was also helpful) and produced http://jsfiddle.net/YgSwF/ which is the following; it works as you requested:
var map;
var listener;
var polys = [];
create = function () {
var poly = new Poly();
if ( !! listener) google.maps.event.removeListener(listener);
listener = google.maps.event.addListener(map, 'click', function (e) {
poly.addPoint(e.latLng);
});
polys.push(poly);
}
function Poly() {
google.maps.Polyline.call(this);
this.markers = [];
this.setMap(map);
}
Poly.prototype = Object.create(google.maps.Polyline.prototype);
Poly.prototype.addPoint = function (p) {
var m = this.createMarker(p);
this.markers.push(m);
this.getPath().push(p);
}
Poly.prototype.createMarker = function (p) {
var marker = new google.maps.Marker({
position: p
});
marker.setMap(this.getMap());
return marker;
}
$(function () {
map = new google.maps.Map(document.getElementById('map'), {
center: new google.maps.LatLng(48.864715, 10.546875),
zoom: 4,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
});​
I believe your problem has to do with variable scope. You should declare poly inside the create() function. Also, I think it would make more sense to do the pushing of the created object into the array within the create() function to adhere to separation of concerns.
Also, in your addPoint() function, you're referring to the global poly variable when you should be using "this".
Updated code:
var map;
var listener;
var polys = [];
create = function() {
var poly = new Poly();
if ( !! listener) google.maps.event.removeListener(listener);
listener = google.maps.event.addListener(map, 'click', function(e) {
poly.addPoint(e.latLng);
});
polys.push(poly);
}
function Poly() {
this.markers = [];
this.setMap(map);
}
Poly.prototype = new google.maps.Polyline();
Poly.prototype.addPoint = function(p) {
var m = this.createMarker(p);
this.markers.push(m);
this.getPath().push(p);
}
Poly.prototype.createMarker = function(p) {
var marker = new google.maps.Marker({
position: p
});
marker.setMap(this.getMap());
return marker;
}
$(function() {
map = new google.maps.Map(document.getElementById('map'), {
center: new google.maps.LatLng(48.864715, 10.546875),
zoom: 4,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
});​

Google map with route-trace loading data instead of adding it on click

In this map
http://econym.org.uk/gmap/example_snappath.htm
source:
<script type="text/javascript">
//<![CDATA[
if (GBrowserIsCompatible()) {
var map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(53.7877, -2.9832),13)
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
var dirn = new GDirections();
var firstpoint = true;
var gmarkers = [];
var gpolys = [];
var dist = 0;
GEvent.addListener(map, "click", function(overlay,point) {
// == When the user clicks on a the map, get directiobns from that point to itself ==
if (!overlay) {
if (firstpoint) {
dirn.loadFromWaypoints([point.toUrlValue(6),point.toUrlValue(6)],{getPolyline:true});
} else {
dirn.loadFromWaypoints([gmarkers[gmarkers.length-1].getPoint(),point.toUrlValue(6)],{getPolyline:true});
}
}
});
// == when the load event completes, plot the point on the street ==
GEvent.addListener(dirn,"load", function() {
// snap to last vertex in the polyline
var n = dirn.getPolyline().getVertexCount();
var p=dirn.getPolyline().getVertex(n-1);
var marker=new GMarker(p);
map.addOverlay(marker);
// store the details
gmarkers.push(marker);
if (!firstpoint) {
map.addOverlay(dirn.getPolyline());
gpolys.push(dirn.getPolyline());
dist += dirn.getPolyline().Distance();
document.getElementById("distance").innerHTML="Path length: "+(dist/1000).toFixed(2)+" km. "+(dist/1609.344).toFixed(2)+" miles.";
}
firstpoint = false;
});
GEvent.addListener(dirn,"error", function() {
GLog.write("Failed: "+dirn.getStatus().code);
});
}
else {
alert("Sorry, the Google Maps API is not compatible with this browser");
}
// This Javascript is based on code provided by the
// Community Church Javascript Team
// http://www.bisphamchurch.org.uk/
// http://econym.org.uk/gmap/
//]]>
</script>
You can click and add paths that trace routes.
I would like to use the trace-road-functionality, but pre-define the data using coordinates instead. How would I do this?

Categories

Resources