I\'m using Google Maps V3 to display some pins. I want to be able to refresh markers without affecting where you\'re at on the map or the zoom level. I want the markers to b
OK, I've got something working - largely a heavy refactoring of your original code - you will recognize various chunks.
$(function() {
var locations = {};//A repository for markers (and the data from which they were constructed).
//initial dataset for markers
var locs = {
1: { info:'11111. Some random info here', lat:-37.8139, lng:144.9634 },
2: { info:'22222. Some random info here', lat:46.0553, lng:14.5144 },
3: { info:'33333. Some random info here', lat:-33.7333, lng:151.0833 },
4: { info:'44444. Some random info here', lat:27.9798, lng:-81.731 }
};
var map = new google.maps.Map(document.getElementById('map_2385853'), {
zoom: 1,
maxZoom: 8,
minZoom: 1,
streetViewControl: false,
center: new google.maps.LatLng(40, 0),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var infowindow = new google.maps.InfoWindow();
var auto_remove = true;//When true, markers for all unreported locs will be removed.
function setMarkers(locObj) {
if(auto_remove) {
//Remove markers for all unreported locs, and the corrsponding locations entry.
$.each(locations, function(key) {
if(!locObj[key]) {
if(locations[key].marker) {
locations[key].marker.setMap(null);
}
delete locations[key];
}
});
}
$.each(locObj, function(key, loc) {
if(!locations[key] && loc.lat!==undefined && loc.lng!==undefined) {
//Marker has not yet been made (and there's enough data to create one).
//Create marker
loc.marker = new google.maps.Marker({
position: new google.maps.LatLng(loc.lat, loc.lng),
map: map
});
//Attach click listener to marker
google.maps.event.addListener(loc.marker, 'click', (function(key) {
return function() {
infowindow.setContent(locations[key].info);
infowindow.open(map, locations[key].marker);
}
})(key));
//Remember loc in the `locations` so its info can be displayed and so its marker can be deleted.
locations[key] = loc;
}
else if(locations[key] && loc.remove) {
//Remove marker from map
if(locations[key].marker) {
locations[key].marker.setMap(null);
}
//Remove element from `locations`
delete locations[key];
}
else if(locations[key]) {
//Update the previous data object with the latest data.
$.extend(locations[key], loc);
if(loc.lat!==undefined && loc.lng!==undefined) {
//Update marker position (maybe not necessary but doesn't hurt).
locations[key].marker.setPosition(
new google.maps.LatLng(loc.lat, loc.lng)
);
}
//locations[key].info looks after itself.
}
});
}
var ajaxObj = {//Object to save cluttering the namespace.
options: {
url: "........",//The resource that delivers loc data.
dataType: "json"//The type of data tp be returned by the server.
},
delay: 10000,//(milliseconds) the interval between successive gets.
errorCount: 0,//running total of ajax errors.
errorThreshold: 5,//the number of ajax errors beyond which the get cycle should cease.
ticker: null,//setTimeout reference - allows the get cycle to be cancelled with clearTimeout(ajaxObj.ticker);
get: function() { //a function which initiates
if(ajaxObj.errorCount < ajaxObj.errorThreshold) {
ajaxObj.ticker = setTimeout(getMarkerData, ajaxObj.delay);
}
},
fail: function(jqXHR, textStatus, errorThrown) {
console.log(errorThrown);
ajaxObj.errorCount++;
}
};
//Ajax master routine
function getMarkerData() {
$.ajax(ajaxObj.options)
.done(setMarkers) //fires when ajax returns successfully
.fail(ajaxObj.fail) //fires when an ajax error occurs
.always(ajaxObj.get); //fires after ajax success or ajax error
}
setMarkers(locs);//Create markers from the initial dataset served with the document.
//ajaxObj.get();//Start the get cycle.
// *******************
//test: simulated ajax
/*
var testLocs = {
1: { info:'1. New Random info and new position', lat:-37, lng:124.9634 },//update info and position and
2: { lat:70, lng:14.5144 },//update position
3: { info:'3. New Random info' },//update info
4: { remove: true },//remove marker
5: { info:'55555. Added', lat:-37, lng:0 }//add new marker
};
setTimeout(function() {
setMarkers(testLocs);
}, ajaxObj.delay);
*/
// *******************
});
At the bottom of the code, you'll find a testLocs
dataset, demonstrating the range of possibilities for adding/removing/updating markers after the initial dataset has been applied.
I've not tested the ajax fully, but have simulated it with the testLocs
dataset.
See DEMO
After 10 seconds, testLocs
will be applied and you will see various changes to the markers (and the info displayed in the infowindow). Note in particular that update data doesn't need to be complete - just specify the changes.
You will need to arrange for your server to :
locs
example.testLocs
example.I have included all the client-side code necessary for fetching new datasets. All you need to do is :
url: "........",
to point to the server-side script, eg url: "get_markers.php"
.ajaxObj.get();
.I have added a boolean "behavioural switch" named auto_remove
. When set to true, a small additional block of code will run, causing all markers for unreported locs to be removed.
This will allow you to report all active markers at every iteration. Removals will happen automatically, without needing to actively command them.
The code which responds to { remove: true }
is still in place, so (with auto_remove
set to false
) removals can be expressly commanded if you ever need to do so.
Updated DEMO
The PHP script should build an array of the following form :
<%php
$testLocs = array(
'loc1' => array( 'info' => '1. New Random info and new position', 'lat' => 0, 'lng' => 144.9634 ),
'loc2' => array( 'lat' => 0, 'lng' => 14.5144 ),
'loc3' => array( 'info' => '3. New Random info' ),
'loc5' => array( 'info' => '55555. Added', 'lat' => 0, 'lng' => 60 )
);
echo json_encode($testLocs);
exit();
%>
I'm not sure whether PHP will handle numeric keys. If not, then try strings, '1'
, '2'
etc. It's probably safest to give all keys an alphabetic prefix, eg. 'loc1'
, 'loc2'
etc. Whatever you choose to do, make sure the keys in the javascript locs
object are of the same type and composition.