Why mouseover event not dispatching for polyline in google map? - javascript

I've a complex flow where I've to attach mouseover event for every polyline on the map. The code for attaching the event is simple:
google.maps.event.addListener(polyline, "mouseover", function() {
console.log('event fired');
});
But the event is attaching to few polylines and not to others. What might be the reason?
Edit
Following is some more code that is before the above code and used for defining polyline:
this.polyline = new google.maps.Polyline({
path : [fromPosition, toPosition],
strokeColor : '#CCCCCC',
strokeOpacity : 1.0,
strokeWeight : 2
});
var polyline = this.polyline;
Edit 05-Apr-2012
Following is the code that creates problem, Please explain why it's happening and recommend any solution. Thanks
function Link(from, to) {
this.from = from;
this.to = to;
}
Link.prototype.show = function() {
this.line = new google.maps.Polyline({
path : [this.from, this.to],
strokeColor : "#0000FF",
strokeOpacity : 0.5,
strokeWeight : 6
});
this.line.setMap(map);
google.maps.event.addListener(this.line, 'mouseover', function() {
this.line.setOptions({
strokeOpacity : 1
});
});
google.maps.event.addListener(this.line, 'mouseout', function() {
this.line.setOptions({
strokeOpacity : 0.5
});
});
}
var links = [];
var link2 = new Link(new google.maps.LatLng(-3.5999999999999996, 23.4), new google.maps.LatLng(-4.5, 23.4)), link1 = new Link(new google.maps.LatLng(-3.5999999999999996, 23.4), new google.maps.LatLng(-3.5999999999999996, 18));
links.push(link1);
links.push(link2);
// I've a long list of links, so I'll prefer a loop
for(var i = 0; i < links.length; i++) {
links[i].show();
}
JSFiddle Demo : http://jsfiddle.net/wasimbhalli/9bg6x/

demo: http://jsfiddle.net/kbngxku9/
var map;
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(-3, 23),
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('mapcanvas'), mapOptions);
var bounds = [];
var bounds_group_1 = [new google.maps.LatLng(-3.5999999999999996, 23.4), new google.maps.LatLng(-4.5, 23.4)],
bounds_group_2 = [new google.maps.LatLng(-3.5999999999999996, 23.4), new google.maps.LatLng(-3.5999999999999996, 18)];
bounds.push(bounds_group_1);
bounds.push(bounds_group_2);
for (var i = 0; i < bounds.length; i++) {
addPolylineSegment(bounds[i]);
}
}
function addPolylineSegment(bounds) {
// optionally you can put each polyline
// segment into an array to later use...
var polyline;
polyline = new google.maps.Polyline({
path: bounds,
strokeColor: "#0000FF",
strokeOpacity: 0.5,
strokeWeight: 6
});
polyline.setMap(map);
// attach event listener to each segment...
google.maps.event.addListener(polyline, 'mouseover', function(event) {
this.setOptions({
strokeOpacity: 1
});
});
google.maps.event.addListener(polyline, 'mouseout', function(event) {
this.setOptions({
strokeOpacity: 0.5
});
});
}
google.maps.event.addDomListener(window, 'load', initialize);

OK, I'm trying to keep the solution close to your code. The key was changing both listener's this.line.setOptions to this.setOptions:
google.maps.event.addListener(this.line, 'mouseover', function() {
this.setOptions({
strokeOpacity : 1
});
});
google.maps.event.addListener(this.line, 'mouseout', function() {
this.setOptions({
strokeOpacity : 0.5
});
});
I've seen a similar case with markers in another question. I believe this inside the function() already refers to the first argument of addListener(), in this case, this.line, so you are covered just saying this. Here is the jsfiddle:
http://jsfiddle.net/zfFsD/
The other change I made was putting the links[] code in my initialize(). Wish you the best!

I think you have a scope problem.
change
this.line.setOptions
with
this.setOptions
Firebug and console.log() are your friends :)

I managed to work around this using the method described below. If I understood you correctly, the loop in which you attach a listener to a polyline does not in fact get "attached" to the polyline that way, but instead, you need a new class instance that contains the polyline and the listeners. This way, each polyline gets it's own listener.
Please, see the explanation below.
EDIT 5.4.2012
Here's also a crude JSFiddle demonstration of the code in action. Link to JSFiddle demo
function initialize() {
// initialize Google Maps canvas normally
var polylines = [];
// Data set of the polylines you want to present on the map,
// e.g. [ { lat:"...",lon:"..." }, ...]
var polylineData = [{ ... }]
for ( i in polylineData ) {
var line = new google.maps.Polyline({
path: [/*coordinates as google.maps.LatLng objects*/]
});
// Create a new myPolyLineClass instance that contains the polyline data
// and push it to polylines array.
polylines.push(new myPolyLineClass(line));
}
// Set all the polylines and their individual listeners on map
for ( i in polylines) {
polylines[i].line.setMap(map);
}
}
function MyPolylineClass(lineData) {
this.line = lineData;
// + all other data you want the polylines to contain
// Add listeners using google.maps.event.addListener to all class instances
// when they are constructed.
// for instance:
google.maps.event.addListener(line, 'mouseover', function() {
line.setOptions({ [options you want to set when area is hovered
and selected] });
});
// Add listeners also for when polyline is not hovered anymore, respectively,
// and other methods you might want to call when polylines are being interacted with.
};
Hope this helps!
Cheers

Related

Preview of polyline drawing each coordinate by coordinate in google maps

I have created an application in googlemap with poly-line, The application is working fine with the polyline drawn perfectly, But the problem is that i need to draw and show the preview of poly-line, drawing each coordinate by coordinate in google-maps
how can we achieve this? I have tried with setInterval(commented within my code) but its not working properly
Can anyone please tell me some solution for this
$scope.autoRefresh = function() {
try {
//
routePoints = [];
if (!_.isEmpty(items)) {
angular.forEach(items, function(cordinates) {
//setInterval(function ()
//{
routePoints.push(new google.maps.LatLng(cordinates.lat, cordinates.lng));
var route = new google.maps.Polyline({
path: routePoints,
strokeColor: '#FF0000',
strokeOpacity: 2.0,
strokeWeight: 3,
editable: false
});
route.setMap(map);
moveMarker(map, marker, cordinates.lat, cordinates.lng);
markLAT = cordinates.lat;
markLNG = cordinates.lng;
//}, 1000);
});
}
//
} catch (e) {
console.log(e);
}
};
Plunker
setInterval is not the right method, you must use setTimeout, otherwise the functions will run endless(until the browser will crash)
you must increment the delay for setTimeout, otherwise you will not see an animation(all functions will be executed with a delay, but at the same time...after 1 second)
don't create a new Polyline on each function call, you'll have a lot of Polylines at the end(1 for each item) . Create a single Polyline and push the locations to the path of the Polyline
$scope.autoRefresh = function() {
try {
var route = new google.maps.Polyline({
path: [],
strokeColor: '#FF0000',
strokeOpacity: 2.0,
strokeWeight: 3,
editable: false,
map:map
}),
index=0,
marker=new google.maps.Marker({map:map,icon:icon});
if (!_.isEmpty(items)) {
angular.forEach(items, function(cordinates) {
setTimeout(function ()
{
route.getPath().push(new google.maps.LatLng(cordinates.lat, cordinates.lng));
route.setMap(map);
moveMarker(map, marker, cordinates.lat, cordinates.lng);
markLAT = cordinates.lat;
markLNG = cordinates.lng;
}, 200*++index);
});
}
//
} catch (e) {
console.log(e);
}
};
Plunker

GoogleMaps addlistener zip popup?

Alright, this has been a problem for me for 3 days, javascript closures are just not my strong suit.
I have a google map which I've applied an overlay with a series of clickable polygons. I want a specific function to run depending on the polygon clicked, which I have working. The problem is I can't figure out how to work the listener so that a function that displays an infowindow with that polygon's zip code in it. Here's the code:
for (x = 0; x < 50 && coordsObject.length > x; x++) { //Only draw 50 polygons at a time
...
//create zipcoords array
clickablePolygons.push(new google.maps.Polygon({
paths: zipCoords
, strokeColor: "#000"
, strokeOpacity: 1
, strokeWeight: 1
, fillColor: convertRatingToHex(rating)
, fillOpacity: 0.45
}));
infoWindow.push(
new google.maps.InfoWindow({
content: '<div id="gcontent">' + zip.toString() + '</div>'
})
);
//problem child
var theFunction = function(arguments, infowindow, map) {
var marker = new google.maps.Marker({
position: arguments[0].latLng
});
infowindow.open(map, marker);
};
google.maps.event.addListener(clickablePolygons[clickablePolygons.length - 1], 'click', function() {
theFunction(arguments, infoWindow[x], map); //:(
});
clickablePolygons[clickablePolygons.length - 1].setMap(map);
}
What am I doing wrong with the closure?
in your addListener call you have function() and not function(arguments). I would also create a variable pointing to the infoWindow outside the call to addlistener. The assumption is that the click event will pass in the arguments that you are expecting. It may need to be function(e,arguments).
var win = infoWindow[x];
google.maps.event.addListener(clickablePolygons[clickablePolygons.length - 1], 'click', function(arguments) {
theFunction(arguments, win, map);
});
Looks like variable scoping problem, give it a try
(function(x){
google.maps.event.addListener(clickablePolygons[clickablePolygons.length - 1], 'click', function(arg) {
theFunction(arg, infoWindow[x], map);
});
})(x);
You do not need multiple instances of an InfoWindow. Just use the methods to set the content and position when needed.
I do not understand why you are adding a marker, is that a requirement? If you just want an InfoWindow to show when the polygon is clicked you can use the MouseEvent object passed from the click event to get the current position of the click.
Here is an example: http://jsfiddle.net/bryan_weaver/akLBM/
code in the link:
var map;
var infoWindow;
var clickablePolygons = [];
function createPolygon(path, stateName) {
var poly = new google.maps.Polygon({
paths: path,
strokeColor: "#000",
strokeOpacity: 1,
strokeWeight: 1,
fillColor: "#330000",
fillOpacity: 0.45
});
//add the polygon to the array, to use later if needed.
clickablePolygons.push(poly);
//attach a click event, the first argument of the listener is the event
//you can get the position of the mouse cursor where the map
//was clicked through this.
google.maps.event.addListener(poly, "click", function (event) {
//call the setContent method and set the content for the info window
infoWindow.setContent("This state is: " + stateName);
//set the anchor of the info window, in this case
//I am using the mouse position at
//the time of the click
infoWindow.setPosition(event.latLng);
//open the info window, passing the map in which to attach it to.
infoWindow.open(map);
});
//add the polygon to the map
poly.setMap(map);
}
function initialize() {
var myLatLng =
new google.maps.LatLng(39.983994270935625, -111.02783203125);
var mapOptions = {
zoom: 5,
center: myLatLng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
//polygon coords for Utah
var utah = [
new google.maps.LatLng(41.983994270935625, -111.02783203125),
new google.maps.LatLng(42.00032514831621, -114.01611328125),
new google.maps.LatLng(36.96744946416931, -114.01611328125),
new google.maps.LatLng(37.00255267215955, -109.0283203125),
new google.maps.LatLng(40.97989806962013, -109.0283203125),
new google.maps.LatLng(41.0130657870063, -111.02783203125)];
//polygon coords for Colorado
var colorado = [
new google.maps.LatLng(40.96330795307351, -109.05029296875),
new google.maps.LatLng(36.96744946416931, -109.0283203125),
new google.maps.LatLng(37.02009820136811, -101.9970703125),
new google.maps.LatLng(40.97989806962013, -102.06298828125)];
map = new google.maps.Map($('#map')[0], mapOptions);
//create a single info window for use in the application
infoWindow = new google.maps.InfoWindow();
//add the polygon and infowindow content to the map.
createPolygon(utah, "Utah");
createPolygon(colorado, "Colorado");
}
google.maps.event.addDomListener(window, 'load', initialize);

Google Maps v3 - zoom in/zoom out able to repeat (and recenter)?

I have a Google map with multiple POLYGON areas. I have figured out how to ZOOM IN with a single click on the polygon, and ZOOM OUT with a 'dblclick' listener and remove the listeners for them...
Once you have clicked to Zoom In, then double clicked to Zoom Out, it's not allowing me to repeat the function again. Is there a way to zoom in and out multiple times?
Here is the code I have:
//POLYGON ZONE 1 ================================
var zone1;
var triangleCoords = [
new google.maps.LatLng(29.738692, -95.399331),
new google.maps.LatLng(29.738688, -95.394781),
new google.maps.LatLng(29.737048, -95.394781),
new google.maps.LatLng(29.737048, -95.399331)
];
// Construct the polygon
// Note that we don't specify an array or arrays, but instead just
// a simple array of LatLngs in the paths property
zone1 = new google.maps.Polygon({
paths: triangleCoords,
strokeColor: "#00AEEF",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#00AEEF",
fillOpacity: 0.05,
});
zone1.setMap(map);
zone1._myBounds = new google.maps.LatLngBounds();
for (var i=0; i<triangleCoords.length; i++)
{
zone1._myBounds.extend(triangleCoords[i]);
}
var listener = google.maps.event.addListener(zone1, 'click', function () {
map.fitBounds(zone1._myBounds);
google.maps.event.removeListener(listener);
});
var listener2 = google.maps.event.addListener(zone1, 'dblclick', function() {
if (map.getZoom() > 16) map.setZoom(13);
//map.setZoom(map.getZoom() -1);
//map.setCenter(map.getCenter());
google.maps.event.removeListener(listener2);
google.maps.event.addListener(zone1, 'click', function (){
map.fitBounds(zone1._myBounds);});
});
For my other POLYGON areas, would I also have to change the variable names for them to work?
Also, the return to center doesn't seem to be working properly. If I need to ask that in a separate question I will.
The immediate problem is that you don't do the same thing in the click listener you add on dblclick:
google.maps.event.addListener(zone1, 'click', function (){
map.fitBounds(zone1._myBounds);});
vs the original:
var listener = google.maps.event.addListener(zone1, 'click', function () {
map.fitBounds(zone1._myBounds);
google.maps.event.removeListener(listener);
});

Google maps circle: how to trigger an event when moved and how to obtain the new center

I was able to make a circle object as an overlay on my google map v3. I set its editable property to true. The next thing I wanted to do was get the coordinates of the center if the user moves the circle. For this I would need some kind of method that's triggered in response to the event. I thought I had this all set up in the initialize function as seen below. However, I'm not getting any alert boxes. So I'm assuming this functions in response to the events are not getting triggered.
function initialize() {
cityCenterLatLng = new google.maps.LatLng(cLat, cLong);
options = {
center : cityCenterLatLng,
zoom : 15,
mapTypeId : google.maps.MapTypeId.ROADMAP,
disableDefaultUI : false,
mapTypeControl : true,
streetViewControl : true,
mapTypeControlOptions : {
style : google.maps.MapTypeControlStyle.DEFAULT,
position : google.maps.ControlPosition.TOP_LEFT
}
};
map = new google.maps.Map(document.getElementById("map_canvas"), options);
$("#map_canvas").css("border", "3px solid black");
infoWindow = new google.maps.InfoWindow({});
var c = {
strokeColor: "#ff0000",
strokeOpacity: 0.8,
strokeWeight: 3,
fillColor: "#b0c4de",
fillOpacity: 0.50,
map: map,
center: cityCenterLatLng,
radius: 1000,
editable:true
};
circle = new google.maps.Circle(c);
google.maps.event.addListener(circle, 'distance_changed', function()
{
alert('Circle moved');
//displayInfo(circle);
});
google.maps.event.addListener(circle, 'position_changed', function()
{
alert('distance changed');
//displayInfo(circle);
});
}
function displayInfo(widget)
{
var info = document.getElementById('info');
info.innerHTML = 'Circle Center:' + circle.get('position') + ',Circle distance: ' +
circle.get('distance');
}
Change distance_changed to center_changed for dragged movement, and use radius_changed to detect resizing. Other events are in the docs.
https://developers.google.com/maps/documentation/javascript/reference#Circle
scroll down to 'Events'.
For the new values, inside the listener functions, write alert(circle.getCenter()); or circle.getRadius()

Encapsulate Google Map V.3 event to listen object methods

I want to encapsulate google map polygon(google.maps.Polygon) and map (google.maps.Map) into a javascript object and handle some event for both polygon and map. Here is some code
function Landmark(map, polygon) {
this.map = map;
this.polygon = polygon;
// Add a listener for the click event
google.maps.event.addListener(this.map, 'click', this.addPoint);
google.maps.event.addListener(this.polygon, 'click', this.addPoint);
addPoint = function (event) {
alert("xxx");
}
}
I called the function using :
var myLatLng = new google.maps.LatLng(24.886436490787712, -70.2685546875);
var myOptions = {
zoom: 5,
center: myLatLng,
mapTypeId: google.maps.MapTypeId.TERRAIN
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
polygonInTest = new google.maps.Polygon({
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35
});
polygonInTest.setMap(map);
var landmark = new Landmark(map, polygonInTest);
But when I trigger the event, by clicking the map, I got this error from firebug :
f.e is undefined
[Break On This Error] function de(a,b){var c,d=a.__e3_||{};i...n"+b]=c,c=new ce(a,b,c,3));return c};
Can anyone point me where have I done wrong and give some suggestions? Any comment or help is appreciated.
Thanks in advance.
My best guess is that when you are creating an event listener
google.maps.event.addListener(this.map, 'click', this.addPoint);
your handler is not yet defined (i.e. you define addPoint later), so at the time of addListener() call this.addPoint is undefined. And GMaps messes up later when the time comes for the handler to be called.
At least that's how I realized I had a problem at this point by looking at your code :)

Categories