Google Maps v3 markers not refreshing - javascript

So I have 3 Divs with hidden Lat Lng inputs, and some ajax pagination to change them out. On the initial load, I have a script that turns each one of the three pairs of Lat Lng inputs into a marker and pushes them into an array. All of this works good.
Now, when I update the 3 divs with my script file, and then try to use the provided v3 API method to clear and redraw the markers, I get the same spots on the map. And then, if I tell it to go back to page one results, it does delete the page 1 markers and I get the markers from page 2 on my map.
Here is the javascript:
var map;
var markers = [];
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(37.09024, -96.712891),
zoom: 3
};
map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
setRGBmarkers();
}
function setRGBmarkers() {
markers.push(new google.maps.Marker({
position: new google.maps.LatLng(
Number(document.getElementById("address-0-Lat").value),
Number(document.getElementById("address-0-Lng").value)
),
map: map
}));
//removed other markers for brevity
}
function setAllMap(map) {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(map);
}
}
function clearMarkers() {
setAllMap(null);
}
function deleteMarkers() {
clearMarkers();
markers = [];
}
var getPage = function () {
var $a = $(this);
var options = {
url: $a.attr("href"),
type: "get"
};
$.ajax(options).done(function (data) {
var target = $a.parents("div.pagedList").attr("data-nerd-target");
$(target).replaceWith(data);
});
deleteMarkers();
setRGBmarkers();
alert('done');
return false;
}
$(".body-content").on("click", ".pagedList a", getPage);
So it successfully goes out and gets the results. I'm guessing it somehow is running delete and set before its actually done replacing the markers so its setting the 'unreplaced data' again, hence why going back to page one results finally in page 2's markers showing up? Here's a snippet of what the div looks like if needed:
<div class="panel-body">
Event Description
<input id="address-0-Lat" type="hidden" value="34.0519079">
<input id="address-0-Lng" type="hidden" value="-118.24389300000001">
</div>

Well, Anto is correct, and upon investigating the jQuery documentation for the ajax() function, I see the correct place to put the code would be like so:
var getPage = function () {
var $a = $(this);
var options = {
url: $a.attr("href"),
type: "get"
};
$.ajax(options).done(function (data) {
var target = $a.parents("div.pagedList").attr("data-nerd-target");
$(target).replaceWith(data);
deleteMarkers();
setRGBmarkers();
alert('done');
});
return false;
}
$(".body-content").on("click", ".pagedList a", getPage);
Where the 'done' function is executed once the response comes back. Documenation and examples can be found here: http://api.jquery.com/jquery.ajax/

Related

Refreshing google maps markers and infoBubbles using ajax

I am using asp mvc along with jquery and google maps api to display and update locations on a map.
My aim:
Use markers to point to a number of locations
Provide a small amount of information on those location using info bubbles info bubble repo
OnClick refresh markers and info bubbles
What I've achieved so far:
I am able to load the map, place the pointers and display the info bubbles. After a few hours of struggling I have also managed to refresh the markers when the ajax call is made.
My problem:
After the first update the markers refresh correctly but the info bubbles remain (I cannot work out how to clear them)
New bubbles are displayed along with the new markers BUT these bubbles do not hold any data
After the second update all markers disappear, but all info bubbles remain
Initial load
After call 1 (rent button clicked)
After call 2 (buy button clicked)
somePartialView.cshtml
#Html.HiddenFor(m => m.LatLng, new { #id = "latLng" })
<div id="map" class="google-maps">
<div id="map-canvas"></div>
</div>
Javascript
NB: While testing I am hard coding the lat and lng values in the viewModel so I know each time a call is made only four values will be returned, which Is why I have hard coded four string into the contentString array.
$(document).ready(function () {
var map;
var iterator = 0;
var markers = [];
var markerLatLng = [];
var contentString = [
'<div class="infobox-inner"><img src="assets/img/icon-1.png" alt=""/><span>Sarkkara Villa</span></div>',
'<div class="infobox-inner"><a href="08_Properties_Single.html"><img src="assets/img/icon-2.png" alt=""/><span>Sarkkara Flat</span></div>',
'<div class="infobox-inner"><a href="08_Properties_Single.html"><img src="assets/img/icon-3.png" alt=""/><span>Sarkkara Commercial</span></div>',
'<div class="infobox-inner"><img src="assets/img/icon-4.png" alt=""/><span>Sarkkara Appartment</span></div>'
];
var latlng = $("#latLng").val();
var aryOfLatLng = latlng.split(';');
loadMarkers(aryOfLatLng);
function loadMarkers(ary) {
$.each(ary, function (index, value) {
if (value !== "") {
var values = value.split(',')
var loc = new google.maps.LatLng(Number(values[0]), Number(values[1]));
markerLatLng.push(loc);
}
})
}
function initialize() {
map = new google.maps.Map(document.getElementById('map-canvas'), {
scrollwheel: false,
zoom: 12,
center: new google.maps.LatLng(52.520816, 13.410186) //Berlin
});
setTimeout(function () {
drop();
}, 1000);
}
// animate markers
function drop() {
for (var i = 0; i < markerLatLng.length; i++) {
setTimeout(function () {
addMarker();
}, i * 400);
}
}
function addMarker() {
var marker = new google.maps.Marker({
position: markerLatLng[iterator],
map: map,
icon: 'assets/img/marker.png',
draggable: false
//,animation: google.maps.Animation.DROP
});
markers.push(marker);
var infoBubble = new InfoBubble({
map: map,
content: contentString[iterator],
position: markerLatLng[iterator],
disableAutoPan: true,
hideCloseButton: true,
shadowStyle: 0,
padding: 0,
borderRadius: 3,
borderWidth: 1,
borderColor: '#74d2b2',
backgroundColor: '#ffffff',
backgroundClassName: 'infobox-bg',
minHeight: 35,
maxHeight: 230,
minWidth: 200,
maxWidth: 300,
arrowSize: 5,
arrowPosition: 50,
arrowStyle: 0
});
setTimeout(function () {
infoBubble.open(map, marker);
}, 200);
google.maps.event.addListener(marker, 'click', function () {
if (!infoBubble.isOpen()) {
infoBubble.open(map, marker);
}
else {
infoBubble.close(map, marker);
}
});
iterator++;
}
google.maps.event.addDomListener(window, 'load', initialize);
$("#rent").click(function () {
ajaxRequest("/Map/_IsForSale", false)
})
$("#buy").click(function () {
ajaxRequest("/Map/_IsForSale", true)
})
function ajaxRequest(targetUrl, data) {
$.ajax({
cache: false,
url: targetUrl,
type: "POST",
data: { 'isForSale': data },
success: function (data) {
successCallBack(data);
},
error: function (request, status, error) {
alert(error)
}
});
}
// Removes the markers from the map, but keeps them in the array. It will hide all markers.
function clearMarkers() {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
}
function successCallBack(data) {
clearMarkers();
var latlng = data.substring(data.indexOf("value=") + 7, data.indexOf(";\""));
var ary = latlng.split(';');
$.each(ary, function (index, value) {
if (value !== "") {
var values = value.split(',')
var loc = new google.maps.LatLng(Number(values[0]), Number(values[1]));
markerLatLng.push(loc);
}
})
drop();
}
});
1. After the first update the markers refresh correctly but the info bubbles remain (I cannot work out how to clear them)
Just like how you created a markers array to store your created markers to later clear with your #clearMarkers. I'd do similar for the infoBubbles, e.g. #clearInfoBubbles. Make an infoBubbles array to store info bubbles. According to the source code (see line 968) in the info bubble repo, you can close an info bubble with InfoBubble#close. Call your #clearInfoBubbles where necessary. In your #successCallBack perhaps.
2. New bubbles are displayed along with the new markers BUT these bubbles do not hold any data
You are creating infoBubble here like this
var infoBubble = new InfoBubble({
map: map,
content: contentString[iterator],
...
});
with contentString, which is only hardcoded to be 4 elements long.
By the time #initialize is finished, iterator will be equal to 4. The subsequent call to #addMarker (when the 1st rent button is clicked) will try to create an info bubble with contentString[4], however, that is undefined. iterator is never reset to 0.
3. After the second update all markers disappear, but all info bubbles remain
All info bubbles remain because they're never closed.
I'm not sure what your "buy" request is giving back to you. I'd check to see that the response is returning the data that you're expecting. My guess is that no new markers are getting created at this point.

Making Google maps marker array global breaks marker click event

In this page I use the following script:
function initialize() {
var mapCanvas = document.getElementById('map');
var mapOptions = {center:new google.maps.LatLng(latitudeMid,longitudeMid),zoom:15,mapTypeId:google.maps.MapTypeId.ROADMAP,streetViewControl:false,mapTypeControl:true,scaleControl:true,scaleControlOptions:{position:google.maps.ControlPosition.TOP_RIGHT}};
var map = new google.maps.Map(mapCanvas, mapOptions);
var markers=[]; //<=========================================== inside function initialize()
var i;
var insertion;
var previousMarker;
for (i = 0; i < fotoCount; i++) {
var myLatLng=new google.maps.LatLng(Latituden[i], Longituden[i]);
var marker = new StyledMarker({styleIcon:new StyledIcon(StyledIconTypes.MARKER,{color:'00ff00',text:Letters[i]}),position:myLatLng,map:map});
marker.set('zIndex', -i);
marker.myIndex = i;
markers.push(marker);
google.maps.event.addListener(marker, 'click', function() {
var insertion="";
insertion='<img src=\"http://www.pdavis.nl/Ams/'.concat(Bestanden[this.myIndex],'.jpg\"></img>');
insertion=insertion.concat('<table class=width100><tr><td>Bestand: ',Bestanden[this.myIndex],'</td><td class=pright>Lokatie: ',Latituden[this.myIndex],' °N., ',Longituden[this.myIndex],' °E. (',Letters[this.myIndex],')</td>');
insertion=insertion.concat('<td class=pright>Genomen: ',Datums[this.myIndex],'</td></tr><td colspan=3>Object: ',Objecten[this.myIndex],'</td></table>');
$('#photo').html(insertion);
if(previousMarker!=null){previousMarker.styleIcon.set('color', '00ff00')};
this.styleIcon.set('color', 'ff0000');
thisMarker=this.myIndex;
previousMarker=this;
});
}
google.maps.event.trigger(markers[0], 'click');
}
google.maps.event.addDomListener(window, 'load', initialize);
Clicking on a marker highlights the selected marker (turns red) and shows the relevant photo. The two buttons Vorige and Volgende (Previous and Next, to select previous or next photo) obviously don't work because the array markers[] is local to function initialize():
function Next() {
thisMarker++;
if (thisMarker>=fotoCount) {thisMarker=0};
// following line not working
google.maps.event.trigger(markers[thisMarker], 'click');
}
function Previous() {
thisMarker--;
if (thisMarker==0) {thisMarker=fotoCount-1};
// following line not working
google.maps.event.trigger(markers[thisMarker], 'click');
}
The obvious fix is to move "var markers=[]" outside function initialize() (this page) to make this array global, but now the button highlighting (button "A" red upon start; clicked button goes red) does not work. What am I doing wrong here?
The only weird thing is not that when you pass the index 0 to the maximum the click event explodes because he is sending a negative value, then change that and wonder if it is -1, if true passes the greater index - 1 (Excepcion: Cannot read property '__e3ae_' of undefined)
function Previous() {
thisMarker--;
if (thisMarker==-1) {thisMarker=fotoCount-1};
// following line not working
google.maps.event.trigger(markers[thisMarker], 'click');
}
Fiddle example
sorry for my English

Add a filter to markers that have been queried from a fusion table and then clustered with markerClusterer

I'm getting my markers and then clustering them like this:
var query = "SELECT Latitude, Longitude, Icon, 'Nr.', Info, 'W/D/L' FROM " +
'11jvxEY_amSEUy4IaWZE4652trcb3VLUu_x4XMUeD';
var encodedQuery = encodeURIComponent(query);
// Construct the URL
var url = ['https://www.googleapis.com/fusiontables/v1/query'];
url.push('?sql=' + encodedQuery);
url.push('&key=AIzaSyAT76tcYefMoGlGrAgBhFFF22W8JhQyQBI');
url.push('&callback=?');
//example URL
//https://www.googleapis.com/fusiontables/v1/query?sql=SELECT longitude_latitude FROM 1WukvEi1lbr-5Eo0Xn-Vqi5OKS7jhvt1aPmDdOD8I LIMIT 5&key=AIzaSyAT76tcYefMoGlGrAgBhFFF22W8JhQyQBI
// Send the JSONP request using jQuery
$.ajax({
url: url.join(''),
dataType: 'jsonp',
success: function (data) {
var rows = data['rows'];
var markers = [];
for (var i in rows) {
//insert info window code
var infoWindow = new google.maps.InfoWindow();
var lat = rows[i][0]
var lng = rows[i][2]
var image = rows[i][3]
var title = rows[i][3]
var content = rows[i][4]
var result = rows[i][5]
var coordinate = new google.maps.LatLng(lat,lng);
var marker = new google.maps.Marker({'position': coordinate,
'icon': image,
'title': 'Länderspiel #'+title,
'result': result
});
google.maps.event.addListener(marker, 'mouseover', (function(marker, content) {
return function(){
infoWindow.setContent(content);
infoWindow.open(map, marker);
}
})(marker, content));
google.maps.event.addListener(marker, 'mouseout', function() {
infoWindow.close();
});
markers.push(marker);
}
// function filter() {
// var where = generateWhere();
//
// if (where) {
// if (!marker.getMap()) {
// marker.setMap;
// }
// marker.setOptions
var markerCluster = new MarkerClusterer(map, markers);
}
});
I've begun to add a filter (commented out), trying to copy this method, but I'm not sure if that will work. I found another example, that seems to be doing exactly what I want, here, but I can't see, where they get the marker-properties they use to filter them from... I'd like to create a variable from the same query that assigns the markers different icons, getting info from the 'W/D/L' column (already included in the code), and then filter the markers by whether that information returns 'W', 'D', or 'L' (win, draw, or loss). I'm a noob, so can someone walk me through it?
The conditions you may retrieve in any desired way, when the user should be able to define the conditions a checkbox should be appropriate, so create checkboxes with the desired values W,D and L.
Observe the click-event of the checkboxes and create the where-clause based on the values of the checked boxes. With jQuery it may look like this:
var where=[];
//ancestor is the common ancestor of all the checkboxes
$('input:checked',ancestor).each(function(){where.push(this.value)});
the result so far will be an array containing the values of the checked checkboxes, e.g. ['W','L'] .
This array now may be used to create the where-clause. The where-clause for the example-array should be :
where 'W/D/L' IN('W','L')
it may be created via:
" where 'W/D/L' IN('"+where.join("','")+"')"
append this where-clause to query and the results will be filtered.
Demo: http://jsfiddle.net/doktormolle/xd8Qp/
This is an addition to the answer provided by #DrMolle.
I tried to copy #DrMolle's demo, but the map initially did not render the markers as well.
It worked after including the necessary script sources which were missing:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>

google maps api v3 multiple markers infowindow onclick works but not when called outside

I have a weird problem and maybe I am just not seeing it clearly. It definitely always helps to have others look at my code. Anyways, I have a drop down menu with options in it, needless to say, onchange it calls a function to open an infowindow. The listener for the click works perfectly fine when displaying the info window, but the handleSelected() function does not display anything.:
<select size='37' id='dpMenu' onchange='handleSelected(this)'>
Now I have an array for my markers outside of my function that creates the markers.
var gmarkers = [];
var oldInfoWin;
var map;
function createEpiMarker(map,point,epi_icon,html,name,detail,iqrid) {
var epimarker = new google.maps.Marker({
position: point,
map: map,
icon: epi_icon
});
epimarker.infowindow = new google.maps.InfoWindow({content: html });
google.maps.event.addListener(epimarker, "click", function() {
epimarker.infowindow.open(map, epimarker);
oldInfoWin = epimarker.infowindow;
infoWindowOpen = true;
});
gmarkers.push(epimarker);
}
This code here handles the dropdown menu selection:
function handleSelected(opt){
var i = opt[opt.selectedIndex].index - 1;
if(i != -1){
gmarkers[i].infowindow.open(map, gmarkers[i]);
oldInfoWin = gmarkers[i].infowindow;
infoWindowOpen = true;
}
}

LeafletJS popups positions and markers add and remove issue

I am implementing displaying locations on openstreetmaps using leafletjs API. Here is the scenario, When the page loads a JS function is being triggered which will query DB to get current locations of all the devices and show them as markers on map. I am facing two major issues in it:
--> I am trying to bind popups with each marker so that it could be descriptive. In other words user should gain idea that of what device this marker for. The problem is that popups is being showed over the marker making marker non-visible. Here is the screenshot:
Marker is shown below(after closing one popup):
--> On this page, I am displaying devices names in a table. The first column of this table is checkbox. When user check a device its marker appears on the map as expected(working fine). After that if user unchecks that device then its marker disappears. But when user re-selects that device again then its marker doesn't appear.
Here is my code:
function OnPageLoad() {
var IDs = GetAllSelectedDeviceIDs();
LoadOpenStreetMap(IDs);
}
var map;
var markers = new Array();
function LoadOpenStreetMap(deviceIDs) {
for (var i = 0; i < deviceIDs.length; i++) {
$.ajax({
url: "../Database/getcurrentlocation.php",
cache: false,
type: "post",
data: "deviceId=" + deviceIDs[i] + "&r=" + Math.random(),
dataType: "html",
async: false,
success: function (data) {
if (data != null) {
var dataArray = data.split(/~/);
SetOpenStreetMap(dataArray[0], dataArray[1], deviceIDs[i], i, flags[i]);
}
}
});
}
deviceIDs = GetAllSelectedDeviceIDs();
setTimeout(function () { LoadOpenStreetMap(deviceIDs); }, 500);
}
function SetOpenStreetMap(lati, longi, deviceID, markerIndex, markerFlag) {
if (!map) {
map = L.map('map').setView([lati, longi], 12);
L.tileLayer('http://{s}.tile.cloudmade.com/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/997/256/{z}/{x}/{y}.png', {
attribution: '',
maxZoom: 18
}).addTo(map);
}
if (markerFlag == 1) {
//need to add marker
if (!markers[markerIndex]) {
var popupLocation1 = new L.LatLng(lati, longi);
var popupContent1 = 'This is a nice popup.';
popup1 = new L.Popup();
popup1.setLatLng(popupLocation1);
popup1.setContent(popupContent1);
markers[markerIndex] = L.marker([lati, longi]).addTo(map);
markers[markerIndex].bindPopup(popupContent1);
map.addLayer(popup1);
}
else
markers[markerIndex].setLatLng([lati, longi]).update();
}
else {
//need to remove marker
if (markers[markerIndex]) {
map.removeLayer(markers[markerIndex]);
}
}
}
Any help would be appreciated.
Thanks.
To put the popup over the marker with some offset there exists an offset property:
if (markerFlag == 1) { //need to add marker
if (!markers[markerIndex]) {
var popupLocation1 = new L.LatLng(lati, longi);
var popupContent1 = 'This is a nice popup.';
popup1 = new L.Popup();
popup1.setLatLng(popupLocation1);
popup1.setContent(popupContent1);
popup1.offset = new L.Point(0, -20);
markers[markerIndex] = L.marker([lati, longi]).addTo(map);
/* markers[markerIndex].bindPopup(popupContent1); */
map.addLayer(popup1);
} else
markers[markerIndex].setLatLng([lati, longi]).update();
}
Set the offset inside the options object when creating the popup.
var options = {
offset: new L.Point(1, -20)
};
var popup = L.popup(options)
.setLatLng([ lat, lng ])
.setContent('Your popup content goes here!')
.openOn(map)
;
The "options" object is the first object that is passed to the L.popup()
To show a popup over a marker, only call the bindPopup method on the marker.
This is shown in the QuickStart.
You do not need to instantiate a popup, yourself.

Categories

Resources