I'm stuck with a problem that I can't find anywhere else on the internet. Or atleast not what I mean.
In my part of code I have made a popup with an map.on('click') event, however I would like the event to be only possible with one layer and only when that layer is active. As you can see in my code I also want my sidebar to open a tab when the layer is clicked, however now when you click the map anywhere the sidebar will still open.
The layer that I want the sidebar to react to is called: "bottlenecklayer"
The next code is what I currently have, the code at the bottom shows what I've tried as well but did not work.
map.on('click', function(evt){
var feature = map.forEachFeatureAtPixel(evt.pixel,
function(feature) {
return feature;
});
document.getElementById("sidebar").classList.toggle("collapsed");
document.getElementById("pop-up-message").classList.toggle("active");
if (feature) {
var geometry = feature.getGeometry();
var coord = geometry.getCoordinates();
var imagebottleneckbefore = feature.get('Image_before');
var imagebottleneckafter = feature.get('Image_after');
/* if (imagebottleneckbefore === null)
{imagebottleneckbefore = "hidden"};*/
if (imagebottleneckafter === null)
{imagebottleneckafter = "otterplaceholde.jpg"};
if (imagebottleneckafter === "nopic")
{imagebottleneckafter = "otterplaceholde.jpg"};
if (feature.get('Description') === null)
{return "Er is geen beschrijving bij dit knelpunt."};
var contentjson = '<h2 >' + "Knelpunt:" + ' ' + feature.get('Name') + '</h2>';
/* contentjson += "<img src='img/bottleneckpictures/"+imagebottleneckbefore+"' style='width:260px; height:130px;'>";*/
contentjson += ' '
contentjson += "<img src='img/bottleneckpictures/"+imagebottleneckafter+"' style='width:260px; height:130px;'>";
contentjson += '<p class="lorem" >' + feature.get('Description') + '</p>';
// contentjson += '<h3>' + feature.get('Descriptionholder') + '</h3>';
content_elementjson.innerHTML = contentjson;
}
});
This is the part of code that does not work either:
bottlenecklayer.on('click',function(evt){
document.getElementById("sidebar").classList.toggle("collapsed");
document.getElementById("pop-up-message").classList.toggle("active")
});
You need to specify a layerFilter function in the forEachFeatureAtPixel request:
var feature = map.forEachFeatureAtPixel(evt.pixel,
function(feature) {
return feature;
}, {
layerFilter: function(layer) {
return layer === bottlenecklayer;
}
});
Layers do not have click events.
Related
I am using MapBox to render a map. I have made a onClick function wherein when clicked on the map it shows the geocode information shown in the screenshot below through api.
Now what I want is to have a button below the table and when click on it I want it to execute a particular function, I have defined it but when clicked on it says Function is not defined
Code
map.current.on('click', function(e) {
var coordinates = e.lngLat;
var lng = coordinates.lng;
var lat = coordinates.lat;
console.log(lat);
console.log(lng);
var d = fetch("https://api.mapbox.com/geocoding/v5/mapbox.places/" + lng + "," + lat + ".json?access_token={token_value}").then(response => response.json()).then(function(data) {
console.log(data)
var str = "<table border='1'><tr><td><center>Title</center></td><td><center>Content</center></td></tr>"
for (let i in data["features"]) {
str = str + "<tr><td style='padding:5px'>" + data["features"][i]["place_type"][0] + "</td><td style='padding:5px'>" + data["features"][i]["place_name"] + "</td></tr>"
}
str = str + "</table>"
// button
str = str + "<button onClick={myFunction}>Save</button>"
function myFunction() {
console.log('Saved pressed');
}
new mapboxgl.Popup()
.setLngLat(coordinates)
.setHTML(str)
.addTo(map.current)
});
console.log(d);
});
Fix code as below
// button
str += `<button onclick="myFunction()"}>Save</button>`;
I would guess the button (and the function name defined for it) are created with a different scope than where you have defined your function. One of these might work:
Define your function as const myFunction = () => console.log("saved pressed").
Try referencing your function as this.myFunction
Working with the Google maps and places API, I am rendering infowindows for each marker that gets generated by a function generateInfoWindow(location).
In there I create a string HTML that will be passed to the Google maps markers content attribute.
Function
function generateInfoWindow(location) {
var html = "<div class = 'infowindowContainer'>" +
"<span class = 'infoWindowHeader'>" + location.name + "</span>" +
"<div class = 'row'>" +
"<span class = 'col-xs-12'> ... : " + getInfoWindowDetails(location).adress + "</span>" +
"<span class = 'col-xs-12'> ... : " + getInfoWindowDetails(location).open_hours + "</span>";
if (location.offers.length > 0) {
html +=
"<span class = 'col-xs-12 iwOffers'> ... </span>" +
"</div>" + //ends row
"<div class = 'infoWindowCircleContainer'>";
for (var i = 0; i < location.offers.length; i++) {
html += "<span class = 'infoWindowCircle'>" + location.offers[i].offer_text + "</span>";
}
html += "</div>" //CircleContainer
}
html += "<span class = 'showMore' onclick = 'processWin(" + location + ")'>Show more</span>";
html += "</div>"; //InfoWindowContainer the parent to all
return html;
}
function processWin(location) {
var winMarker;
var winnerMap;
var mapOptions = {
zoom: 15,
center: location.geometry.location,
mapTypeId: google.maps.MapTypeId.ROADMAP,
styles: googleMapsStyles
};
var locationId = location.place_id;
var request = {
placeId: locationId
};
places.getDetails(request, getWinnerDetails); //Where getWinnerDetails is the callback
//since the location that we are passing in the callback function is the one we get as a JSON from the detailed search we are going to have to use our modified vars associated with the location here such as .keyword
$("#foodType").text("Typ av mat : " + location.keyword);
winnerMap = new google.maps.Map(document.getElementById('displayWinnerMap'), mapOptions);
for (var i = 0; i < markers.length; i++) {
if (markers[i].placeId == location.place_id) {
winMarker = markers[i];
break;
}
}
//setOfferCircles(location);
winMarker.setMap(winnerMap);
$("#displayWinPage").css("display", "block");
doScroll("#displayWinPage");
}
Where I append the span with the class showMore I wish to append an onclick event that will call a method processWin(location) where I pass the location variable. (Will be multiple markers).
I can't seem to be able to pass the object location in the onclick event and
I don't understand why. Please do enlighten me.
An object converted to a string becomes [object object] and that is what you are passing as the parameter and not the object itself. Here is example code showing the wrong output
var location = {x : 100, y : 100};
var html = "<span class = 'showMore' onclick = 'processWin(" + location + ")'>Show more</span>";
console.log(html);
Output: <span class = 'showMore' onclick = 'processWin([object Object])'>Show more</span>
Using JSON.stringify(location) you get the object output correctly as shown below.
var location = {x : 100, y : 100};
var html = "<span class = 'showMore' onclick = 'processWin(" + JSON.stringify(location) + ")'>Show more</span>";
console.log(html);
Output:<span class = 'showMore' onclick = 'processWin({"x":100,"y":100})'>Show more</span>
I am creating an app that allows the user to check the local weather and temperature in celsius or fahrenheit. However, I am having a problem when toggling between the two unit types when the temperature is clicked on. This is the link to my demo.
And here is my Javascript code:
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
$.getJSON("https://crossorigin.me/http://api.openweathermap.org/data/2.5/weather?lat=" + position.coords.latitude + "&lon=" + position.coords.longitude + "&units=imperial&appid=a62849f462c6573114f32a691f5d3c3f", function(json) {
var all = JSON.stringify(json);
var weather = JSON.stringify(json.weather[0]["description"]);
weather = weather.slice(1, -1);
var tempFahrenheit = JSON.stringify(json.main.temp);
var tempCelsius = JSON.stringify(json.main.temp * 2);
$("#weather").html(weather);
$("#temp").html(Math.floor(tempFahrenheit) + " °<span id='units'>F</span>");
$("#units").on('click', function() {
if ($(this).text() == "F") {
$("#temp").html(Math.floor(tempCelsius) + " °<span id='units'>C</span>");
} else {
$("#temp").html(Math.floor(tempFahrenheit) + " °<span id='units'>F</span>");
}
});
});
});
}
When you replace the html contents of the #temp div, you lose your event handler on the units div as well. Use event delegation instead. Assign the event on the body tag, but listen for events on the #units div.
Updated code:
$("body").on('click', '#units', function() {
if ($(this).text() == "F") {
$("#temp").html(Math.floor(tempCelsius) + " °<span id='units'>C</span>");
} else {
$("#temp").html(Math.floor(tempFahrenheit) + " °<span id='units'>F</span>");
}
});
Working fork of your Codepen: https://codepen.io/anon/pen/AXzYzR?editors=0010
I'm currently using a png as markers but I would like to change the one that get clicked on & active to a different png.
How do I achieve that?
var icon = [
{
"className": "my-icon icon-dc", // class name to style
"html": '<img class="style-svg" src="wp-content/uploads/2016/06/circle.svg" alt="">', // add content inside the marker
"iconSize": [60,60] // size of icon, use null to set the size in CSS
}
];
myLayer.on('layeradd', function(e) {
var marker = e.layer,
feature = e.layer.feature;
marker.setIcon(L.divIcon(feature.properties.icon));
});
// Listen for individual marker clicks.
myLayer.on('click',function(e) {
// Force the popup closed.
e.layer.closePopup();
var feature = e.layer.feature;
var content = '<div><div id="close1" class="absolute_p"><img class="exit" src="/wp-content/uploads/2016/06/X#2x.png"></div>' +
'<img src="' + feature.properties.img + '" alt="">' +
'<h4>' + feature.properties.title + '</h4>' +
'<p>' + feature.properties.description + '</p>' +
'<p class="num">' + feature.properties.num + 'Properties now showing</p>' +
'find your second home here</div>';
info.innerHTML = content;
map.panTo(e.layer.getLatLng());
});
At the end of your click event handling, why not just use setIcon on the e.layer with a reference to an "active"/"clicked" icon you declare somewhere else?
var myNewIcon = L.icon({
iconUrl: 'my-new-icon.png'
});
e.layer.setIcon(myNewIcon)
http://leafletjs.com/reference.html#icon
I have a dropdown menu that I want to put inside a google maps infowindow. The menu is populated with contents from an array. When I position the menu outside the info window it works fine but when I try and put it inside the infowindow it breaks. The end goal is to get a form inside the info window so when I submit the form I can process the form data and return the directions to the marker. I have attached the code below and the problematic line is denoted by ** and thanks in advance for all your help.
Infowindow code:
google.maps.event.addListener(marker, 'click', function () {
service.getDetails(request, function (place, status) {
var locationofplace = place.geometry.location;
var markerlocation = marker.getPosition();
var markerlat = markerlocation.lat();
var markerlng = markerlocation.lng();
if (status == google.maps.places.PlacesServiceStatus.OK) {
var contentStr = '<h5>' + place.name + '</h5><p>' + place.formatted_address;
if (!!place.formatted_phone_number) contentStr += '<br>' + place.formatted_phone_number;
if (!!place.website) contentStr += '<br><a target="_blank" href="' + place.website + '">' + place.website + '</a>'; * * contentStr += '<form><select id="selectNumber"><option>Change Address</option></select></form>'; * *
contentStr += '<br>Get Directions';
contentStr += '<br>' + place.types + '</p>';
infowindow.setContent(contentStr);
infowindow.open(map, marker);
} else {
var contentStr = "<h5>No Result, status=" + status + "</h5>";
infowindow.setContent(contentStr);
infowindow.open(map, marker);
}
});
});
add data to menu code:
window.addEvent('load', function () {
var select = document.getElementById("selectNumber");
for (var i = 0; i < addresses.length; i++) {
var opt = addresses[i];
var el = document.createElement("option");
el.textContent = opt;
el.value = opt;
select.appendChild(el);
}
});
use the domready-event of the infowindow instead of the load-event of the window to manipulate the dropdown(the dropdown hasn't been injected into the document before the domready-event)