I'm having an issue drawing a dynamic polygon using ngmap. Basically I have a map with an on-click event as follows
<map center="<% latitude %>, <% longitude %>" zoom="2" on-click="placeMarker()">
and the "placeMarker" method is inside my controller. Now, the following code will correctly place markers on the map and turn them into a polygon the moment you place the 4th marker...
$scope.placeMarker = function(e)
{
var marker = new google.maps.Marker({position: e.latLng, map: $scope.map});
$scope.coordinates.push( [Number(e.latLng.J),Number(e.latLng.M)] );
if( $scope.coordinates.length == 4 )
{
$scope.createPolygon();
}
}
$scope.createPolygon = function()
{
$scope.GoogleMap.polygons.push( $scope.coordinates );
$scope.coordinates = [];
}
... but when I try to refactor the code to build the polygon when the user clicks back onto the first marker they placed nothing happens. The event listener fires, the logic appears OK but the polygon never appears
$scope.placeMarker = function(e)
{
var marker = new google.maps.Marker({position: e.latLng, map: $scope.map});
$scope.coordinates.push( [Number(e.latLng.J),Number(e.latLng.M)] );
if( $scope.coordinates.length == 1 )
{
google.maps.event.addListener(marker, 'click', function () {
$scope.createPolygon();
});
}
}
$scope.createPolygon = function()
{
$scope.GoogleMap.polygons.push( $scope.coordinates );
$scope.coordinates = [];
}
I'm sure this is probably a limitation in my generic JS knowledge. It has me stumped. Can anybody please advise?
Related
I have a script that:
pulls results from a database in the form of an XML file
parses those results
creates a marker for each result and places it on a map (a single map for all markers)
at the same times, builds a clickable HTML list (sidebar) containing all those results.
When the user clicks on a place name in the sidebar, the info window from the corresponding marker on the map is automatically displayed. Of course the user can also click directly on a marker on the map, and the same info window is also displayed.
This code has been working fine for several years, but last week I noticed that its behavior was now bugged. When viewing some given results, the first click (either on the map or in the sidebar) works fine (the info window opens and displays the correct information), but the following clicks all show the same information from the first click, all in their respective info window. (To be clear: the information shown is the one from the very first click, not from the previous click.)
I've been trying to debug that for hours but I don't understand why it doesn't work anymore. As you can see in my code below, I tried adding a console.log in the google.maps.event.addListener function, to see what data is being worked with when the marker is clicked, but even there, I don't see anything wrong.
Here is my code (simplified to be more readable):
var side_bar_html = '\n';
var gmarkers = []; // array for created markers
var infoWindow;
var center_lat = <?php echo $position_lat; ?>;
var center_lng = <?php echo $position_lng; ?>;
function createMarker(point, name, html, place_id, map) {
var marker, markerOptions;
markerOptions = {
map: map,
position: point,
dataId: place_id,
icon : 'theme/marker.png',
shadow: 'theme/marker_shadow.png'
};
marker = new google.maps.Marker(markerOptions);
infoWindow = new google.maps.InfoWindow({content: html});
google.maps.event.addListener(marker, 'click', function() {
console.log(this, marker, html);
infoWindow.content = html;
infoWindow.open(map, this);
});
gmarkers.push(marker);
side_bar_html += '\n<li>' + name + '</li>';
return marker;
}
function showPlace(i) {
google.maps.event.trigger(gmarkers[i], 'click');
}
function loadEarth(opt, zoom) {
var map, point, mapCenter, mapOptions;
if (zoom === null) {zoom = 7;}
mapCenter = new google.maps.LatLng(center_lat, center_lng);
mapOptions = {
zoom: zoom,
center: mapCenter,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
point = new google.maps.LatLng(parseFloat(center_lat), parseFloat(center_lng));
if (opt != 0) {
map.setMap(new google.maps.Marker(point));
}
}
// receiving results via XML
function go() {
var map, bounds;
var mapOptions = {
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
bounds = new google.maps.LatLngBounds();
$.ajax({
url : 'url/to/data.xml',
type : 'GET',
dataType : 'xml',
success : function(xml) {
var markers, lat, lng, place_id, point, label, html, marker;
markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
// extract data for each marker
lat = parseFloat(markers[i].getAttribute("lat"));
lng = parseFloat(markers[i].getAttribute("lng"));
place_id = parseFloat(markers[i].getAttribute("place_id"));
point = new google.maps.LatLng(lat,lng);
label = $(markers[i]).find('label').eq(0).text();
html = $(markers[i]).find('infowindow').eq(0).text();
// marker creation
marker = createMarker(point, label, html, place_id, map);
// extend visible zone to newly added marker
bounds.extend(point);
}
map.setCenter(new google.maps.LatLng(center_lat, center_lng), 7);
bounds.extend(point);
if (markers.length>0) {
document.getElementById("side_results").innerHTML = side_bar_html;
map.fitBounds(bounds);
map.setCenter(bounds.getCenter());
} else {
loadEarth();
}
} // end AJAX success
}); // end AJAX
} // end go()
if ($('#places_page').is('.empty')) {
loadEarth(0,8);
} else go();
Any help would be greatly appreciated.
Edit:
As requested, here's a sample of the XML received. In this case, the PHP variables at the start of the script would receive the following values:
$position_lat: 46.9479222
$position_lng: 7.4446085
<?xml version="1.0" encoding="UTF-8"?><markers>
<marker place_id="955" lat="46.950218" lng="7.442429">
<label><![CDATA[<em>Place 955</em><strong>3011 Bern</strong>]]></label>
<infowindow>
<![CDATA[<p><em>Place 955</em><br />Speichergasse 35<br />3011 <ins>Bern</ins></p>]]>
</infowindow>
</marker>
<marker place_id="985" lat="46.942032" lng="7.389993">
<label><![CDATA[<em>Place 985</em><strong>3018 Bern</strong>]]></label>
<infowindow>
<![CDATA[<p><em>Place 985</em><br />BrĂ¼nnenstrasse 106A<br />3018 <ins>Bern</ins></p>]]>
</infowindow>
</marker>
</markers>
The Google Maps API is included via this line:
<script src="http://maps.google.com/maps/api/js?v=3&sensor=true&language=fr&key=..."></script>
Edit 2:
Changing the API call to force it to use version 3.18 does fix the problem:
<script src="http://maps.google.com/maps/api/js?v=3.18&sensor=true&language=fr&key=..."></script>
Obviously this is a temporary fix, since v. 3.18 won't always be available. Now I need to understand what change in the 3.19 version made this bug appear. Any suggestion is still appreciated. :)
This undocumented usage:
infoWindow.content = html;
May be the issue. Should be:
infoWindow.setContent(html);
The .content property went away or is no longer supported issue
I want to get the element let say marker when it is clicked. Mouse click event not send any object of sender.
I know this can be achieved via :
var locMarker = new google.maps.Marker({
map : map,
icon : icon,
position : point
});
locMarker.id = (i + 1);
locMarker.clubID = clubid;
locMarker.clubName = clubname;
google.maps.event.addListener(locMarker, 'click', function(evt) {
console.log(evt);
console.log(locMarker);
});
But this way I can only get evt, not the whole marker object, here i can access marker object, but if i declare click event function somewhere else like this :
google.maps.event.addListener(locMarker, 'click', this.locationMarkerOnClick);
then i only get evt, not markerObject. Is there any solution?
Use the keyword this:
(function() {
var locMarker = new google.maps.Marker({
map: map,
icon: icon,
position: point
});
locMarker.id = (i + 1);
locMarker.clubID = clubid;
locMarker.clubName = clubname;
google.maps.event.addListener(locMarker, 'click', this.locationMarkerOnClick);
})();
function locationMarkerOnClick(evt) {
console.log(this); // get (show in console) the marker itself
console.log(evt); // show the evt as expected
}
So I'm trying to figure out a way to change the HTML of Google Maps V3 markers after they have been pulled from the database but before they are pushed up to the array.
When getFishing() is called, I'd like to run convertRate(rate) so that if the rate variable is equal to two or more, it shows a picture which is within the HTML of the Markers themselves. I've tried putting it in the bindInfoWindow4() and I've tried several places within the getFishing() function with no success. Has anyone done this before? Is it possible after the markers have been pushed up to the fishArray?
function getFishing() {
fishingUrl("XML_Fishing.php", function (data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var id = markers[i].getAttribute("id");
var title = markers[i].getAttribute("title");
var rate = markers[i].getAttribute("rate");
var Fishhtml = "<img id='1star' src='images/1star.png' style='visibility:hidden'>";
var icon = FishingIcon;
var Fishmark = new google.maps.Marker({
map: map,
position: point,
icon: icon.icon
});
fishArray.push(Fishmark);
bindInfoWindow4(Fishmark, map, Fishinfo, Fishhtml);
}
});
}
function convertRate(rate) {
if (rate >= 2) {
document.getElementById("1star").style.visibility = 'visible';
}
}
function bindInfoWindow4(marker, map, infoWindow, html) {
google.maps.event.addListener(marker, 'click', function () {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
}
If you change your click listener to display the HTML saved in a member variable of the marker, you can change it at any time. If the InfoWindow is open, you may want to close it and reopen it (or update its content in place, but that gets more complicated).
Something like:
function bindInfoWindow4(marker, map, infoWindow, html) {
marker.myHtmlContent = html;
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(marker.myHtmlContent);
infoWindow.open(map, marker);
});
}
Then update the content by changing the value in marker.myHtmlContent. To make it visible, somthing like this:
marker.myHtmlContent = "<img id='1star' src='images/1star.png' style='visibility:visible'>";
We have a dynamic json feed that is parsed into markers on our google map.
the parsing function looks something like this:
function parse_json(json) {
// alert('start parse: '+json.length);
if (json.length > 0) {
var markers = [];
for (i=0; i<json.length; i++) {
var report = json[i];
//alert(report.longitude +','+report.latitude);
// addLocation(report);
markers[i] = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(report.latitude, report.longitude),
pop_title: report.area1.name,
pop_body: '<b>'+ report.spot.name +'</b>'+
'<br>'+ report.report_description,
draggable: false,
title: 'title',
zIndex: i,
icon: '/images/map_icon.png'
});
markers[i].metadata = {type: "point", id: report.id};
google.maps.event.addListener(markers[i], 'click', onMarkerClick);
}
};
i have added metadata info to the markers created so their id is the report.id - but i want to use the google.maps.event.trigger(SOMETHING_HERE, 'click'); construct to trigger a click event on a given marker when a button outside of the map is pressed. how do i get the object name, or is there a way to do this using the object's id?
thanks!
If you declare your markers array at a higher scope than your parse_json function, then you will be able to refer to it later, something like this:
var markers = new Array();
function parse_json(json) {
//code removed for brevity
}
Then later, when you need to find the marker you want to fire a click event against, you could use the id like this:
for ( var i = 0; i < markers.length; i++ ) {
var mkr = markers[i];
if ( mkr.metadata.id === idYouAreSearchingFor ) {
//do whatever is needed here and fire your event
}
}
In the code available here :
https://gist.github.com/1338861
if I would include the code of the function function attachEvent(marker){...}
into the body of the function
function addResults(json) {...}
like this :
function addResults(json) {
if (json.results && json.results.length) {
for (var i = 0, placemark; placemark = json.results[i]; i++) {
var pos = new google.maps.LatLng(parseFloat(placemark.point.latitude, 10),
parseFloat(placemark.point.longitude, 10));
var marker = new google.maps.Marker({
map: map,
title : placemark.name,
position: pos
});
google.maps.event.addListener(marker, 'click', function(){
var text = marker.getTitle();
showInContentWindow(text);
profileMarkers.push(marker);
}
}
}
the result would be that when clicking on any marker from the map, it would be shown in the content window only the information characteristic to the last marker added to profileMarkers array (instead of the information of the marker clicked).
My question is why does the onclick listener for the marker need to be attached in a different function (attachEvent in this context) ?
Because you keep changing marker to the last one by continuing the loop. Try this:
(function(mkr) {
google.maps.event.addListener(marker, 'click', function(){
var text = mkr.getTitle();
showInContentWindow(text);
profileMarkers.push(mkr);
}
})(marker);
In the place of the current google.maps.event.addListener code. This will create a closure and effectively "fix" the value of the variable.