Displaying popup values of markers in leaflet - javascript

I'm trying to display markers on a map using Leaflet. On clicking each marker, I'm trying to display a variable inside a popup but I am not able to do so. However, if the same thing is done inside the alert method, the variable gets displayed. What am I doing wrong?
var map = L.map('map').setView([51.505, -0.09], 12);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
var latlngs = [[51.49,-0.11],[51.51,-0.13],[51.505,-0.09],[51.507,-0.08], [51.509,-0.07]];
var speed = [1,2,3,4,5]
var time = [12,14,15,16]
var test = 1
customMarker = L.CircleMarker.extend({
options: {
}
});
for (var i = 0, len = latlngs.length; i < len; i++) {
var m = new customMarker(latlngs[i], {
speed: speed[i],
time: time[i]
});
m.on('mouseover', function() {
//alert('Speed at this point' + this.options.speed)
this.bindPopup(this.options.speed).openPopup()
})
m.addTo(map);
}
var polyline = L.polyline(latlngs,{});
polyline.addTo(map);

bindPopup accepts multiple types for its content argument :
bindPopup(<String|HTMLElement|Function|Popup>content, <Popup options> options?)
You're passing an integer, not a string and that confuses Leaflet into looking for a DOM node named 1. Cast your value to a string and your problem disappears :
this.bindPopup(this.options.speed+"").openPopup()
And a demo
var map = L.map('map').setView([51.505, -0.09], 12);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
var latlngs = [[51.49,-0.11],[51.51,-0.13],[51.505,-0.09],[51.507,-0.08], [51.509,-0.07]];
var speed = [1,2,3,4,5]
var time = [12,14,15,16]
var test = 1
customMarker = L.CircleMarker.extend({
options: {
}
});
for (var i = 0, len = latlngs.length; i < len; i++) {
var m = new customMarker(latlngs[i], {
speed: speed[i],
time: time[i]
});
m.on('mouseover', function() {
this.bindPopup(this.options.speed+"").openPopup()
})
m.addTo(map);
}
var polyline = L.polyline(latlngs,{});
polyline.addTo(map);
html, body {
height: 100%;
margin: 0;
}
#map {
width: 100%;
height: 100%;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.2.0/dist/leaflet.css" integrity="sha512-M2wvCLH6DSRazYeZRIm1JnYyh22purTM+FDB5CsyxtQJYeKq83arPe5wgbNmcFXGqiSH2XR8dT/fJISVA1r/zQ==" crossorigin=""/>
<script src="https://unpkg.com/leaflet#1.2.0/dist/leaflet.js" integrity="sha512-lInM/apFSqyy1o6s89K4iQUKg6ppXEgsVxT35HbzUupEVRh2Eu9Wdl4tHj7dZO0s1uvplcYGmt3498TtHq+log==" crossorigin=""></script>
<div id='map'></div>

Related

Cant get my marker's latLng to use in L.Routing.control

guys
I been trying to get my markers latlon when user double click on it but still don't get any results. Been trying other methods but i think this is the most accurate since i dont get any error when executing js
Any recommendation pls
var places = [
["LOCATION_1", 8.9856146341374, -79.51102268985925],
["LOCATION_2", 8.984640842221594, -79.51383510471848],
["LOCATION_3", 8.972080043026754, -79.5529245611453],
["LOCATION_4", 9.052896045979661, -79.4515923525883],
["LOCATION_5", 9.053366385577624, -79.50832832626823]
];
var map = L.map('map', {
center: [9.352867999999996, -79.689331],//[35.791188, -78.636755],
zoom: 9,
layers:L.tileLayer('http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}',{
maxZoom: 20,
subdomains:['mt0','mt1','mt2','mt3']
})
});
for (var i = 0; i < places.length; i++) {
marker = new L.marker([places[i][1], places[i][2]])
.bindPopup(places[i][0])
.addTo(map);
}
function getdest(){
L.marker.on('dblclick',function(e){
var latlng_dest=e.latlng() });
console.log(latlng_dest)
return latlng_dest
}
navigator.geolocation.getCurrentPosition(function(location) {
var latlng_orig = new L.LatLng(location.coords.latitude, location.coords.longitude);
L.Routing.control({
waypoints: [
//L.latLng(9.10607301250145, -79.34754531445351),
L.latLng(latlng_orig)
//,L.latLng(latlng_dest)
//,L.latLng(9.100769244670843, -79.35099352767948)
,L.latLng(getdest())
]
}).addTo(map)
});
You have many common things wrong:
e.latlng() is not a function it is a property e.latlng
L.marker.on('dblclick',function(e){ this makes no sense. You creating a new instance of a Marker without coords and then adding a listener to it.
You can't return a value in a function from a listener. The listener is not called at the moment you return the value L.marker.on('dblclick',function(e){ var latlng_dest=e.latlng() }); return latlng_dest
Your code should look like that:
for (var i = 0; i < places.length; i++) {
marker = new L.marker([places[i][1], places[i][2]])
.bindPopup(places[i][0])
.addTo(map)
.on('dblclick', function(e) {
waypoints.push(e.latlng);
routeControl.setWaypoints(waypoints);
});
}
var routeControl = L.Routing.control({
waypoints: [],
}).addTo(map);
var waypoints = [];
navigator.geolocation.getCurrentPosition(function(location) {
var latlng_orig = new L.LatLng(location.coords.latitude, location.coords.longitude);
waypoints.push(latlng_orig);
});

Leaflet Tag Filter Button and MarkerCluster.LayerSupport Plugins - Integration to make filters on click update the clusters

I have 2 plugins that I want to work together: Leaflet Tag Filter Button made by maydemirx and MarkerCluster.LayerSupport made by ghybs (both awesome people and plugins btw). What I want to happen is when I click a filter on the tag filter button, I would like the marker clusters to update based on the new filter (like this). So a cluster of 5 points becomes 2, or a cluster of 10 becomes 1 marker. I succeeded in adding the layerSupported cluster to my map, so there's no hiccup there. I am unsure, though, how to integrate the supported cluster with the tag filter buttons, as they are two separate entities.
The Leaflet Tag Filter Button does support an update() method and an enablePruneCluster method, both of which sound like they could be used to achieve what I'm looking for. Yet, when I apply them individually to the filter buttons, they don't work. I'm either applying the filter button methods incorrectly, creating the layerSupported cluster inaccurately, and/or the plugins were not made to be compatible with each other.
Here is my code for generating the layer supported marker cluster group:
var clusters = L.markerClusterGroup.layerSupport({maxClusterRadius:75}),
group1 = L.layerGroup();
var getjson = $.getJSON("map-v2.geojson",function(data){
var bev = L.geoJson(data,{
pointToLayer: function(feature,latlng){
var marker = L.marker(latlng, { tags: feature.properties.Genres.concat(feature.properties.Creator)});
marker.bindPopup('<p align=center>' + '<strong>Title: </strong>' + feature.properties.Title + '<br/><img src="' + feature.properties.Thumbnail_URL + '"/><br/>' + '<strong>Date: </strong>' + feature.properties.Date + '<br/>' + '<strong>Creator: </strong>' + feature.properties.Creator, {minWidth : 250});
return marker;
}
});
bev.addTo(group1);
clusters.addLayer(group1);
map.addLayer(clusters);
});
// Here is where I add the layer supported clusters to the map.
clusters.checkIn(group1);
clusters.addTo(map);
Here is the section where I generate the tag filter buttons:
// Here is the code block for the Tag Filter Button. I start by accessing a tags file that has the data that I use for filter options. I should note that the genres.addToRelated is not working (it is supposed to link the 2 buttons together to work in conjunction with each other).
$.getJSON('tags.json', function(data) {
var genres = L.control.tagFilterButton({
data: data.genres,
filterOnEveryClick: true,
icon: '<i class="fas fa-tags"></i>',
}).addTo(map);
var creators = L.control.tagFilterButton({
data: data.creators,
filterOnEveryClick: true,
icon: '<i class="fas fa-user-edit"></i>',
}).addTo(map);
jQuery('.easy-button-button').click(function() {
target = jQuery('.easy-button-button').not(this);
target.parent().find('.tag-filter-tags-container').css({
'display' : 'none',
});
});
genres.addToRelated(creators);
genres.update(clusters);
genres.enablePruneCluster(clusters);
});
If you'd like to see it all in action, here is a plunker of the code.
Strangely the Leaflet Tag Filter Button plugin and/or latest Leaflet version look to have some bugs / listeners that may pause the script (hence the browser) when the Web Console is open.
Once those bugs are fixed, there are still bugs with the "addToReleated" method. Since I do not know what it is supposed to do, I will just ignore it for now, and let you possibly fix it with the plugin author.
As for integration with the Leaflet.markercluster plugin, it really does not look like the 1st plugin is supposed to support it. PruneCluster plugin (for which the enablePruneCluster method of Tag Filter Button is intended) works very differently from Leaflet.markercluster.
By having a look into the source code of Tag Filter Button, it seems that you could implement it by adapting the enablePruneCluster code and the hide function of the call to registerCustomSource in the default _prepareLayerSources. The idea is to avoid using directly the _map, and use an MCG instead.
Since you can directly handle calls to MCG addLayers and removeLayers within the hide function, there is really no need for the Leaflet.MarkerCluster.LayerSupport plugin at all.
Here is a quick and dirty implementation, called "enableMCG":
////////////////////////////////////////////////
// Quick and dirty implementation of enableMCG
////////////////////////////////////////////////
L.Control.TagFilterButton.include({
// Goal: read from MCG instead of from _map
enableMCG: function(mcgInstance) {
this.registerCustomSource({
name: 'mcg',
source: {
mcg: mcgInstance,
hide: function(layerSource) {
var releatedLayers = [];
for (
var r = 0; r < this._releatedFilterButtons.length; r++
) {
releatedLayers = releatedLayers.concat(
this._releatedFilterButtons[r].getInvisibles()
);
}
var toBeRemovedFromInvisibles = [],
i,
toAdd = [];
for (var i = 0; i < this._invisibles.length; i++) {
if (releatedLayers.indexOf(this._invisibles[i]) == -1) {
for (
var j = 0; j < this._invisibles[i].options.tags.length; j++
) {
if (
this._selectedTags.length == 0 ||
this._selectedTags.indexOf(
this._invisibles[i].options.tags[j]
) !== -1
) {
//this._map.addLayer(this._invisibles[i]);
toAdd.push(this._invisibles[i]);
toBeRemovedFromInvisibles.push(i);
break;
}
}
}
}
// Batch add into MCG
layerSource.mcg.addLayers(toAdd);
while (toBeRemovedFromInvisibles.length > 0) {
this._invisibles.splice(
toBeRemovedFromInvisibles.pop(),
1
);
}
var removedMarkers = [];
var totalCount = 0;
if (this._selectedTags.length > 0) {
//this._map.eachLayer(
layerSource.mcg.eachLayer(
function(layer) {
if (
layer &&
layer.options &&
layer.options.tags
) {
totalCount++;
if (releatedLayers.indexOf(layer) == -1) {
var found = false;
for (
var i = 0; i < layer.options.tags.length; i++
) {
found =
this._selectedTags.indexOf(
layer.options.tags[i]
) !== -1;
if (found) {
break;
}
}
if (!found) {
removedMarkers.push(layer);
}
}
}
}.bind(this)
);
for (i = 0; i < removedMarkers.length; i++) {
//this._map.removeLayer(removedMarkers[i]);
this._invisibles.push(removedMarkers[i]);
}
// Batch remove from MCG
layerSource.mcg.removeLayers(removedMarkers);
}
return totalCount - removedMarkers.length;
},
},
});
this.layerSources.currentSource = this.layerSources.sources[
'mcg'
];
},
});
////////////////////////////////////////////////
// Fix for TagFilterButton
////////////////////////////////////////////////
L.Control.TagFilterButton.include({
_prepareLayerSources: function() {
this.layerSources = new Object();
this.layerSources['sources'] = new Object();
this.registerCustomSource({
name: 'default',
source: {
hide: function() {
var releatedLayers = [];
for (var r = 0; r < this._releatedFilterButtons.length; r++) {
releatedLayers = releatedLayers.concat(
this._releatedFilterButtons[r].getInvisibles()
);
}
var toBeRemovedFromInvisibles = [],
i;
// "Fix": add var
for (var i = 0; i < this._invisibles.length; i++) {
if (releatedLayers.indexOf(this._invisibles[i]) == -1) {
// "Fix": add var
for (var j = 0; j < this._invisibles[i].options.tags.length; j++) {
if (
this._selectedTags.length == 0 ||
this._selectedTags.indexOf(
this._invisibles[i].options.tags[j]
) !== -1
) {
this._map.addLayer(this._invisibles[i]);
toBeRemovedFromInvisibles.push(i);
break;
}
}
}
}
while (toBeRemovedFromInvisibles.length > 0) {
this._invisibles.splice(toBeRemovedFromInvisibles.pop(), 1);
}
var removedMarkers = [];
var totalCount = 0;
if (this._selectedTags.length > 0) {
this._map.eachLayer(
function(layer) {
if (layer && layer.options && layer.options.tags) {
totalCount++;
if (releatedLayers.indexOf(layer) == -1) {
var found = false;
for (var i = 0; i < layer.options.tags.length; i++) {
found =
this._selectedTags.indexOf(layer.options.tags[i]) !==
-1;
if (found) {
break;
}
}
if (!found) {
removedMarkers.push(layer);
}
}
}
}.bind(this)
);
for (i = 0; i < removedMarkers.length; i++) {
this._map.removeLayer(removedMarkers[i]);
this._invisibles.push(removedMarkers[i]);
}
}
return totalCount - removedMarkers.length;
},
},
});
this.layerSources.currentSource = this.layerSources.sources['default'];
},
});
////////////////////////////////////////////////
// Adapted from TagFilterButton demo
// https://github.com/maydemirx/leaflet-tag-filter-button/blob/0.0.4/docs/assets/js/main.js
////////////////////////////////////////////////
var osmUrl = 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
osmAttrib =
'© OpenStreetMap contributors',
osm = L.tileLayer(osmUrl, {
maxZoom: 18,
attribution: osmAttrib,
});
// initialize the map on the "map" div with a given center and zoom
var releatedUsageMap = L.map('releated-usage-map')
.setView([50.5, 30.5], 12)
.addLayer(osm);
var mcg = L.markerClusterGroup().addTo(releatedUsageMap);
L.marker([50.521, 30.52], {
tags: ['tomato', 'active']
})
.bindPopup('tomato, active')
.addTo(mcg);
L.marker([50.487, 30.54], {
tags: ['tomato', 'ended']
})
.bindPopup('tomato, ended')
.addTo(mcg);
L.marker([50.533, 30.5], {
tags: ['tomato', 'ended']
})
.bindPopup('tomato, ended')
.addTo(mcg);
L.marker([50.54, 30.48], {
tags: ['strawberry', 'active']
})
.bindPopup('strawberry, active')
.addTo(mcg);
L.marker([50.505, 30.46], {
tags: ['strawberry', 'ended']
})
.bindPopup('strawberry, ended')
.addTo(mcg);
L.marker([50.5, 30.43], {
tags: ['cherry', 'active']
})
.bindPopup('cherry, active')
.addTo(mcg);
L.marker([50.48, 30.5], {
tags: ['cherry', 'ended']
})
.bindPopup('cherry, ended')
.addTo(mcg);
var statusFilterButton = L.control
.tagFilterButton({
data: ['active', 'ended'],
filterOnEveryClick: true,
icon: '<span>suitcase</span>',
})
.addTo(releatedUsageMap);
// Enable MCG integration
statusFilterButton.enableMCG(mcg);
/*var foodFilterButton = L.control
.tagFilterButton({
data: ['tomato', 'cherry', 'strawberry'],
filterOnEveryClick: true,
icon: '<i class="fa fa-pagelines"></i>',
})
.addTo(releatedUsageMap);
foodFilterButton.addToReleated(statusFilterButton);*/
html,
body,
#releated-usage-map {
height: 100%;
margin: 0;
}
<!-- Leaflet -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.3/leaflet.css" media="screen, print" rel="stylesheet" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="">
<script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.3/leaflet.js' integrity="sha512-tAGcCfR4Sc5ZP5ZoVz0quoZDYX5aCtEm/eu1KhSLj2c9eFrylXZknQYmxUssFaVJKvvc0dJQixhGjG2yXWiV9Q==" crossorigin=""></script>
<!-- MarkerCluster Plugin -->
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.3.0/MarkerCluster.css" />
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.3.0/MarkerCluster.Default.css" />
<script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.3.0/leaflet.markercluster.js'></script>
<!-- EasyButton Plugin (compatibility for tagFilterButton) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet-easybutton#2/src/easy-button.css">
<script src="https://cdn.jsdelivr.net/npm/leaflet-easybutton#2/src/easy-button.js"></script>
<!-- tagFilterButton Plugin -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet-tag-filter-button#0.0.4/src/leaflet-tag-filter-button.css">
<script src="https://cdn.jsdelivr.net/npm/leaflet-tag-filter-button#0.0.4/src/leaflet-tag-filter-button.js"></script>
<div id="releated-usage-map"></div>

Dynamically change Leaflet layer

First, to get some context, I asked this a few weeks ago.
I now have Leaflet parsing a folder of gpx files, and drawing all of them in one map instance, using the Omnivore plugin.
Now what I need is for those files to change dynamically. I have a slider that represents a time interval. Each time I use the slider, I narrow the interval in which I want the tracks to be shown.
Ex: My slider goes from 15th of January to the 15th of May. So, the map shows all tracks from that time. If I change the slider to show from the 1st of April to the 15th of May, the map should react accordingly and re-draw the corresponding files, erasing from the map the tracks from before the 1st of April.
The problem is that I can't seem to get it doing this, since I keep getting a
TypeError: Cannot read property 'addLayer' of undefined
When I make a console.log of the layer, in the line where the problem happens, it prints at exactly the same time, the layer and then an undefined. I don't know why this happens and it is very hard do debug.
My code is as follows:
setTimeout(function() {
var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
osmAttrib = '© OpenStreetMap contributors',
osm = L.tileLayer(osmUrl, {maxZoom: 18, attributionControl: false});
var ggl = new L.Google();
angular.element($elem[0]).append(angular.element('<div id="trackmap'+ trackmapCount +'" style="width: 100%; height: calc(100% - 25px); border: 1px solid #ccc"></div>'));
trackmaps[trackmapCount] = new L.Map('trackmap'+ trackmapCount +'', {center: new L.LatLng(center[0], center[1]), zoom: 10});
trackmaps[trackmapCount].addControl(new L.Control.Layers( {'Google':ggl,'OSM':osm}, {}));
console.log('map'+ trackmapCount +'');
var layer1 = osm.addTo(trackmaps[trackmapCount]);
createTracks(jsonRes);
$scope.$watch(function () {
return $elem[0].parentNode.clientWidth;
}, function ( w ) {
if ( !w ) { return; }
for(var i = 0; i < trackmapCount; i++) {
trackmaps[i].invalidateSize();
}
});
$scope.$watch(function () {
return $elem[0].parentNode.clientHeight;
}, function ( h ) {
if ( !h ) { return; }
for(var i = 0; i < trackmapCount; i++) {
trackmaps[i].invalidateSize();
}
});
$scope.$on('$destroy', function() {
rootScopeBroadcast();
});
var rootScopeBroadcast = $rootScope.$on('rootScope:broadcast-timeline_slider', function (event, data) {
for(var i = 0; i < trackmapCount; i++) {
trackmaps[i].removeLayer(runLayer);
}
var new_tracks = sliderProcessing(data.min_time, data.max_time, jsonRes)
createTracks(new_tracks); // THE PROBLEM IS HERE
});
function createTracks (track_list) {
myStyle = {
"color": "#0033ff",
"weight": 5,
"opacity": 0.65,
"clickable": true
};
customLayer = L.geoJson(null, {
style: myStyle,
});
for (var i = 0; i < track_list.length; i += 1) {
runLayer = omnivore.gpx(folderPath + track_list[i], null, customLayer)
.on('ready', function() {
//runLayer.showExtremities('arrowM');
})
.addTo(trackmaps[trackmapCount])
//a console.log of trackmaps[trackmapCount] here shows both the layer and an undefined at the same time
.on('click', function(d) {
console.log(d);
});
}
}
trackmapCount++;
delay = 0;
}, delay);
I'm probably missing some Leaflet re-draw function, or my control code is not correctly placed, but I've messed around with it and it stays the same.

Speed up Google Map

I have a asp.net 4.0 page that loads a Google map, with over 6,000 markers (and growing!)
I am loading the markers from my SQL DB, using a repeater control in the javascript like in this [this example:] (http://www.aspsnippets.com/Articles/ASPNet-Populate-Google-Maps-V3-with-Multiple-Markers-using-Address-Latitude-and-Longitude-values-stored-in-database.aspx)
I have already added marker clustering and done everything I can think of to speed it up.
Some of the markers are added during the initial load, but are not displayed on the map until the user zooms in. (via height:1 width:1 for the cluster icon)
Here is what I want to do, but I'm not sure if it is possible. I want to have my vb codebehind/asp:Repeater load the markers that will display initially. Then in the "Idle" listner, have it load the other markers so that they are ready once the map is zoomed in.
BUT, I can't figure out how to accomplish this. Any ideas?
Here is the bulk of the javascript:
// configure options
var map;
var locations = new Array();
var markers = new Array();
var markerCluster1 = null;
var markerCluster2 = null;
var markerCluster3 = null;
var markerCluster4 = null;
var Style1 = [{url: '../images/m1.png',
height: 48,
width: 48
}];
var Style2 = [{url: '../images/m2.png',
height: 48,
width: 48
}];
var Style3 = [{url: '../images/m3.png',
height: 48,
width: 48
}];
var Style4 = [{url: '../images/m4.png',
textSize: 1,
height: 1,
width: 1
}];
var mcOA1 = {gridSize: 50, maxZoom: 10, styles: Style1};
var mcOA2 = {gridSize: 50, maxZoom: 10, styles: Style2};
var mcOA3 = {gridSize: 50, maxZoom: 10, styles: Style3};
var mcOA4 = {gridSize: 300, maxZoom: 9, styles: Style4, minimumClusterSize: 2};
var infoWindow = new google.maps.InfoWindow();
<asp:Repeater ID="rptMarkers" runat="server" EnableViewState = false>
<ItemTemplate>locations[<%# Eval("i")%>]=new Array(),locations[<%# Eval("i")%>][0]='<%# Eval("PType")%>',locations[<%# Eval("i")%>][1]='<%# Eval("Lat")%>',locations[<%# Eval("i")%>][2]='<%# Eval("Lon")%>',locations[<%# Eval("i")%>][3]='<div class=\"info-window\"><%# Eval("MDesc")%></div>',locations[<%# Eval("i")%>][4]='<%# Eval("Name") %>';
</ItemTemplate>
<SeparatorTemplate></SeparatorTemplate>
</asp:Repeater>
function initialize() {
var myOptions =
<asp:Repeater ID="MapOptions" runat="server">
<ItemTemplate>
{
center: new google.maps.LatLng(<%# Eval("center")%>),
zoom: <%# Eval("zoom")%>,
streetViewControl: false,
mapTypeId: <%# Eval("mapTypeId")%>
}
</ItemTemplate>
</asp:Repeater>
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
for (i = 1; i < locations.length; i++) {
if (typeof(locations[i]) == 'object') {
var icon = "";
switch (locations[i][0]) {
case "A1":
icon = "../images/A13.png";
break;
case "A2":
icon = "../images/A23.png";
break;
case "A3":
icon = "../images/A33.png";
break;
case "A4":
icon="../images/A44.png"
break;
case "Furniture":
icon="../images/Furniture3.png"
break;
case "Property Manager":
icon="../images/PropertyManager3.png"
break;
default:
icon="../images/A13.png"
break;
}
var point = new google.maps.LatLng(locations[i][1], locations[i][2]);
markers[i] = new google.maps.Marker({
position: point,
icon: new google.maps.MarkerImage(icon),
animation: google.maps.Animation.DROP,
title: locations[i][4]
});
markers[i].setMap(map);
google.maps.event.addListener(markers[i], 'click', function() {infoWindow.setContent(locations[i][3]);infoWindow.open(map, markers[i]);});
}
} // for
// check to see which category is selected
var location_selector = document.getElementsByName('loc_sel');
for (var i=0; i < location_selector.length; i++) {
if (location_selector[i].checked) {
var location_type = location_selector[i].value;
}
}
show_markers(location_type);
} // function initialize() {
function show_markers (location_type) {
var temp_markers1 = new Array();
var temp_markers2 = new Array();
var temp_markers3 = new Array();
var temp_markers4 = new Array();
// if the markerClusterer object doesn't exist, create it with empty temp_markers
if (markerCluster1 == null) {
markerCluster1 = new MarkerClusterer(map, temp_markers1, mcOA1);
}
if (markerCluster2 == null) {
markerCluster2 = new MarkerClusterer(map, temp_markers1, mcOA2);
}
if (markerCluster3 == null) {
markerCluster3 = new MarkerClusterer(map, temp_markers1, mcOA3);
}
if (markerCluster4 == null) {
markerCluster4 = new MarkerClusterer(map, temp_markers1, mcOA4);
}
// clear all markers
markerCluster1.clearMarkers();
markerCluster2.clearMarkers();
markerCluster3.clearMarkers();
markerCluster4.clearMarkers();
// iterate through all locations, setting only those in the selected category
for (i = 1; i < locations.length; i++) {
if (typeof(locations[i]) == 'object') {
if (locations[i][0] == location_type) {
markers[i].setVisible(true);
if (locations[i][0] == "A1") {temp_markers1.push(markers[i]);}
if (locations[i][0] == "A2") {temp_markers2.push(markers[i]);}
if (locations[i][0] == "A3") {temp_markers3.push(markers[i]);}
if (locations[i][0] == "A4") {temp_markers4.push(markers[i]);}
} else {
markers[i].setVisible(false);
if (locations[i][0] == "A4") {markers[i].setVisible(true);
temp_markers4.push(markers[i]);}
}
}
} // for
// add all current markers to cluster
markerCluster1.addMarkers(temp_markers1);
markerCluster2.addMarkers(temp_markers2);
markerCluster3.addMarkers(temp_markers3);
markerCluster4.addMarkers(temp_markers4);
} // function show_markers
Thank you all!
One probable solution to this problem may be to fire a query to the SQL DB to fetch all the markers when the map is in the idle state.
google.maps.event.addListener(map, 'idle', function() {
fetchMarkersfromDB();
});
And in the initialize() function pass both this listener and also the showMarker() function call. So that whenever the maps are initialized and displayed the markers at current zoom position would be displaced and during the idle phase the query in the backgroud would fetch remaining markers that can be shown in the next or consequent zoom levels. This way the markers would be ready and performance will be better.
Hope this would help!!

Multiple Locations in Bing Maps in an iframe

I'm trying to get this piece of code to work in an iframe, but I always get the error:
ReferenceError: GetMap is not defined
I am not an advanced programmer, so I have no idea why it works alone, but not in an iframe (and nobody seems to have the same problem)! Help would be very appreciated.
PS: The programming code is mostly from YoYoMyo (who posted it on stackoverflow), I just adapted it for my use
<html>
<head>
<script charset="UTF-8" type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"></script>
<script type="text/javascript" language="JavaScript">
function GetMap() {
var longitude = new Array();
var latitude = new Array();
var title = new Array();
var description = new Array();
longitude[0] = 47.5564154 //two defined locations
latitude[0] = 7.59245395
title[0] = "Basler Münster"
description[0] = "Basel"
longitude[1] = 47.55330556 //second defined Location
latitude[1] = 7.59001851
title[1] = "Theater Basel"
description[1] = "Basel"
var total = 2 //number of locations
var pinInfoBox; //the pop up info box
var infoboxLayer = new Microsoft.Maps.EntityCollection();
var pinLayer = new Microsoft.Maps.EntityCollection();
var apiKey = "AmpgeSj6OVb9ILPwvjyIfwM3qmqm5yccyNGR_mxmbpw2znYZoXxQAz_KVbc84XCC";
map = new Microsoft.Maps.Map(document.getElementById("map"), {credentials: apiKey});
// Create the info box for the pushpin
pinInfobox = new Microsoft.Maps.Infobox(new Microsoft.Maps.Location(0, 0), { visible: false });
infoboxLayer.push(pinInfobox);
for (var i = 0 ; i < total; i++){
//add pushpins
var latLon = new Microsoft.Maps.Location(longitude[i], latitude[i]);
var pin = new Microsoft.Maps.Pushpin(latLon);
pin.Title = title[i];//usually title of the infobox
pin.Description = description[i]; //information you want to display in the infobox
pinLayer.push(pin); //add pushpin to pinLayer
Microsoft.Maps.Events.addHandler(pin, 'click', displayInfobox);
}
map.entities.push(pinLayer);
map.entities.push(infoboxLayer);
map.setView({zoom: 15, center: new Microsoft.Maps.Location(47.55330556, 7.59001851)});
}
function displayInfobox(e)
{
pinInfobox.setOptions({title: e.target.Title, description: e.target.Description, visible:true, offset: new Microsoft.Maps.Point(0,25)});
pinInfobox.setLocation(e.target.getLocation());
}
function hideInfobox(e)
{
pinInfobox.setOptions({ visible: false });
}
</script>
<style>
#map { position: relative; top: 0; left: 0; width: 100%; height: 800px; border:none;}
</style>
</head>
<body onload="GetMap()">
<div id="some stuff" style="width=100%; height:80px">
some text
</div>
<div id="map" style="width=100%; height:800px">
</div>
<div id="some more stuff" style="width=100%; height:80px">
some more text to read
</div>
</body>
</html>
The code looks fine and I'm unable to reproduce the error you are seeing.

Categories

Resources