Google Maps v3 -> Database/mysql -> AJAX -> LOOP -> AJAX -> Loop - javascript

a) the real joke first:
Finally buying Microsoft stuff over the years paid off..
Trying to debug using Chrome, my map was showing just one marker. It was on the correct latlng for the period of the setTimeout, blinks for a small fraction of second, back to same position.
At a certain time, shot code to Explorer by mistake....... voila... code iterates through the database, but does not use the setTimeout for each marker. At Explorer, setTime out (Ex, 5 seconds), means all the markers will show up, with the right infowindow, but it's 5 seconds for all markers. The longer the time, the longer it will stay in one of them (alwyas the same one), going really fast on the other markers. At chrome, the iteration was so fast I could not see the iteration thru the other latlng's. It was just a blink.
b) I guess the problem is that the getJson (or Ajax), using either for loop or $.each (I used all sorts of combinations.....) is combined with the other loop inside the function changeMarker. So there are two loops going on at the same time. However, I don't know how to fix it. If I close the Ajax (or getJson) right after the $.each or for loop, the rest of the code doesn't get the values. Nothing happens (just my alert, which is for debugging purposes).
No, I don't fully understand closures. Yes, I read a bunch of stuff, the main one here, but also here and here and there. but still didn't figure it out to :/
c) Not easy being a newbie, trying to solve a problem for days... and not getting it solved.
Any help will be greatly appreciated!
Here is the code - omitted a long section where map gets personal options.
var BERLIN = new google.maps.LatLng(-32.517683, -46.394393);
var map = null;
var marker = null;
var index = 0;
var infoWindow = null;
var latlng ;
var MY_MAPTYPE_ID = 'custom_style';
function initialize() {
//personal options not included here.
var customMapType = new google.maps.StyledMapType(featureOpts, styledMapOptions);
map.mapTypes.set(MY_MAPTYPE_ID, customMapType);
$.getJSON('php/locationsJson.php',function(json){
$.each( json, function(i, item) {
var lat = this.lat;
var lng = this.lng;
var location = new google.maps.LatLng(json[i].lat,json[i].lng);
alert( json[i].lat +','+json[i].lng );
function dropMarker (map, pos){
return new google.maps.Marker({
map: map,
position: location,
draggable: false,
}); // return
}
function changeMarker() {
if (marker) {
infoWindow.close();
marker.setMap(null);
}
var pos = location[index];
marker = dropMarker(map,pos);
var contentString = ('lat: ' + location.lat() + '<br />' + 'lng: ' + location.lng())
infoWindow.setContent(contentString);
setTimeout(function () {
infoWindow.open(map, marker);
}, 100);
index = (index + 1) % json.length;
setTimeout(function () {
changeMarker();
}, 4000);
}
var customMapType = new google.maps.StyledMapType(featureOpts, styledMapOptions);
infoWindow = new google.maps.InfoWindow()
changeMarker();
}); //$.each
}); //end of getjson
} //end of initialized
Here is fiddle (thanks for the help to get to that point) for the code BEFORE the AJAX. I tried to add the json file in the fiddle, but it's too complex to add json inside the fiddle.
Thank you again for your time.

As your approach in the fiddle works fine, you don't need much modifications to
achieve it via ajax.
Instead of starting the timeouts inside the loop use the loop only to populate the NEIGBORHOODS-array, and after the loop call changeMarker()
The success-callback for $.getJSON:
function(json){
NEIGBORHOODS=[];
$.each(json,
function(){
NEIGBORHOODS.push(new google.maps.LatLng(this.lat,this.lng));
});
changeMarker();
}
The rest of the code may stay as it is in the fiddle.
Working fiddle with ajax-request: http://jsfiddle.net/doktormolle/CVECG/
(Note: In the fiddle I've used $.post() because jsfiddle requires post-requests for JSON, you can use $.getJSON in your application)

Related

Javascript leafletjs get user position for distance calc

I'm currently trying to create a map application, so far the map loads and the custom information and icons work flawlessly. I'd, however, like to show the user how far away (distance) to the marker on the map.
This code is working, but I'd like the "from" variable to be the users current position instead of a predetermined position.
var onePlace = L.marker([63, 20], {icon: thisIcon}).bindPopup('My text'),
theOtherPlace = L.marker([65, 20], {icon: thatIcon}).bindPopup('My text');
var to = onePlace.getLatLng();
var from = theOtherPlace.getLatLng();
var distance = from.distanceTo(to);
To set the users position on the map I use the code from their quickstart guide whick looks something like this
primaryMap.locate({
});
primaryMap.on('locationfound', positionFound);
primaryMap.on('locationerror', positionNotFound);
function positionFound(e) {
var myPosition = L.marker(e.latlng, {
}).addTo(primaryMap);
}
function positionNotFound(e) {
alert(e.message);
}
But how to get the position that I set here in a later stage is what I'm struggling with.
Basically, what I want is this
var myPos = [??].getLatLng();
var to = onePlace.getLatLng();
var distance = myPos.distanceTo(to);
Sorry for the strange formatting on some of the code, first time posting.
Anyway, if someone could help me out here I'd be incredibly thankful. Been stuck on this one problem for forever and can't seem to find anything helpful in the documentation (probably just don't quite understand it as I'm rather new to this).
Thanks in advance!
UPDATE:
jsfiddle: https://jsfiddle.net/xcyniic/98sy6zxb/27/
Maybe this can help shed some light on what I'm doing / have done wrong.
You get the latlng from the locationfound event.
primaryMap.on('locationfound', positionFound);
function positionFound(e) {
var myPos = e.latlng;
var to = onePlace.getLatLng();
var distance = myPos.distanceTo(to);
}
Update
To get the pos value outside you have to create the variable outside and test if it is not null;
var myPos = null;
primaryMap.on('locationfound', positionFound);
function positionFound(e) {
myPos = e.latlng;
calcDistances();
}
function calcDistances(){
if(myPos){
var to = onePlace.getLatLng();
var distance = myPos.distanceTo(to); +
var to2 = twoPlace.getLatLng();
var distance = myPos.distanceTo(to2);
//...
}
}
I think that you are thinking wrong. The locationfound event is not called immediately, it is a async service. So you have to calc the distance after the event is called and the user position is found.

Bing Maps Api clear a layer

I have a page that works well it loads a Bing Map and creates a layer which is then filled with Polygons. I then need to reload the JSON data that makes the polygons and this again works, however the data is then added to another layer so appears over the top. I have tried to delete the layer, clear the layer etc etc but nothing seems to work.
Any idea please.
This is the function that does it all...
function AddData() {
dataLayer = new Microsoft.Maps.Layer();
Microsoft.Maps.loadModule('Microsoft.Maps.GeoJson', function () {
var featureCollection = Microsoft.Maps.GeoJson.read(json, {
polygonOptions: {
strokeColor: 'LightSkyBlue',
strokeThickness: 2
}
});
for (var i = 0; i < featureCollection.length; i++) {
var fillColour = featureCollection[i].metadata.FillColor;
featureCollection[i].setOptions({ fillColor: fillColour });
Microsoft.Maps.Events.addHandler(featureCollection[i], 'click', displayClickBox);
Microsoft.Maps.Events.addHandler(featureCollection[i], 'mouseover', displayMouseOverBox);
Microsoft.Maps.Events.addHandler(featureCollection[i],'mouseout', displayMouseOut);
dataLayer.add(featureCollection[i], 0);
}
map.layers.insert(dataLayer);
});
}
var getJson = function () {
var onContentComplete = function (response) {
//Load the JSON data into the local variable for use latter in the project...
json = response.data;
//load the map now that we have the polygon data...
AddData();
};
var onError = function (reason) {
//An error has occured so display a message to the user...
$scope.error = "Server communication error please try again...";
//Log the error to the console for admin debug...
console.log(reason.data);
};
//Load the JSON for the map polygons into memory ready for display...
$http.get("../JSON/MapData.json")
.then(onContentComplete, onError);
}
As I have said I have tried to clear the layer first using
dataLayer.clear();
But that seems to do nothing.
Help please as I have been working at this for hours now.
Thanks
Cliff.
By the sounds of things you want all data to render in a single layer, but instead it is rendering two or more layers. This happens because you are creating a new instance of dataLayer every time the AddData function is called. Additionally, this overwrites the local variable for dataLayer and thus you lose the reference to the original layer that you are trying to clear/delete. If you want to clear or delete the layer, do that before initializing the new layer. Try adding the following to the top of your AddData function:
if(dataLayer){
map.layers.remove(dataLayer);
}
Alternatively, reuse the layer by clearing it if it exists of or creating it if it doesn't:
if(dataLayer){
dataLayer.clear();
}else{
dataLayer = new Microsoft.Maps.Layer();
}

Weird Issue with Javascript object properties

Apologies in advance if this is an obvious issue. I have done as much searching as I could putting this issue into search terms.
I have the below block of code which is supposed to create a Google maps marker for each 'transponder' if there has not been one added previously. However every time this block of code runs it doesn't detect the previously created marker stored in the transponder object and recreates it.
This is despite seeing the marker within the transponder object in the DOM view of Firebug.
function addOrUpdateTransponderPostionRpt(transponderPositionRpt) {
var t = getTransponderById(transponderPositionRpt.TransponderId);
if (t) {
console.log("Found Transponder: " + t.Id);
if (t.gMapMarker) {
console.log("Transponder has existing marker, updating: " + t.Id);
moveMarker(t.gMapMarker, new google.maps.LatLng(transponderPositionRpt.Latitude, transponderPositionRpt.Longitude));
} else {
console.log("Transponder has no existing marker, creating: " + t.Id);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(transponderPositionRpt.Latitude, transponderPositionRpt.Longitude),
map: map,
title: t.DefaultNickname
});
t.gMapMarker = marker;
}
}
}
debug output from the javascript (the same every time)
Found Transponder: 4
Transponder has no existing marker, creating: 4
Found Transponder: 6
Transponder has no existing marker, creating: 6
Can anyone help ? :)
EDIT: Additional methods referenced in this code block:
function getTransponderById(id) {
var ret;
$.each(transponders, function (i, item) {
if (transponders[i].Id == id) {
ret = transponders[i];
return;
}
});
return ret;
}
function moveMarker(marker, newPosition) {
marker.setPosition(newPosition);
}

Storing javascript data in global array not working as expected [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
change global variable inside javascript closure
I am having a problem storing data in a javascript global array . I can't figure out why the array is empty even though I have assigned it some elements.
Basically I have two functions: loadMarkers is called whenever a user clicks a button and gets some information from a url in JSON, parses that data and stores it in the global array. The other function is showMarkers that just iterates over the array and show all the markers, but that array is empty!
Thansks in advance.
var markers = [];
function loadMarkers(url) {
markers = [];
$.get(url, function(data) {
var json = jQuery.parseJSON(data);
for (var i = 0; i < json.length; i++) {
// parsing json
var lat = json[i].Latitude;
var lng = json[i].Longitude;
var id = json[i].ID;
console.log(id); // this prints with no problems!
// create new marker
var marker = new google.maps.Marker({
position: new google.maps.LatLng(lat, lng),
title: id,
html: "<p>" + "Info for container " + id + "</p>"
});
// add marker to markers array
markers.push(markers[i]);
// add info window to marker
google.maps.event.addListener(marker, "click", function() {
infoWindow.setContent(this.html);
infoWindow.open(map, this);
});
}
});
}
function showMarkers() {
for (i = 0; i < markers.length; i++)
console.log(markers); // here I get an empty array!
markers[i].setMap(map);
}
It seems like this line:
markers.push(markers[i]);
should instead be:
markers.push(marker);
Maybe its the following code
// add marker to markers array
markers.push(marker); // was markers[i]
Regarding your second question in the comments the $.get() method returns a jQuery deferred object which allows you to execute functions after method has finished.
$.get().done( function( ) {
// your code
});
There's a typo in the code:
markers.push(markers[i]);
should be:
markers.push(marker);
It can be surprisingly hard to spot this kind of typos by just looking at the code (it's like our brains are trained to let us read what we expect to read)... In this case the best approach to find quickly these kind of errors is to add a debugger; instruction in the code, and follow along the execution of the program through the devtools of your choice.

Combining Google Maps MarkerClusterer v3 and Viewport Marker Management

I've successfully setup both MarkerClusterer v3 and Viewport Marker Management ( performing an ajax call to gather only markers visible with viewport and rendering those whenever the map is 'idle') separately.
However when I combine them, they only seem to work together when the page first loads and not afterward.
When zooming or panning the initial clusters remain and the markers are for the entire map are rendered unclustered, but leaves the previously clustered markers.
The original clustered markers still behave properly though when you zoom in/out, but the new markers provided when the viewport bounds are changed aren't added to them or clustered.
Code Below:
function drawMap(swLat, swLng, neLat, neLng){
//Load the map data
$.ajax({
type: "POST",
url: "readMapInfo.php",
cache: false,
data:{S:swLat, W:swLng, N:neLat, E:neLng},
dataType: "xml",
success: function(data) {
if(markerArray.length >0){
for (i in markerArray) {
markerArray[i].setMap(null);
}
drawMarker(data); //takes the info provided and performs "markerArray.push(marker);"
mc = new MarkerClusterer(map, markerArray, clusterOptions);
} else {
drawMarker(data); //takes the info provided and performs "markerArray.push(marker);"
mc = new MarkerClusterer(map, markerArray, clusterOptions);
}
});
}
google.maps.event.addListener(map, 'idle', function() {
bounds = map.getBounds();
sw = bounds.getSouthWest();
ne = bounds.getNorthEast();
swLat = sw.lat();
swLng = sw.lng();
neLat = ne.lat();
neLng = ne.lng();
drawMap(swLat, swLng, neLat, neLng);
});
Your description of your problem is detailed and thorough, but it would be easier if there were also a URL to a page that demonstrates the problem(s). Of course, that may not be possible in this specific scenario. That said, I will take a crack at helping out:
I believe you need some additional cleanup code at the beginning of your ajax success callback:
if( markerArray.length > 0 ) {
// For loop logic is unchanged
// It removes the markers from the Map, but leaves them in markerArray
for (i in markerArray) {
markerArray[i].setMap( null );
}
// New code to truncate the Array; the markers should be removed
markerArray.length = 0;
// New code to clear the clusterer; the markers should be removed
mc.clearMarkers();
// Original line of code unchanged
drawMarker(data); //takes the data and performs markerArray.push(marker)
// Commented out, because the cluster is cleared each time, not recreated
//mc = new MarkerClusterer(map, markerArray, clusterOptions);
// New code to refill the cluster, rather than recreate the cluster
// The original clusterOptions are retained
mc.addMarkers( markerArray );
} else {
// Original line of code unchanged
drawMarker(data); //takes the data and performs markerArray.push(marker)
// Original line of code unchanged
// Necessary here, because the clusterer does not yet exist
mc = new MarkerClusterer(map, markerArray, clusterOptions);
}
I believe this will help move you forward. Please let me know if this resolves the problem or at least helps.
After you have your immediate challenges resolved, I also suggest that you take a look at MarkerClustererPlus; it is described in the question: Is there any way to disable the Marker Clusterer for less than defined marker counts?.

Categories

Resources