One pushpin click opens them all - bing

Need help troubleshooting. All of the pushpins open upon clicking a single one opens up every pushpin infobox. I want there to be one pushpin infobox that changes each time a pushpin is clicked, only allowing one infobox to be open at a time.
// BING MAP Java Script
var map = null;
var pinid = 0;
var arrPinInfobox = [];
//Bing V8 start
function GetMap() { //LocInfo, Lat, Long
var _MapElement = document.getElementById("myMap");
if (_MapElement === null || typeof _MapElement === "undefined")
return;
if(jQuery("#pagesitemap_4_noMap").length < 0)
return;
var arrLocInfoRec = [];
var arrLLAdder = [];
var MapCenterLat;
var MapCenterLong;
var ZoomFactor;
var ZipLLSource = jQuery("#hdnZipLL").val();
var LocInfo = jQuery("#hdnCompleteLocInfo").val();
var ZipLL = [];
var Lat = "";
var Long ="";
console.log("Long");
if(typeof LocInfo === "undefined")
{
console.log("locInfo Undefined");
return;
}
if (ZipLLSource.length > 0) {
ZipLL = (ZipLLSource).split("`");
}
if (LocInfo.length > 0) {
arrLocInfoRec = LocInfo.split("|")
}
if (Lat.length > 0 && Long.length > 0) {
MapCenterLat = parseFloat(Lat);
MapCenterLong = parseFloat(Long);
ZoomFactor = 11; //16
}
else if (ZipLL.length >= 2) {
MapCenterLat = parseFloat(ZipLL[0]);
MapCenterLong = parseFloat(ZipLL[1]);
ZoomFactor = 11;
}
var mapOptions = {
credentials: ' ',
center: new Microsoft.Maps.Location(MapCenterLat, MapCenterLong),
mapTypeId: Microsoft.Maps.MapTypeId.Automatic,
zoom: ZoomFactor,
showScalebar: true
}
map = new Microsoft.Maps.Map('#myMap', mapOptions);
var arrPins = [];
var arrPinCenter = [];
//Generating Pins for multiple locations with Lat,Long
for (var locNum = 0; locNum <= arrLocInfoRec.length - 1; locNum++) {
try {
arrLLAdder = arrLocInfoRec[locNum].split("`");
if (arrLLAdder.length >= 13) {
//var latlong = arrLLAdder[11].split(',');
arrPinCenter[locNum] = new Microsoft.Maps.Location(parseFloat(arrLLAdder[11]), parseFloat(arrLLAdder[12]));
arrPinCenter[locNum] = new Microsoft.Maps.Location(parseFloat(arrLLAdder[11]), parseFloat(arrLLAdder[12]));
arrPins[locNum] = new Microsoft.Maps.Pushpin(
arrPinCenter[locNum], {
text: arrLLAdder[8] ,
icon: 'https://www.bingmapsportal.com/Content/images/poi_custom.png',
anchor: new Microsoft.Maps.Point(12, 39)
}
);
var adder = arrLLAdder[2] + '\r\n' + arrLLAdder[4] + '\r\n' + arrLLAdder[6] + arrLLAdder[9] + "\r\n" + arrLLAdder[1]
// Create the infobox for the pushpin
arrPinInfobox[locNum] = new Microsoft.Maps.Infobox(arrPins[locNum].getLocation(),
{ width: 350,
height: 100,
title: arrLLAdder[5],
description: adder,
offset: new Microsoft.Maps.Point(-3,13),
visible: false
});
// Add handler for the pushpin click event.
Microsoft.Maps.Events.addHandler(arrPins[locNum], 'click', displayInfobox);
// Add the Push Pins and InfoBox to the map all at once
if(arrPins.length > 0) {
map.entities.push(arrPins); //[locNum]
}
}
else {
console.log("Invalid Data: arrLocInfoRec[" + locNum + "] = \"" + arrLocInfoRec[locNum] + "\"");
}
} catch (e) {
console.log(e.message + "\r\n" + arrLocInfoRec[locNum]);
}
}
}
function displayInfobox(e) {
//map.entities.push(arrPinInfobox);
console.log("DisplayBox");
for(var i in arrPinInfobox){
arrPinInfobox[i].setOptions({ visible: true });
arrPinInfobox[parseInt(e.target.getText()) - 1].setOptions({ visible: true });
var infobox = arrPinInfobox[i];
infobox.setMap(map);
}
}

Your code in the displayInfobox function loops through all your infoboxes and sets visible to true and adding them to the map. Your code is functioning how it was written.
What you want to do is filter out your infoboxes. Personally I hate the whole array of infobox idea, it is messy. I believe I've recommended before the idea of creating a single infobox and reusing it when a pushpin is clicked. That is the best approach if you only need one infobox to appear at a time. If you want to be able to show multiple infoboxes at a time, store the reference to the infobox in the pushpin some how. All shapes in Bing Maps has a metadata property reserved for your custom data. Also just noticed you add the array of pushpins to the map several times, this will cause issues. Here is a proposed change to your code, I've added a comment with // Ricky: to indicate the changes I made:
// BING MAP Java Script
var map = null;
var pinid = 0;
var arrPinInfobox = [];
//Bing V8 start
function GetMap() { //LocInfo, Lat, Long
var _MapElement = document.getElementById("myMap");
if (_MapElement === null || typeof _MapElement === "undefined")
return;
if(jQuery("#pagesitemap_4_noMap").length < 0)
return;
var arrLocInfoRec = [];
var arrLLAdder = [];
var MapCenterLat;
var MapCenterLong;
var ZoomFactor;
var ZipLLSource = jQuery("#hdnZipLL").val();
var LocInfo = jQuery("#hdnCompleteLocInfo").val();
var ZipLL = [];
var Lat = "";
var Long ="";
console.log("Long");
if(typeof LocInfo === "undefined")
{
console.log("locInfo Undefined");
return;
}
if (ZipLLSource.length > 0) {
ZipLL = (ZipLLSource).split("`");
}
if (LocInfo.length > 0) {
arrLocInfoRec = LocInfo.split("|")
}
if (Lat.length > 0 && Long.length > 0) {
MapCenterLat = parseFloat(Lat);
MapCenterLong = parseFloat(Long);
ZoomFactor = 11; //16
}
else if (ZipLL.length >= 2) {
MapCenterLat = parseFloat(ZipLL[0]);
MapCenterLong = parseFloat(ZipLL[1]);
ZoomFactor = 11;
}
var mapOptions = {
credentials: ' ',
center: new Microsoft.Maps.Location(MapCenterLat, MapCenterLong),
mapTypeId: Microsoft.Maps.MapTypeId.Automatic,
zoom: ZoomFactor,
showScalebar: true
}
map = new Microsoft.Maps.Map('#myMap', mapOptions);
var arrPins = [];
var arrPinCenter = [];
//Generating Pins for multiple locations with Lat,Long
for (var locNum = 0; locNum <= arrLocInfoRec.length - 1; locNum++) {
try {
arrLLAdder = arrLocInfoRec[locNum].split("`");
if (arrLLAdder.length >= 13) {
//var latlong = arrLLAdder[11].split(',');
arrPinCenter[locNum] = new Microsoft.Maps.Location(parseFloat(arrLLAdder[11]), parseFloat(arrLLAdder[12]));
arrPins[locNum] = new Microsoft.Maps.Pushpin(arrPinCenter[locNum], {
text: arrLLAdder[8] ,
icon: 'https://www.bingmapsportal.com/Content/images/poi_custom.png',
anchor: new Microsoft.Maps.Point(12, 39)
});
var adder = arrLLAdder[2] + '\r\n' + arrLLAdder[4] + '\r\n' + arrLLAdder[6] + arrLLAdder[9] + "\r\n" + arrLLAdder[1]
// Create the infobox for the pushpin
//Ricky: Add your infobox as a reference in your pushpin
arrPins[locNum]. metadata = new Microsoft.Maps.Infobox(arrPins[locNum].getLocation(),
{ width: 350,
height: 100,
title: arrLLAdder[5],
description: adder,
offset: new Microsoft.Maps.Point(-3,13),
visible: false
});
// Add handler for the pushpin click event.
Microsoft.Maps.Events.addHandler(arrPins[locNum], 'click', displayInfobox);
}
else {
console.log("Invalid Data: arrLocInfoRec[" + locNum + "] = \"" + arrLocInfoRec[locNum] + "\"");
}
} catch (e) {
console.log(e.message + "\r\n" + arrLocInfoRec[locNum]);
}
}
// Add the Push Pins and InfoBox to the map all at once
//Ricky: Moved this out of the array as you only need to add array of pushpins to the map once.
if(arrPins.length > 0) {
map.entities.push(arrPins); //[locNum]
}
}
function displayInfobox(e) {
//map.entities.push(arrPinInfobox);
console.log("DisplayBox");
//Get infobox from the pushpin, rather than looping through array.
var infobox = e.target.metadata;
infobox.setOptions({ visible: true });
//for(var i in arrPinInfobox){
//arrPinInfobox[i].setOptions({ visible: true });
//arrPinInfobox[parseInt(e.target.getText()) - 1].setOptions({ visible: true });
//var infobox = arrPinInfobox[i];
//infobox.setMap(map);
//}
}
If you want to clean up your code some more I recommend:
get rid of all the array's, there is no need for them.
Use a layer for your pushpins. Add a single click event on the layer rather than on each individual pushpin.

Related

How to get nodes in OpenStreetMap using Leaflet strictly contained in my current view?

I'm able to correctly query data from the OSM api.
I can also show highways and trunks correctly on the map.
However, the query gives me back always results for a fixed zoom even if my current zoom is higher.
this is how i do my call:
var opl = new L.OverPassLayer({
minZoom: 14,
query: '(way({{bbox}})["highway"~"^(' + query + ')$"];);(._;>;);out geom;',
onSuccess: function (data) {
console.log(data);
urlxml = data.urlxml;
data = data.result;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
// Typical action to be performed when the document is ready:
//document.getElementById("demo").innerHTML = xhttp.responseText;
$("#fileData").text(xhttp.responseText);
console.log(xhttp.responseText);
}
};
xhttp.open("GET", urlxml, true);
console.log(urlxml);
xhttp.send();
console.log(urlxml);
for (let i = 0; i < data.elements.length; i++) {
let pos;
let marker;
const e = data.elements[i];
if (e.id in this._ids) {
continue;
}
this._ids[e.id] = true;
if (e.type === "way") {
let posWay = [];
for (let j = 0; j < e.geometry.length; j++) {
pos = L.latLng(e.geometry[j].lat, e.geometry[j].lon);
posWay.push(pos);
}
var polyline = L.polyline(posWay, { color: "blue" }).addTo(map);
}
console.log("DATA: " + JSON.stringify(data.elements));
}
},
});
How can i get results from the current view only?
Thank you.

Chart.js click on labels, using bar chart

i need help with my Chart.js interactivity. When I click on the label, I need to return the column(index) number at which I clicked.
I tried to use getElementsAtEvent but it only work if I click directly at chart.
This http://jsfiddle.net/yxz2sjam/ is pretty much what I am looking for but getPointsAtEvent is no longer available in the new versions.
canvas.onclick = function (evt) {
var points = chart.getPointsAtEvent(evt);
alert(chart.datasets[0].points.indexOf(points[0]));
};
I also found this http://jsfiddle.net/1Lngmtz7/ but it isn't working with bar chart.
var ctx = document.getElementById("myChart").getContext("2d");
var myRadarChart = new Chart(ctx, {
type: 'radar',
data: data
})
$('#myChart').click(function (e) {
var helpers = Chart.helpers;
var eventPosition = helpers.getRelativePosition(e, myRadarChart.chart);
var mouseX = eventPosition.x;
var mouseY = eventPosition.y;
var activePoints = [];
helpers.each(myRadarChart.scale.ticks, function (label, index) {
for (var i = this.getValueCount() - 1; i >= 0; i--) {
var pointLabelPosition = this.getPointPosition(i, this.getDistanceFromCenterForValue(this.options.reverse ? this.min : this.max) + 5);
var pointLabelFontSize = helpers.getValueOrDefault(this.options.pointLabels.fontSize, Chart.defaults.global.defaultFontSize);
var pointLabeFontStyle = helpers.getValueOrDefault(this.options.pointLabels.fontStyle, Chart.defaults.global.defaultFontStyle);
var pointLabeFontFamily = helpers.getValueOrDefault(this.options.pointLabels.fontFamily, Chart.defaults.global.defaultFontFamily);
var pointLabeFont = helpers.fontString(pointLabelFontSize, pointLabeFontStyle, pointLabeFontFamily);
ctx.font = pointLabeFont;
var labelsCount = this.pointLabels.length,
halfLabelsCount = this.pointLabels.length / 2,
quarterLabelsCount = halfLabelsCount / 2,
upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),
exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);
var width = ctx.measureText(this.pointLabels[i]).width;
var height = pointLabelFontSize;
var x, y;
if (i === 0 || i === halfLabelsCount)
x = pointLabelPosition.x - width / 2;
else if (i < halfLabelsCount)
x = pointLabelPosition.x;
else
x = pointLabelPosition.x - width;
if (exactQuarter)
y = pointLabelPosition.y - height / 2;
else if (upperHalf)
y = pointLabelPosition.y - height;
else
y = pointLabelPosition.y
if ((mouseY >= y && mouseY <= y + height) && (mouseX >= x && mouseX <= x + width))
activePoints.push({ index: i, label: this.pointLabels[i] });
}
}, myRadarChart.scale);
var firstPoint = activePoints[0];
if (firstPoint !== undefined) {
alert(firstPoint.index + ': ' + firstPoint.label);
}
});
Thank for response.
I solve the problem with
document.getElementById("chart").onclick = function(e)
{
var activeElement = weatherMainChart.lastTooltipActive;
console.log(activeElement[0]._index);
};
this solution register clicks on chart and label, then I restricted it with e.layerY to register only clicks on label section.
document.getElementById("chart").onclick = function(e)
{
var activeElement = weatherMainChart.lastTooltipActive;
if(e.layerY > 843 && e.layerY < 866 && activeElement[0] !== undefined)
console.log(activeElement[0]._index);
};
If you add a click handler through the onClick option you can use the following code using the getElementsAtEventForMode() call:
function handleClick(evt) {
var col;
switch(chartType) {
case "horizontalBar":
this.getElementsAtEventForMode(evt, "y", 1).forEach(function(item) { col = item._index });
break;
case "bar":
this.getElementsAtEventForMode(evt, "x", 1).forEach(function(item) { col = item._index });
break;
}
if (!col) {
return;
}
alert("Column " + col + " was selected");
};
You'll probably need to add extra switch checks for other chart types but I'm sure you get the idea.
Using version 2.4.0, i created an onClick Event, and inside it
var activeIndex = localChart.tooltip._lastActive[0]._index;
var clickCoordinates = Chart.helpers.getRelativePosition(e, localChart.chart);
if (clickCoordinates.y >= 530) { //custom value, depends on chart style,size, etc
alert("clicked on " + localChart.data.labels[activeIndex]);
}
I Solved this problem with single or multiple label click you will be find using true/false
First you need to set your chartJs Id click
below code SessionChart = Your ChartJs ID e.g. ("myChart") I was replace it for my Id
document.getElementById("SessionChart").onclick = function (evt) {
var meta = SubscriberSessionChart.getDatasetMeta(0);
if (meta.$filler.chart.legend.legendItems[0].text.toLowerCase() "sessions")
{
if (meta.$filler.chart.legend.legendItems[0].hidden) {
sessionHidden = true;
}
}
}
here "sessions" = first label text
meta.$filler.chart.legend.legendItems[0].text.toLowerCase() = is your first label
from Array so you can get multiple label's click here true / false
if (meta.$filler.chart.legend.legendItems[0].hidden) = your label is not active then
you will get hidden true otherwise you will get false if not tick on label
by default label tick hidden is false in chart js

Leaflet : Map container is already initialized

The User types some address (Hyderabad,Telanagna) on text field and clicks on Go button
I am fetching the latitude_res and longitude from google Map API as shown below
$(document).on('click', '.gobtn', function(event) {
$.getJSON('https://maps.googleapis.com/maps/api/geocode/json?address=' + address + '', function(data) {
latitude_res = data.results[0].geometry.location.lat;
longitude_res = data.results[0].geometry.location.lng;
}).done(function() {
});
});
I am able to fetch the latitude and longitude , from google API say for example i got the following values
**17.385044
78.910965**
Then i am making a Ajax call again to fetch all the Markers present at this location in our Database .
And finally initializaing the map as shown below
initializeMap(lator,lonor,markers);
function initializeMap(lator, lonor, markers) {
var map = new L.Map('map_canvas', {
center: new L.LatLng(lator, lonor),
zoom: 5
});
var ggl = new L.Google();
var ggl2 = new L.Google('ROADMAP');
map.addLayer(ggl2);
if (markers.length > 0) {
var markers_leafcontainer = new L.MarkerClusterGroup();
var markersList = [];
for (var i = 0; i < markers.length; i++) {
var lat = parseFloat(markers[i].latitude);
var lng = parseFloat(markers[i].longititude);
var trailhead_name = markers[i].address;
var dealerId = markers[i].dealerID_db;
var dealername = markers[i].dealerName_db;
var contentString = "<html><body><div><p><h2>" + dealername + "</h2></p></div></body></html>";
var marker = L.marker(new L.LatLng(lat, lng), {}).on('click', onClick);
$(".howmanyfound").text(markers.length + ' Found');
markers_leafcontainer.addLayer(marker);
}
map.addLayer(markers_leafcontainer);
map.fitBounds(markers_leafcontainer.getBounds()); //set view on the cluster extent
}
}
Only for the first time this is working , from there on i am getting Uncaught Error: Map container is already initialized.
I am using leaflet with google Maps
So, don't initialize the map inside your function.
var map = new L.Map('map_canvas');
initializeMap(lator,lonor,markers);
function initializeMap(lator, lonor, markers) {
map.setView(L.latLng(lator, lonor));
}

Integrating / adding Google Earth View to my map

I am creating an interactive map for a non profit association "Friends of Knox Mountain Park" but I am getting trouble with the Google Earth view.
I've been searching on the web for weeks and none of the solutions I found works for me. Can someone take a look of the code and let me know what I should do to include Google Earth View in the map? Thanks in advance.
The online project: http://www.virtualbc.ca/knoxmountain/
And this is the javascript file (mapa2.js) containing the google map's code:
google.load('earth', '1');
var map;
var googleEarth;
var gmarkers = [];
var iconShadow = new google.maps.MarkerImage('icons/shadow.png',
new google.maps.Size(46, 42),
new google.maps.Point(0,0),
new google.maps.Point(13, 42));
var sites = [
['Apex Trail - Shelter',49.91174271, -119.48507050, 4, '<img src="images/apex_point_high.jpg">','magenta','14'],
['Apex Trail',49.91286999, -119.48413424, 3, '<img src="images/apex_point_low.jpg">','lemon','1'],
['Gordon Trail',49.91971281, -119.47954356, 2, '<img src="images/apex_point_low.jpg">','lemon','1'],
['Paul Tomb Bay',49.92555541, -119.47710250, 1, '<img src="images/tomb_bay.jpg">','lemon','1']
];
var infowindow = null;
var overlay;
// Used to make Google Map quard coords to MapCruncher/BingMaps quard coords
function TileToQuadKey ( x, y, zoom)
{
var quad = "";
for (var i = zoom; i > 0; i--)
{
var mask = 1 << (i - 1);
var cell = 0;
if ((x & mask) != 0)
cell++;
if ((y & mask) != 0)
cell += 2;
quad += cell;
}
return quad;
}
function init() {
var centerMap = new google.maps.LatLng(49.909671, -119.482241);
var myOptions = {
zoom: 10,
center: centerMap,
mapTypeId: google.maps.MapTypeId.SATELLITE
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
// Create the tile layers
// ASTER Tile Layer
myASTEROptions = {
getTileUrl : function (a,b) {
return "http://www.virtualbc.ca/knoxmountain/map/" + TileToQuadKey(a.x,a.y,b) + ".png";
},
isPng: true,
opacity: 1.0,
tileSize: new google.maps.Size(256,256),
name: "ASTER",
minZoom:13,
maxZoom:20
}
ASTERMapType = new google.maps.ImageMapType( myASTEROptions );
map.overlayMapTypes.insertAt(0, ASTERMapType);
// Aerial Tile Layer
myAerialOptions = {
getTileUrl : function (a,b) {
return "http://www.virtualbc.ca/knoxmountain/map/" + TileToQuadKey(a.x,a.y,b) + ".png";
},
isPng: true,
opacity: 1.0,
tileSize: new google.maps.Size(256,256),
name: "Aerial",
minZoom:15,
maxZoom:21
}
AerialMapType = new google.maps.ImageMapType( myAerialOptions );
map.overlayMapTypes.insertAt(1, AerialMapType);
var panorama = new google.maps.StreetViewPanorama(map.getDiv());
panorama.setVisible(false);
panorama.set('enableCloseButton', true);
map.setStreetView(panorama);
panorama.setPosition(centerMap);
setMarkers(map, sites);
setZoom(map, sites);
infowindow = new google.maps.InfoWindow({
content: "Loading..."
});
googleEarth = new GoogleEarth(map);
google.maps.event.addListenerOnce(map, 'tilesloaded', addOverlays);
}
/*
This functions sets the markers (array)
*/
function setMarkers(map, markers) {
for (var i = 0; i < markers.length; i++) {
var site = markers[i];
var siteLatLng = new google.maps.LatLng(site[1], site[2]);
var marker = new google.maps.Marker({
position: siteLatLng,
map: map,
title: site[0],
zIndex: site[3],
html: site[4],
// Markers drop on the map
animation: google.maps.Animation.DROP,
icon: 'http://www.virtualbc.ca/knoxmountain/icons/icon.png',
shadow: iconShadow
});
gmarkers.push(marker);
google.maps.event.addListener(marker, "click", function () {
infowindow.setContent(this.html);
infowindow.open(map, this);
});
}
}
/*
Set the zoom to fit comfortably all the markers in the map
*/
function setZoom(map, markers) {
var boundbox = new google.maps.LatLngBounds();
for ( var i = 0; i < markers.length; i++ )
{
boundbox.extend(new google.maps.LatLng(markers[i][1], markers[i][2]));
}
map.setCenter(boundbox.getCenter());
map.fitBounds(boundbox);
}
// This function picks up the click and opens the corresponding info window
function myclick(i) {
google.maps.event.trigger(gmarkers[i-1], "click");
}
google.maps.event.addDomListener(window, 'load', init);
The first issue I notice with your site is you are linking to http://www.virtualbc.ca/src/googleearth-compiled.js which does not exist.

Google maps api v2 get polygon coordinate

I am a bit of a beginner at google maps api. I managed to let the user to draw a polygon on the map and then I want to get the coordinates on the drew polygon.
I have used the following segment of code but it gave me the following error Uncaught TypeError: Object [object Object] has no method 'getPath'
this is the code that I used
function startShape() {
initialize();
document.getElementById('lat').disabled = true;
document.getElementById('lng').disabled = true;
var polygon = new GPolygon([],"ff0000", 2, 0.7,"ff0000",0.2);
startDrawing(polygon, "Shape " + (++shapeCounter_), function() {
var cell = this;
var area = polygon.getArea();
cell.innerHTML = (Math.round(area / 10000) / 100) + "km<sup>2</sup>";
});
showcoor(polygon);
}
function startDrawing(poly, name, onUpdate) {
map.addOverlay(poly);
poly.enableDrawing(options);
poly.enableEditing({onEvent: "mouseover"});
poly.disableEditing({onEvent: "mouseout"});
GEvent.addListener(poly, "endline", function() {
//var cells = addFeatureEntry(name, color);
//GEvent.bind(poly, "lineupdated", cells.desc, onUpdate);
GEvent.addListener(poly, "click", function(latlng, index) {
if (typeof index == "number") {
poly.deleteVertex(index);
}
});
});
}
function showcoor (poly) {
GEvent.addListener(poly, "endline", function() {
GEvent.addListener(poly, "click", function() {
var str;
var vertices = this.getPath();
for (var i =0; i < vertices.length; i++) {
var xy = vertices.getAt(i);
str += xy.lat() +"," + xy.lng()+"<br />";
}
alert (str);
});
});
}
There is no getPath method on the GPolygon object. See the GPolygon reference.
Instead, you'll need to use getVertexCount() and getVertex(i).
for (var i = 0, I = this.getVertexCount(); i < I; ++i) {
var xy = this.getVertex(i);
str += xy.lat() + ', ' + xy.lng() + '<br />';
}