Change Mapbox marker image on click - javascript

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

Related

.on('click') event for a single JSON layer, how to?

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 += '&nbsp'
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.

url.content not loading image javascript and asp.net mvc

I have my javascript in my view and I am trying to load an image from my database into an info window for my google maps but the image does not load.
Javascript code in view:
$.get("#Url.Action("GetMarkers","Donator")", function (json, status) {
//Global infoWindow object that will be reused by all markers
var infoWindow = new google.maps.InfoWindow();
var marker, data;
//Loop through the json data
for (var i = 0; i < json.length; i++) {
data = json[i];
var latLng = new google.maps.LatLng(data.Latitude, data.Longitude)
//Creating marker and putting it on the map
marker = new google.maps.Marker({
position: latLng,
map: map,
title: data.NpoName + ' says Click Me!'
});
// Creating a closure to retain the correct data, notice how I pass the current data in the loop into the closure (marker, data)
(function (marker, data) {
// Attaching a click event to the current marker
google.maps.event.addListener(marker, "click", function (e) {
var imageUrl = '<%=Url.Content(' + data.VerificationIcon + ')%>';
infoWindow.setContent('<h3 class="info-window-title">' + data.NpoName + '</h3>' + '<hr />' + '<p>Npo type: ' + data.NpoType + '</p>' + '<p>' + data.VerificationStatus + '<img src="' + imageUrl + '" alt="verification icon" class="verification-icon" />' + '</p>' + 'Click here to donate!');
infoWindow.open(map, marker);
});
})(marker, data);
};
});
Code in controller:
public JsonResult GetMarkers()
{
//Disable lazy loading
db.Configuration.ProxyCreationEnabled = false;
//Map marker section
var DynamicMapMarkers = db.tblNpo.Include(zz => zz.tblVerification).Include(xx => xx.tblNpo_Type);
//Set map marker values
foreach (var item in DynamicMapMarkers)
{
DonatorUserViewModel MapMarkers = new DonatorUserViewModel();
MapMarkers.NpoID = item.npo_id;
MapMarkers.NpoName = item.npo_name;
MapMarkers.NpoType = item.tblNpo_Type.description;
MapMarkers.VerificationStatus = item.tblVerification.description;
MapMarkers.VerificationIcon = item.tblVerification.verification_icon;
MapMarkers.Longitude = Convert.ToDouble(item.longitude);
MapMarkers.Latitude = Convert.ToDouble(item.latitude);
MapMarkerList.Add(MapMarkers);
}
var json = MapMarkerList;
return Json(json, JsonRequestBehavior.AllowGet);
}
Main focus area from the code above:
var imageUrl = '<%=Url.Content(' + data.VerificationIcon + ')%>';
infoWindow.setContent('<h3 class="info-window-title">' + data.NpoName + '</h3>' + '<hr />' + '<p>Npo type: ' + data.NpoType + '</p>' + '<p>' + data.VerificationStatus + '<img src="' + imageUrl + '" alt="verification icon" class="verification-icon" />' + '</p>' + 'Click here to donate!');
The format of the way the image is stored in the database ~/Images/DbImages/verified.png
I am not sure why the image isn't loading, or how to work around it. Any help would be appreciated.

Images and links are not working when they are values of json object properties

I don't know what is happening, but both my images and links are not working, even after declaring globally!?
if I write the src directly into src then everything seems fine , even alert pops the same url and img src! need help guys!
var combo0;
var combo1;
var combo2;
var combo3;
var random;
var images=["../IMAGES/park.jpg","../IMAGES/palace.jpg","../IMAGES/oriental.jpg"]
var weburls=["https://www.royalplaza.com.hk","https://www.caesars.com","http://www.venetianmacao.com/"]
function gethotel(){ // a= check-in b=check-out and c=no-of-rooms
var arraysofobjects=[
combo0=[
],
combo1=[
{hotelname:"The Royal Plaza",purl:"images[0]",rflag:"",weburl:"weburls[0]",description:"Locate"
,price:"HKD 1200"},
],
combo2=[
{hotelname:"The Royal Plaza",purl:"images[0]",rflag:"",weburl:"weburls[0]",description:"Located drive away."
,price:"HKD 1200"},
{hotelname:"Caesars Palace",purl:"images[1]",rflag:"",weburl:"weburls[1]",description:"Built in 1903, the treatments"
,price:"HKD 1900"}
],
combo3=[
{hotelname:"The Royal Plaza",purl:"images[0]",rflag:"",weburl:"weburls[0]",description:"Located in less ."
,price:"HKD 1200"},
{hotelname:"Caesars Palace",purl:"images[1]",rflag:"",weburl:"weburls[1]",description:"Built in 1903, tatments"
,price:"HKD 1900"},
{hotelname:"The Venetian Hotel",purl:"images[2]",rflag:"",weburl:"weburls[2]",description:"The Vor area."
,price:"HKD 2200"}
]
]
random=Math.floor((Math.random() * 4));
return arraysofobjects[random];
}
var object=gethotel();
for(var i=0; i<random;++i) {
var heading = '<h2>' + object[i].hotelname + '</h2>';
var description = '<p>' + object[i].description + '</p>';
var priceho='<h4>' + object[i].price + '</h4>';
//web url
var a = document.createElement('a');
var linkText = document.createTextNode("Offical website");
a.appendChild(linkText);
a.title = "official website";
a.href = object[i].weburl;
var hotel = '<img src="object[i].purl">' + '<div>'+ heading + description + priceho + '<a target="_blank" href=object[i].weburl>Official website</a>' +'</div>';
var str="Details";
var link=this.str.link("room.html");
document.getElementById("hotels").innerHTML+=hotel + link;
}
It looks like is may be because your weburl:"weburls[0]" property value has quotes around it. Try it like: weburl:weburls[0].
I assume that you have an array elsewhere in your code named weburls, and the above property is supposed to be setting the weburl property equal to the value of the 0-indexed item in weburls.
With the quotes it means after this line a.href = object[i].weburl;, a.href is literally equal to "weburls[0]". You should be able to perform an inspection on the DOM to confirm this.
Update
The code in the for loop seems that it could be replaced with this:
var heading = '<h2>' + object[i].hotelname + '</h2>';
var description = '<p>' + object[i].description + '</p>';
var priceho='<h4>' + object[i].price + '</h4>';
var hotel =
'<img src="' + object[i].purl + '" />' +
'<div>' + heading + description + priceho +
'<a target="_blank" href="' + object[i].weburl + '">Official website</a>' +
'</div>';
document.getElementById("hotels").innerHTML += hotel;

How can I resize infowindow with button onclick in it? + Change content of infowindow

I have tried a lot of different ways to write this, but I really dont understand how I can do it. I am new in javascript, so maybe it will be easy to do for you.
I have infobox when I click on marker on map. I want to have "more" button in that infobox. When someone clicks on the button, the infobox will resize and change content. How can I write it, using javascript and HTML?
resizeWindow = function (stringItem, isResized) {
var eventItem = JSON.parse(stringItem);
processLocation(eventItem, isResized);
};
processLocation = function (eventItem, isResized) {
var i, contentString, myOptions, ib, markerOptions, marker, infoWindowWidth;
console.log("---> event is stoned: " + eventItem.name);
var stringItem = JSON.stringify(eventItem);
if (!isResized) {
infoWindowWidth = "450px";
contentString =
'<div class="eventitem-content">' +
'<div class="eventitem-bodycontent">' +
'<div class="eventitem-title">' + eventItem.name + '</div><img src="/Content/LandfillPhotos/' + eventItem.photo_number + '.png" alt="Landfill" style="width:425px;height:335px"/>' +
'<div class="eventitem-company">' + eventItem.company + '</div><div class="eventitem-address">' + eventItem.company_address + '</div>' +
'<button onclick="FBN.events.resizeWindow('+ stringItem + ', true)">Více</button>' +
'</div>' +
'</div>';
console.log(isResized);
} else {
infoWindowWidth = window.screen.availWidth + "px";
contentString =
'<div class="eventitem-content">' +
'<div class="eventitem-bodycontent">' +
'<div class="eventitem-title">' + eventItem.name + '</div><img src="/Content/LandfillPhotos/' + eventItem.photo_number + '.png" alt="Landfill" style="width:425px;height:335px"/>' +
'<div class="eventitem-company">' + eventItem.company + '</div><div class="eventitem-address">' + eventItem.company_address + '</div>' +
'<button onclick="FBN.events.resizeWindow(' + stringItem + ', false)">Více</button>' +
'</div>' +
'</div>';
}
myOptions = {
content: contentString,
disableAutoPan: false,
maxWidth: 0,
pixelOffset: new google.maps.Size(-140, 4),
zIndex: null,
boxStyle: {
width: infoWindowWidth
},
closeBoxMargin: "6px",
closeBoxURL: "https://www.google.com/intl/en_us/mapfiles/close.gif",
infoBoxClearance: new google.maps.Size(1, 1),
isHidden: false,
pane: "floatPane",
enableEventPropagation: false
};
ib = new InfoBox(myOptions);
infoWindows.push(ib);
markerOptions = {
position: new google.maps.LatLng(eventItem.latitude, eventItem.longitude),
map: map,
title: eventItem.name,
icon: 'https://cdn1.iconfinder.com/data/icons/Map-Markers-Icons-Demo-PNG/32/Map-Marker-Marker-Outside-Azure.png'
}
marker = new google.maps.Marker(markerOptions);
markers.push(marker);
createListener(marker, map, ib);
};
When I do it like this, console writes me: Unexpected token ;
'<button onclick="FBN.events.resizeWindow('+ stringItem + ', true)">Více</button>' +
This line is problem
This is a really involved situation, and there will be more issues soon with variable scoping once you solve this immediate problem. I will show you how to solve your immediate problem which is regarding the Unexpected token ;.
You are in a difficult spot with quotes and JSON. Take your code for example:
'<button onclick="FBN.events.resizeWindow('+ stringItem + ', true)">Více</button>'
Your stringItem is no longer just a variable, but its contents will be inlined above. If it has any unescaped single or double quotes, it will cause an error.
Here is a sample stringItem I recovered:
{"name":"Skládka odpadů S-OO3 se sektorem S-OO1 Ďáblice","county_code":"CZ010", ... ,"longitude":"14.482411","photo_number":"1"}
In other words, you are essentially writing this dynamic HTML. Notice the double quotes:
<button onclick="FBN.events.resizeWindow({"name":"Skládka odpadů S-OO3 se sektorem S-OO1 Ďáblice","county_code":"CZ010", ... ,"longitude":"14.482411","photo_number":"1"}, true)">Více</button>
First, you need to surround this literal string with single quotes. So we need this:
'<button onclick="FBN.events.resizeWindow(\''+ stringItem + '\', true)">Více</button>'
This is enough information for you to solve your problem, but to go a step further, instead of
var stringItem = JSON.stringify(eventItem);
you should encode stringItem more to remove all quotes. I got your code working with this:
var stringItem = utf8_to_b64(JSON.stringify(eventItem));
where I included these useful functions whose names are self-explanatory:
function utf8_to_b64( str ) {
return window.btoa(unescape(encodeURIComponent( str )));
}
function b64_to_utf8( str ) {
return decodeURIComponent(escape(window.atob( str )));
}
When I made the modifications to the site you supplied (using Chrome Dev tools), your "Vice" buttons now render like this
<button onclick="FBN.events.resizeWindow('eyJuYW1lIj ... IjoiMyJ9', true)">Více</button>
which is now valid syntax. Your new problem is where the onclick handler expects to find FBN.events.resizeWindow(). But that's for a different question. :)
Here are some of the changes I experimented with: http://pastebin.com/Uczwct8H

Marker click event always opens to the last pushed infowindow

I have a json object infoCentros which I use to construct the map, like this:
for ( var i = 0; i < infoCentros.length; i++ ) {
var centro = infoCentros[i];
var lat = centro.cordenadas.lat;
var lon = centro.cordenadas.long;
if (lat && lon) {
c++;
latlon = new google.maps.LatLng(lat, lon);
var moptions = {
position: latlon,
map: $project.gmap
}
moptions.icon = theme_uri + '/images/marker.png';
var marker = new google.maps.Marker(moptions);
$project.mapMarkers.push(marker);
google.maps.event.addListener(marker, 'click', function() {
$project.mapInfoWindow.setContent(
'<div class="sescam-info-window">' +
'<h3>' + centro.nombre + '</h3>' +
'<p>' + centro.lugar + '</h3>' +
'<p>Coordinador</p>' +
'<p>' + centro.coordinador.nombre + '</p>' +
'<p>' + centro.coordinador.email + '</p>' +
'<p>Responsable</p>' +
'<p>' + centro.responsable.nombre + '</p>' +
'<p>' + centro.responsable.email + '</p>'
+ '</div>'
);
$project.mapInfoWindow.open($project.gmap, marker);
});
$project.mapBounds.extend(latlon);
}
}
It seems to work fine, but if I have 5 markers, It doesn't matter which one I click, the infowindow always corresponds to the last item (position and content),
Any idea what am I missing? I thought that passing marker to the addListener would Do the trick..
Problem is with third argument of google.maps.event.addListener. That anonymous function contains the variable from the parent scope which when evaluated with marker click will always take the last value assigned. Look for closure for more details. However you may able to get the desired behaviour by using "bind" feature of javascript function prototype in below manner:
//inside for loop
google.maps.event.addListener(marker, 'click', handleMarkerClick.bind(undefined, marker, i));
//other codes if any...
defining handleClick
function handleMarkerClick(marker, index) {
if (typeof infowindow === 'undefined') {
infowindow = new google.maps.InfoWindow({});
}
var data = infoCentros[index]//helpful data
//create content with dynamic data
infowindow.setContent("dynamic content");
infowindow.open(marker.getMap(), marker);//modify as per your requirement
}
Duncan is right, he means you have to attach the listener outside of your for loop. It's not specific to Google Maps, it's how javascript works. Try searching for "javascript closures for loop" or visit this link - Closures in Javascript for a simple explanation.

Categories