How can I add a textarea to a maplibre gl marker? - mapbox

I am trying to add an editable textarea to a marker in MapLibreGL:
el.classList.add("marker");
el.innerHTML = `
<img src="/marker.svg" alt="" />
<textarea>click to edit</textarea>
`;
const marker = new maplibregl.Marker(el)
.setLngLat([longitude, latitude])
.addTo(map);
The marker shows but I cannot type in the textarea...I can't click or inspect it either. I tried .marker { z-index: 100000; } in css but that didn't do anything.

Related

How to add webp images as background image of a div with fallback to Jpeg

I want to add a background image to a div in webp format with fallback to jpg.
If it is img tag, we can call it as:
<picture>
<source srcset="image.webp" type="image/webp">
<source srcset="image.jpg" type="image/jpeg">
<img src="image.jpg">
</picture>
And what can we do in case of <div class="carousel-item active" style="background-image: url('images/image.jpeg')">
Thank you for any help!
Here is a my solution...
You load the image with a hidden picture element and fetch with js the loaded image (with fallback to jpg or png). Finally you set the loaded image with jquery as the background of the parent div.
Maybe there is a better solution in the field.
function makeBgImage( img ){
let srcImage;
if ( typeof img.currentSrc === "undefined" ){
//Old browser
srcImage = img.src;
}else{
//Modern browser
srcImage = img.currentSrc;
}
let ref = $(img).parents('div:first');
ref.css('background', 'url(' + srcImage + ')');
if( ref.hasClass('contain') ){
ref.css('background-size', 'contain');
}else{
ref.css('background-size', 'cover');
}
ref.css('background-position', 'center');
ref.css('background-repeat', 'no-repeat');
}
.hidden{display: none;}
.img-container{
width: 100%;
padding-top: 62.5%; /* 8:5 Aspect Ratio */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="img-container">
<picture class="hidden">
<source srcset="image.webp" type="image/webp">
<img onload="makeBgImage(this)" alt="Image" src="image.png">
</picture>
</div>

How to get marker popup on hover element from list using Leaflet and L.Control.ListMarkers?

Using Leaflet and plugins like ListMarkers, I display a list of visible markers on the map. After hovering over the appropriate <li> element in the List, I want the marker popup to be displayed. The <li> element contains various information about the product, unfortunately after hovering over them, the popup appears and disappears. How to make it that if I hover entire <li> element popup will show and not go crazy of each element separately ?
var list = new L.Control.ListMarkers({ layer: markers, itemIcon: null });
list.addTo(map);
list.on('item-mouseover', function(e) {
e.layer.setIcon(L.icon({
iconUrl: '/marker2.png'
}));
e.layer.openPopup();
}).on('item-mouseout', function(e) {
e.layer.setIcon(L.icon({
iconUrl: '/marker.png'
}))
e.layer.closePopup();
});
listaHTML = list.getContainer();
document.getElementById("lista").appendChild(listaHTML);
Seems to be a CSS problem.
Workaround
li.list-markers-li>a>span,
li.list-markers-li>a>b {
pointer-events: none;
}
var map = new L.Map('map', {
zoom: 10,
minZoom: 10,
center: L.latLng(43.90974, 10.2419)
});
map.addLayer(new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png')); //base layer
var markersLayer = new L.LayerGroup(); //layer contain searched elements
map.addLayer(markersLayer);
////////////populate map from cities-italy.js
for (var i in cities) {
let marker = L.marker(L.latLng(cities[i].loc), {
title: cities[i].name
}).addTo(markersLayer);
marker.bindPopup(cities[i].name)
}
var list = new L.Control.ListMarkers({
layer: markersLayer,
itemIcon: null
});
list.on('item-mouseover', function(e) {
e.layer.openPopup();
}).on('item-mouseout', function(e) {
e.layer.closePopup();
});
map.addControl(list);
#map {
position: absolute;
top: 35px;
left: 0;
width: 100%;
height: 80%
}
li.list-markers-li>a>span,
li.list-markers-li>a>b {
pointer-events: none;
}
<script src="https://labs.easyblog.it/maps/leaflet-list-markers/examples/cities-italy.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.3.1/dist/leaflet.js"></script>
<script src="https://labs.easyblog.it/maps/leaflet-list-markers/src/leaflet-list-markers.js"></script>
<link href="https://labs.easyblog.it/maps/leaflet-list-markers/src/leaflet-list-markers.css" rel="stylesheet" />
<div id="map"></div>

Leaflet external link without popup

I am trying to create a link beetween an external menu (img) / a marker / a div (content) - not using bindpopup.
I managed to create a link to open the bindpopup.
This is my marker :
var markers = [];
var marker1 = L.marker([43.55,7.02],{title:"marker_1", icon: ballicon}).addTo(map).bindPopup('Villes de CANNES');
markers.push(marker1);
This my link :
<div class="item">
<a id="marker_1" href="#">
<table class="cannes" align="center" cellpadding="0" cellspacing="0" height="150" styleborder="0" width="250"><tbody><tr><td valign="top" background="cannes-250x150.jpg" height="150"><div id="numcannes">1</div> </td></tr><tr><td class="titlecannes" height="25">Cannes</td></tr></tbody></table></a>
</div>
But instead of open the bindpopup I would like to zoom on the marker and open the popup content in a div.
I can do it by clicking on the marker :
var marker1 = L.marker([45,1],{title:"marker_1", icon: ballicon, clickable: true,
name: 'Cannes Place', type: 'City'}).on('click', onClick).addTo(map);function onClick(e) { $('#content').html("<p><strong>Name:</strong> "+this.options.name+"</p><p><strong>Type:</strong> "+this.options.type+"</p>")};
... but I do not know how to open the content in div by clicking on my img.
Thank you in advance,
If you don't want your content to be utilizing in Leaflet's Popup functionality, why involve Popup at all? Simple attach the properties you need to the options hash of Leaflet's Marker, and go from there. Then I would assume you could bind to your image(although I would use an actual IMG tag instead of the deprecated background attribute on a TD) with
$("#marker_1").click(function(){
map.setView(marker_1.getLatLng(),10);
//set content of #content here
})

How to implement autocomplete while using locator in arcgis

The below code is to find a location on map, once the location is entered in a textbox.Please note in the below code that I am using 'locator' instead of 'geocoder' as i would like to have custom textbox instead of the textbox provided by the 'esri/dijit/geocoder' and also i would like to get the geocoordinates values using locator.
In the below code, i would like to add 'autocomplete' feature in textbox that has the same functionality as of 'autocomplete' feature in 'geocoder'.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--The viewport meta tag is used to improve the presentation and behavior of the samples
on iOS devices-->
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>Find Address</title>
<link rel="stylesheet" href="http://js.arcgis.com/3.12/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="http://js.arcgis.com/3.12/esri/css/esri.css">
<style>
html, body {
height: 100%; width: 100%;
margin: 0; padding: 0;
}
#map{
padding:0;
border:solid 1px #343642;
margin:5px 5px 5px 0px;
}
#leftPane{
width:20%;
border-top: solid 1px #343642;
border-left: solid 1px #343642;
border-bottom: solid 1px #343642;
margin:5px 0px 5px 5px;
color: #343642;
font:100% Georgia,"Times New Roman",Times,serif;
/*letter-spacing: 0.05em;*/
}
</style>
<script src="http://js.arcgis.com/3.12/"></script>
<script>
var map, locator;
require([
"esri/map", "esri/tasks/locator", "esri/graphic",
"esri/InfoTemplate", "esri/symbols/SimpleMarkerSymbol",
"esri/symbols/Font", "esri/symbols/TextSymbol",
"dojo/_base/array", "esri/Color",
"dojo/number", "dojo/parser", "dojo/dom", "dijit/registry",
"dijit/form/Button", "dijit/form/Textarea",
"dijit/layout/BorderContainer", "dijit/layout/ContentPane", "dojo/domReady!"
], function(
Map, Locator, Graphic,
InfoTemplate, SimpleMarkerSymbol,
Font, TextSymbol,
arrayUtils, Color,
number, parser, dom, registry
) {
parser.parse();
map = new Map("map", {
basemap: "streets",
center: [-93.5, 41.431],
zoom: 5
});
locator = new Locator("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer");
locator.on("address-to-locations-complete", showResults);
// listen for button click then geocode
registry.byId("locate").on("click", locate);
map.infoWindow.resize(200,125);
function locate() {
map.graphics.clear();
var address = {
"SingleLine": dom.byId("address").value
};
locator.outSpatialReference = map.spatialReference;
var options = {
address: address,
outFields: ["Loc_name"]
};
locator.addressToLocations(options);
}
function showResults(evt) {
var symbol = new SimpleMarkerSymbol();
var infoTemplate = new InfoTemplate(
"Location",
"Address: ${address}<br />Score: ${score}<br />Source locator: ${locatorName}"
);
symbol.setStyle(SimpleMarkerSymbol.STYLE_SQUARE);
symbol.setColor(new Color([153,0,51,0.75]));
var geom;
arrayUtils.every(evt.addresses, function(candidate) {
console.log(candidate.score);
if (candidate.score > 80) {
console.log(candidate.location);
var attributes = {
address: candidate.address,
score: candidate.score,
locatorName: candidate.attributes.Loc_name
};
geom = candidate.location;
var graphic = new Graphic(geom, symbol, attributes, infoTemplate);
//add a graphic to the map at the geocoded location
map.graphics.add(graphic);
//add a text symbol to the map listing the location of the matched address.
var displayText = candidate.address;
var font = new Font(
"16pt",
Font.STYLE_NORMAL,
Font.VARIANT_NORMAL,
Font.WEIGHT_BOLD,
"Helvetica"
);
var textSymbol = new TextSymbol(
displayText,
font,
new Color("#666633")
);
textSymbol.setOffset(0,8);
map.graphics.add(new Graphic(geom, textSymbol));
return false; //break out of loop after one candidate with score greater than 80 is found.
}
});
if ( geom !== undefined ) {
map.centerAndZoom(geom, 12);
}
}
});
</script>
</head>
<body class="claro">
<div id="mainWindow" data-dojo-type="dijit/layout/BorderContainer"
data-dojo-props="design:'sidebar', gutters:false"
style="width:100%; height:100%;">
<div id="leftPane"
data-dojo-type="dijit/layout/ContentPane"
data-dojo-props="region:'left'">
Enter an address then click the locate button to use a sample address locator to return the location for
street addresses in the United States.
<br>
<textarea id="address">380 New York St, Redlands</textArea>
<br>
<button id="locate" data-dojo-type="dijit/form/Button">Locate</button>
</div>
<div id="map"
data-dojo-type="dijit/layout/ContentPane"
data-dojo-props="region:'center'">
</div>
</div>
</body>
</html>
How to add 'autocomplete' feature in this code?
What do you mean by using your own custom textbox provided by esri/dijit/geocoder? The Geocoder dijit comes with default ESRI css to style the dijit, but nothing prevents you from overriding this with your own styles.
For instance you could add a class in your body tag to override the claro styles:
<body class="claro custom">
This way esri dijits will use claro by default, but if you define the same css selectors as the esri dijit and append them with your custom class, the dijit will use that instead. Here's a short example where we override 2 properties of the results element in the Geocoder:
/* Custom styles for the Geocoder dijit */
.custom #myGeocoder .esriGeocoderResults {
overflow: visible;
z-index: 1000 !important;
}
The geocode dijit supports autocomplete using either the default locator or custom ones. Since you are referencing the default locator service you can just use the dijit and pass autoComplete in the options
<script>
var map, geocoder;
require([
"esri/map", "esri/dijit/Geocoder", "dojo/domReady!"
], function(Map, Geocoder) {
map = new Map("map",{
basemap: "gray",
center: [-120.435, 46.159], // lon, lat
zoom: 7
});
geocoder = new Geocoder({
map: map,
autoComplete : true
}, "search");
geocoder.startup();
});
</script>

bingmaps- when click on pushpin in one map it is showing the pushpin description in the last map

i have to display 2 bingmaps on same page with pushpins. But when i clicks on the pushpin in first map, it is showing the pushpin popup box on next map. i want to show the pushpins popups which are associated with the corresponding map.
Please check my source code.
<html>
<head>
<script charset="UTF-8" type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
var pinInfoBox; //the pop up info box
var infoboxLayer = new Microsoft.Maps.EntityCollection();
var pinLayer = new Microsoft.Maps.EntityCollection();
var apiKey = "YOUR_BING_MAPS_KEY";
function GetMap() {
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 < 10; i++){
//add pushpins
var latLon = new Microsoft.Maps.Location(Math.random()*180-90, Math.random()*360-180);
var pin = new Microsoft.Maps.Pushpin(latLon);
pin.Title = name;//usually title of the infobox
pin.Description = "first map, "+ 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);
}
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 });
}
$(document).ready(function() {
GetMap();
getnewmap();
});
function getnewmap() {
maps2 = new Microsoft.Maps.Map(document.getElementById("maps2"), {credentials: apiKey});
pinInfobox = '';
// 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 < 10; i++){
//add pushpins
var latLon = '';
var mypin = '';
var latLon = new Microsoft.Maps.Location(Math.random()*180-90, Math.random()*360-180);
var mypin = new Microsoft.Maps.Pushpin(latLon);
mypin.Title = name;//usually title of the infobox
mypin.Description = "second map, "+ i; //information you want to display in the infobox
pinLayer.push(mypin); //add pushpin to pinLayer
Microsoft.Maps.Events.addHandler(mypin, 'click', displayInfobox);
}
maps2.entities.push(pinLayer);
maps2.entities.push(infoboxLayer);
}
</script>
<style>
#map { position: relative; margin:20px; width: 500px; height: 400px; border:#555555 2px solid;}
#maps2 { position: relative; margin:20px; width: 500px; height: 400px; border:#555555 2px solid;}
</style>
</head>
<body onload="">
<div width="100%" height="100%" style="border:1px solid red;">
<div id="map" style="border:1px solid orange;"> one
</div><br/>
<div id="maps2" style="border:1px solid green;">hello
</div>
</div>
</body>
The infobox layer only exists in your first map. You have to create a second one for the second map, otherwise it will always show up on the first map.