I am developing a web application that contains some information about place. That place may have more than one agenda. Can I show more information in one marker, such as stack balloon?
This is my maps
http://petamajelis.org/maps/index.php
This is my data
http://petamajelis.org/maps/ajax2.php
there are some places that have more than one agenda, and I want to show all of that agendas in one marker if the latitude and longitude are same.
this is my code to show marker depend on database, I put it in index.php
function load() {
var map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(-6.270293,106.830995),
zoom: 13,
mapTypeId: 'roadmap'
});
var infoWindow = new google.maps.InfoWindow;
// Change this depending on the name of your PHP file
downloadUrl("ajax2.php", function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var name = markers[i].getAttribute("name");
var address = markers[i].getAttribute("address");
var type = markers[i].getAttribute("type");
var materi = markers[i].getAttribute("materi");
var pemateri = markers[i].getAttribute("pemateri");
var tanggal = markers[i].getAttribute("tanggal");
var hari= markers[i].getAttribute("hari");
var jam= markers[i].getAttribute("jam");
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("lat")),
parseFloat(markers[i].getAttribute("lng")));
var html = "<b>" + name + "</b> <br/>" + address + "<br/>" +materi+ " : "+pemateri+ "<br/>"+ hari +" "+tanggal+ " Jam : "+jam;
var icon = customIcons[type] || {};
var marker = new google.maps.Marker({
map: map,
position: point,
icon: icon.icon,
shadow: icon.shadow
});
bindInfoWindow(marker, map, infoWindow, html);
}
});
}
function bindInfoWindow(marker, map, infoWindow, html) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
could i modify that code to show some information if latitude/longitude are same and show it in a balloon above marker?
thanks before
Possible way to achieve it(there may be many ways):
create some object at the begin of the callback of downloadUrl()
var markerContents={};
inside the loop where you create the markers populate this object with properties. As name for the properties assign the string-representation of the point(will be returned by LatLng.toString()). Create a variable of this string:
var markerId = point.toString();
First you have to check now if this property already exists, when not create it and set the value to an empty array:
if(!markerContents[markerId]){
markerContents[markerId] = [];
}
Then, after the line where create the html, push the html into the array:
markerContents[markerId].push(html);
to avoid the creation of multiple markers at the same position, leave the current iteration before you create the marker, when there are more than 1 item inside the array:
if(markerContents[markerId].length>1){return;}
modify the call of bindInfoWindow(); , pass the array as argument instead of html
bindInfoWindow(marker, map, infoWindow, markerContents[markerId]);
Modify the click-listener of the Marker so that he may use the content of the array as InfoWindowContent
function bindInfoWindow(marker, map, infoWindow, html) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html.join('<hr/>'));
infoWindow.open(map, marker);
});
}
There will no longer be multiple markers at the same position, instead there will be 1 marker with the content set to the html of all markers with this position, delimited by a horizontal rule.
Related
I'm trying to make an array of markers and have each marker open an info window with related info onclick but I either get a cannot read 'apply' property of undefined or it opens on the wrong marker; My 2 attempts were:
Cannot read apply:
var infowindow = new google.maps.Infowindow();
for (var i=0;i<popular.length;i++){
var mkrLatLng = new google.maps.LatLng(popular[i][1], popular[i][2]);
var marker = new google.maps.Marker({
map: map,
title: popular[i][0],
position: mkrLatLng
});
markers.push(marker);
}
for (var i=0;i<markers.length;i++){
markers[i].addListener('click', (function(){
console.log('click');
cont = "<div> " + markers[i].title + " </div>";
infowindow.setContent(cont);
infowindow.open(map, marker);
})(markers));
}
Opens on wrong marker (Anonymous function is wrapped in another function since it got rid of the undefined error, I don't understand why):
var infowindow = new google.maps.Infowindow();
for (var i=0;i<popular.length;i++){
var mkrLatLng = new google.maps.LatLng(popular[i][1], popular[i][2]);
var marker = new google.maps.Marker({
map: map,
title: popular[i][0],
position: mkrLatLng
});
marker.addListener('click', function(){(function(){
console.log('click');
cont = "<div> " + marker.title + " </div>";
infowindow.setContent(cont);
infowindow.open(map, marker);
})(marker)});
markers.push(marker);
}
Your structure is wrong
this is example enter link description here
//wrong
for(var i=0;i<3;i++){
var count=i
$('<p>wrong</p>').on('click',function(){
alert(count)
}).appendTo('body')
}
//what you want
for(var i=0;i<3;i++){
createEl(i)
}
function createEl(i){
$('<p>correct</p>').on('click',function(){
alert(i)
}).appendTo('body')
}
Hope this will help you understand why you're wrong
So you need to change your code to this
for(){
createMarker(parameter)
}
function createMarker(parameter){
var marker=...,
infowindow=....
marker.addlistener(...)
.......
}
Try your second code, make var infowindow global, maybe it'll work, I'm not sure.
Or else you can new every infowindow in forloop, and push into array, just like you handle markers.
var mark = new google.maps.Marker({
map: map,
position: place.geometry.location,
optimized: false,
icon: 'red-dot.png'
}),
infowindow = new google.maps.InfoWindow()
infowindow.setContent(place.name)
infowindows.push(infowindow)
//then addlistener to marker
//markers.push(marker)
To open just one infowindow, use infowindow.close() to close all infowindows,
then call infowindow.open(map,marker)
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'm using the following code to generate marker pins. It loads perfectly, but to the left of this map I have filters. How do I reload the markers without reloading the map? This has been causing some frustration so any help would be appreciated.
Many thanks,
//Google map results
var contentStrings = [];
var infowindow = new google.maps.InfoWindow();
var mapinited = false;
var map;
var myOptions = {
zoom: 11,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var currentinfobox;
var myLatlng;
var markersArray=[];
var LatLngList = [];
$().ready(function() {
//reinit search
if (window.location.hash) {
submitForm(window.location.hash.replace('#',''));
}
else if (readCookie('sf')) {
//submitForm(readCookie('sf'));
}
//init map
$('#map_view').click(function() {
if (mapinited) {
return;
} else {
mapinited = true;
initMap();
}
function initMap() {
locate(["Ireland"],function(result) {
map = new google.maps.Map(document.getElementById("search_map"), myOptions);
myLatlng = new google.maps.LatLng(result.lat(),result.lng());
var key =0;
$.each(map_results, function(key, value){
LatLngList[key] = new google.maps.LatLng(value.lat,value.long)
contentStrings[key] =
'<div id="ginfo_content" class="map-pop-up">'+
'<span class="content-top"> </span>'+
'<div class="content-middle">'+
'<div class="map-filler">'+
'<a class="map-close" href="javascript:;" onclick="infowindow.close();" title="Close">x</a>'+
'<br class="clearfix">'+
'<div class="map-pop-up-left">'+
'<div class="thumbnail"><img src="'+ value.image +'" width="64" height="64"></div>'+
'Contact'+
'</div>'+
'<div class="map-pop-up-right">'+
'<h2>'+ value.firstname +' '+value.lastname+', '+ value.address +'</h2>'+
'<p>'+ stripslashes(value.about) +'</p>'+
'</div>'+
'<br class="clearfix">'+
'<div class="map-pop-up-footer">View Profile<span class="telephone">Telephone: '+ value.phone +'</span></div>'+
'</div>'+
'</div>'+
'<span class="content-bottom"> </span>'+
'</div>';
key++;
});//end each
map_results="";
google.maps.event.addListener(infowindow, 'domready', function() {
var infocontent = $('#ginfo_content').clone();
var l = $('#ginfo_content').parent().parent().parent().addClass('original_popup').html('');
$('.original_popup').append(infocontent).show();
$('.original_popup').css('width','360px').css('height','230px').css('left','+=27px').css('top','+=65px');
});
var zoomChangeBoundsListener = google.maps.event.addListener(map, 'zoom_changed', function() {
if (this.getZoom() > 14) // Change max/min zoom here
this.setZoom(14);
google.maps.event.removeListener(zoomChangeBoundsListener);
});
var infoboxlistener = google.maps.event.addListener(map, 'zoom_changed', `enter code here`function() {
infowindow.close();
});
loadMapInit(LatLngList,contentStrings);
});
}
});
});
Hopefully this is answering what you're asking:
When you create a marker, you can use the 'map' parameter to set its map and have it show up. Or, if you want to tie it to a filter, you can ignore the map paramter and use marker.setMap(map) later.
// To add the marker to the map, use the 'map' property
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title:"Hello World!"
});
If you want to 'remove' and 'add' markers with events, you can use marker.setMap(null) to remove the marker and marker.setMap(map) to re-add it.
var marker = new google.maps.Marker({
position: myLatlng,
title:"Hello World!"
});
// To add the marker to the map, call setMap();
marker.setMap(map);
// To remove the marker from the map
marker.setMap(null);
https://developers.google.com/maps/documentation/javascript/markers
Update:
So if you wanted to 'reload' the markers, you could traverse through and array of currently active markers, set their maps to null, and then reset them on the map.
My page loads maps in two scenarios 1) first load 2) ongoing refreshing of a google map through ajax calls.
The following worked for me
<input type="hidden" id="lonDeg"><!--route lat to here via ajax call-->
<input type="hidden" id="latDeg"><!--route lon to here via ajax call-->
<script>
var map;
function initMap() {
// these two lines are the only variation from the native google
// API code. They allow for dynamic updates of the lon/lat (below)
var lonDeg = parseFloat($("#lonDeg").val());
var latDeg = parseFloat($("#latDeg").val());
var midp = {lat:latDeg, lng:lonDeg };
map = new google.maps.Map(document.getElementById('map'), {
scaleControl: true,
center: midp,
zoom: 10
});
var marker = new google.maps.Marker({map: map, position: midp});
marker.addListener('click', function() {
infowindow.open(map, marker);
});
}
</script>
The event trigger in my case a button
<button id="getNextMap">Go to Next Map</button>
Then finally the javascript that makes it all happen
var qstring = 'myArgsToPass';
var csv = new Array();
$.ajax({
url: 'mapProfileGrabber.php',
type: 'POST',
data: {q:qstring},
success: function(data) {
csv = data.split(",");
$("#lonDeg").val(csv[0]);
$("#latDeg").val(csv[1]);
initMap();
}
In my case, I'm using SVG icons, and I'm changing the strokeColor in code, after the marker (and its icon) are on the map.
To have the map display the new color, I simply call setMap again:
marker.setMap(map);
I find no need to remove it first with marker.setMap(null);
I have a hunch this will work with other changes to the marker, like its icon's URL, etc.
Here's what I'm trying to accomplish:
When you click on the marker, the info that would normally show up in the bubble, is instead displayed in a DIV outside the map, in a section to the right, with it's own formatting.
I'm not really sure what to do. I tried the suggestions here, but that was from 2007, and I think the GDownload() function is now deprecated. Or at least, I couldn't find any reference of it in the documentation and API lists on the Google Developer site.
All I know is that I need to convert the following into a DIV, somehow.
downloadUrl("genxml.php", function(data) {
var xml = data.responseXML;
var locations = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < locations.length; i++) {
var name = locations[i].getAttribute("name");
var address = locations[i].getAttribute("address");
var type = locations[i].getAttribute("type");
var point = new google.maps.LatLng(
parseFloat(locations[i].getAttribute("lat")),
parseFloat(locations[i].getAttribute("lng")));
var html = "<div id=loc> <div class=loc-name>" + name + "</div> <br/>" + address + "<br/>" + "<div class=loc-type>" + type + "</div></div>";
var icon = customIcons[type] || {};
var marker = new google.maps.Marker({
map: map,
position: point,
icon: icon.icon,
shadow: icon.shadow
});
bindInfoWindow(marker, map, infoWindow, html);
}
});
}
document.getElementById("loc-info").innerHTML = html;
function bindInfoWindow(marker, map, infoWindow, html) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
}
Can anyone point me in the right direction?
Just change the code that creates the infowindow to set the content of your div :
function bindInfoWindow(marker, map, infoWindow, html) {
google.maps.event.addListener(marker, 'click', function() {
document.getElementById('loc-info').innerHTML = html;
});
}
EDIT : You also want to remove that line (the one before your function bindInfoWindow), which does nothing, since html doesn't exist at this point :
document.getElementById("loc-info").innerHTML = html;
I have finally managed to add multiple markers with custom icons to my Googlemap.
The next step would be to add an individual Infowindow for each marker.
Unfortunatelly i cant figure out how.
Here is my script so far:
<script type="text/javascript">
var offender_locations = [
["10010", "http://localhost/safenation/img/map_offender_icon.png"],
["10001", "http://localhost/safenation/img/map_visitor_icon.png"]
];
var myOptions = {zoom: 10,center: latlng,mapTypeId: google.maps.MapTypeId.ROADMAP};
var map = new google.maps.Map(document.getElementById("elementid"), myOptions);
var latlng = new google.maps.LatLng(0, 0);
var marker;
var i;
for (i = 0; i < offender_locations.length; i++) {
var infowindow = new google.maps.InfoWindow();
var geocoder_map = new google.maps.Geocoder();
var address = offender_locations[i][0];
var icon = offender_locations[i][1];
geocoder_map.geocode({'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: map.getCenter(),
icon: icon
});
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
infowindow.setContent(offender_locations[i][1]);
infowindow.open(map, marker);
}
})(marker, i));
} else {alert("The requested offender is not mappable !")};});
}
</script>
I think there now is a problem with the loop. When i try:
var icon = offender_locations[1][1];
all icons are "map_offender_icon.png"
When I use :
var icon = offender_locations[i][1];
nothing changes and all icons are still "map_offender_icon.png"
It seems the var offender_locations[i][1]; is not changing accordingly. The var offender_locations[i][0]; changes accordingly.
Your marker variable is local to your for loop which is not visible outside the loop so the statement
var infowindow = new google.maps.InfoWindow();
google.maps.event.addListener(marker, 'click', (function(marker, i)
is not able to set the listener for your marker.
Best way is include your Info window initialization inside your loop to set listeners to your entire markers.
Hope this helps.
The problem has been solved!
Working script:
Javascript Loop - 2nd variable Not Displaying
(Extracted from edit to the original question)