Answered by:
Multiple pin layers; deleting pins from the bottom layer

Question
-
Hi everyone,
I am currently developing a disaster app using Bing maps. I have two pin layers:
1) The first layer (User layer) allows the user to plot their own location or another location they are interested in. For the pins in this layer, I have created a table for the user to track their plots and I have delete buttons for each pin in the table that allows the user to delete that location and pin.
2) The second layer (Events layer) currently pulls earthquake data from USGS and plots it on the map. I activate this using a button.
After activating the Events layer, I am still able to delete pins from the User layer if they are added before I activate the Events layer. However, I am no longer able to delete pins that are on the User layer if they are added after activating the Events layer. Does anyone know why?
Wednesday, July 26, 2017 12:46 PM
Answers
-
You are creating a Layer, but adding it to map.entities which will not work. You need to add layers to map.layers using the insert function. So this "map.entities.push(pinLayer);" should be "map.layers.insert(pinLayer);". Then to remove you can use
You are also calling "addPinToMap(pinLayer, coordinates);" inside of a loop which means you are adding the same layer multiple times to the map which will cause issues. Move this outside of your for loop.
To remove the layer by index use, "map.layers.removeAt(idx);".
Minor improvement, move this "Microsoft.Maps.Events.addHandler(pin, 'click', displayInfobox);" outside of the for loop and replace "pin" with "pinLayer". This will add the click event to the layer rather than to individual pushpins. It will fire only when the pushpins are clicked but adds a small performance boost as there would be a lot less event handlers for the map to deal with.
- Proposed as answer by Ricky_Brundritt Monday, July 31, 2017 1:18 PM
- Marked as answer by Timothylaiwg Tuesday, August 1, 2017 5:34 AM
Monday, July 31, 2017 1:18 PM
All replies
-
-
<g class="gr_ gr_3 gr-alert gr_gramm gr_inline_cards gr_run_anim Punctuation only-ins replaceWithoutSep" data-gr-id="3" id="3">Hi</g> Ricky, this is the relevant code:
$(document).ready(function() { //apiKey info var apiKey = "BING MAP API KEY"; //array that stores pushpin info var pushPinInfo = []; var location = []; var eventPin = []; //delay calling map var timeoutID = window.setTimeout(createMap, 1500); //get current time var time = new Date().getTime(); //create map function createMap() { //generating map options var mapOptions = { credentials: apiKey, mapTypeId: Microsoft.Maps.MapTypeId.road, zoom: 9 }; //print map map = new Microsoft.Maps.Map("#myMap", mapOptions); }; //add entered primary form data to pinLayer function addPinLayer() { //creating layers var pinLayer = new Microsoft.Maps.Layer(); //generating pushpins and placing them in pin layer var coordinates = new Microsoft.Maps.Location(pushPinInfo[pushPinInfo.length - 1][0], pushPinInfo[pushPinInfo.length - 1][1]); var pin = new Microsoft.Maps.Pushpin(coordinates, {title:pushPinInfo[pushPinInfo.length - 1][3], color:pushPinInfo[pushPinInfo.length - 1][4], 'draggable': true}); pinLayer.add(pin); //placing pin on map addPinToMap(pinLayer, coordinates); }; //function to add pin to map and zoom to coordinates function addPinToMap(pinLayer, coordinates) { map.entities.push(pinLayer); bestView(coordinates); }; function bestView(coordinates) { var maxLat = -90; var minLat = 90; var maxLong = -180; var minLong = 180; var centerLat = 0; var centerLong = 0; for (var i = 0; i < pushPinInfo.length; i++) { if (maxLat < pushPinInfo[i][0]) { maxLat = pushPinInfo[i][0] } if (minLat > pushPinInfo[i][0]) { minLat = pushPinInfo[i][0] } if (maxLong < pushPinInfo[i][1]) { maxLong = pushPinInfo[i][1] } if (minLong > pushPinInfo[i][1]) { minLong = pushPinInfo[i][1] } }; centerLat = (maxLat + minLat) / 2; centerLong = (maxLong + minLong) / 2; var centerPoint = new Microsoft.Maps.Location(centerLat, centerLong); var sw = new Microsoft.Maps.Location(minLat, minLong); var ne = new Microsoft.Maps.Location(maxLat, maxLong); var rectangle = new Microsoft.Maps.LocationRect.fromCorners(sw, ne); if (pushPinInfo.length == 1) { map.setView({center: coordinates}); } else { map.setView({bounds:rectangle}); } }; //update table info function updateTable() { //remove table hidden attribute $("#outputPanel").removeAttr("hidden"); //delete table contents for refresh of table //easier to reload information from array $(".tableItem").empty(); //add row for latest pin added for (var j = 0; j <pushPinInfo.length; j++) { $("#table tbody:last-child").append( "<tr class='tableItem'>" + "<th>" + (j + 1) + "</th>" + "<th>" + pushPinInfo[j][2] + "</th>" + "<th>" + pushPinInfo[j][0].toFixed(5) + "</th>" + "<th>" + pushPinInfo[j][1].toFixed(5) + "</th>" + "<th>" + '<button type="button" class="btn btn-info btn-sm deletePin" id="delButton' + (j) + '">Delete Pin</button>' + "</th>" + "</tr>"); } }; //remove pin handler function removePinFromMap(index) { map.entities.removeAt(index); }; function timeSince(date) { var seconds = Math.floor((new Date() - date) / 1000); var interval = Math.floor(seconds / 31536000); if (interval > 1) { return interval + " years"; } interval = Math.floor(seconds / 2592000); if (interval > 1) { return interval + " months"; } interval = Math.floor(seconds / 86400); if (interval > 1) { return interval + " days"; } interval = Math.floor(seconds / 3600); if (interval > 1) { return interval + " hours"; } interval = Math.floor(seconds / 60); if (interval > 1) { return interval + " minutes"; } return Math.floor(seconds) + " seconds"; } //click function for primary submit button $("#submitPrimaryForm").click(function () { //check user has entered something if ($("#location").val().length > 0) { //send location query to bing maps REST api var query = $("#location").val(); $.getJSON('http://dev.virtualearth.net/REST/v1/Locations?query=' + encodeURIComponent(query) + "&key=" + apiKey +"&jsonp=?", function (result) { if (result.resourceSets[0].estimatedTotal > 0) { //check user has entered description if ($("#description").val().length != 0) { //get coordinates var loc = result.resourceSets[0].resources[0].point.coordinates; //description of the venue var description = $("#description").val(); var des; //check if checkboxed is checked if ($("#desCheck").prop("checked")) { des = description; } else { des = ""; }; //if pin color is checked in form var col = $('input[name=pinColor]:checked', "#pinDetails").val(); //form array of pin details and add to pushPinInfo array var addPin = [loc[0], loc[1], description, des, col]; pushPinInfo.push(addPin); //take new pin info and publish pin layer and table addPinLayer(); updateTable(); $("#errorPanel").removeAttr("hidden").addClass("alert-success").removeClass("alert-danger").html("<strong>Pin added.</strong>"); } else { $("#errorPanel").removeAttr("hidden").addClass("alert-danger").removeClass("alert-success").html("<strong>Please enter a description.</strong>"); } } else { $("#errorPanel").removeAttr("hidden").addClass("alert-danger").removeClass("alert-success").html("<strong>Sorry that address cannot be found.</strong>"); } }); } else { $("#errorPanel").removeAttr("hidden").addClass("alert-danger").removeClass("alert-success").html("<strong>Please enter an address</strong>"); } }); //delegated click handler for delete pin button $(document).delegate(".deletePin", "click", function(e) { //get button id var buttonId = e.target.id; var index = buttonId[buttonId.length - 1]; pushPinInfo.splice(index, 1); removePinFromMap(index); updateTable(); $("#errorPanel").addClass("alert-success").removeClass("alert-danger").html("<strong>Pin deleted.</strong>"); }); //add event pin with infobox function eventPinLoad() { var pinLayer = new Microsoft.Maps.Layer(); for (var i = 0; i < eventPin.length; i++) { //generating pushpins and placing them in pin layer var coordinates = new Microsoft.Maps.Location(eventPin[i][0], eventPin[i][1]); var pin = new Microsoft.Maps.Pushpin(coordinates, {'draggable': false}); //Create an infobox at the center of the map but don't show it. infobox = new Microsoft.Maps.Infobox(pin.getLocation(), { visible: false }); //Assign the infobox to a map instance. infobox.setMap(map); //Store some metadata with the pushpin. pin.metadata = { title: eventPin[i][2], description: eventPin[i][3] }; pinLayer.add(pin); addPinToMap(pinLayer, coordinates); Microsoft.Maps.Events.addHandler(pin, 'click', displayInfobox); } }; function displayInfobox(e) { //Make sure the infobox has metadata to display. if (e.target.metadata) { //Set the infobox options with the metadata of the pushpin. infobox.setOptions({ location: e.target.getLocation(), title: e.target.metadata.title, description: e.target.metadata.description, visible: true }); } } function earthquakes() { callUSGS(); // Loop through the results array and place a marker for each // set of coordinates. var latestEarthquake; window.eqfeed_callback = function(results) { // latestEarthquake = results.features[0].properties.title; // alert(latestEarthquake); for (var i = 0; i < results.features.length; i++) { var loc = results.features[i].geometry.coordinates; // var coordinates = new Microsoft.Maps.Location(loc[1],loc[0]); //create description var mag = (results.features[i].properties.mag).toString(); // add title var title = "M" + mag + " Earthquake"; //add description var eventTime = results.features[i].properties.time; var timeString = (timeSince(eventTime)).toString(); var earthquakePlace = (results.features[i].properties.place).toString(); var url = results.features[i].properties.url; var des = "<a href='" + url + "'>A M" + mag + " earthquake occured " + timeString + " ago at " + earthquakePlace + ".</a>"; var earthquakeArray = [loc[1], loc[0], title, des]; eventPin.push(earthquakeArray); eventPinLoad() } } } $("#test").on("click", earthquakes) });
Hope this clarifies my problem.
-Tim
Monday, July 31, 2017 9:31 AM -
You are creating a Layer, but adding it to map.entities which will not work. You need to add layers to map.layers using the insert function. So this "map.entities.push(pinLayer);" should be "map.layers.insert(pinLayer);". Then to remove you can use
You are also calling "addPinToMap(pinLayer, coordinates);" inside of a loop which means you are adding the same layer multiple times to the map which will cause issues. Move this outside of your for loop.
To remove the layer by index use, "map.layers.removeAt(idx);".
Minor improvement, move this "Microsoft.Maps.Events.addHandler(pin, 'click', displayInfobox);" outside of the for loop and replace "pin" with "pinLayer". This will add the click event to the layer rather than to individual pushpins. It will fire only when the pushpins are clicked but adds a small performance boost as there would be a lot less event handlers for the map to deal with.
- Proposed as answer by Ricky_Brundritt Monday, July 31, 2017 1:18 PM
- Marked as answer by Timothylaiwg Tuesday, August 1, 2017 5:34 AM
Monday, July 31, 2017 1:18 PM -
You are creating a Layer, but adding it to map.entities which will not work. You need to add layers to map.layers using the insert function. So this "map.entities.push(pinLayer);" should be "map.layers.insert(pinLayer);". Then to remove you can use
The sentence above is cut off. Is there another line of code that should be there?
Tuesday, August 1, 2017 7:20 AM -