leaflet mouse hover popup through array list - javascript

i want to display a popup on mouse hover,i want to show names on popup,which will be select from the array list,i placed multiple markers on map at different latlon,now i want to display a popup(which contain name) for particular latlon,this is my code,where i want to show my district name on mouse hover,now i am getting the popup text on mouse hover but i don't know how can i call my array list in popupcontent,any one can suggest what i should do?
var planes = [
["Jodhpur",26.28, 73.02],
["Bikaner",28.0229,73.3119],
["Churu",28.3254,74.4057],
["Ganga Nagar",29.9038,73.8772],
["Hanumangarh",29.1547,74.4995],
["Jaisalmer", 26.9157,70.9083],
["Jalore",25.1257,72.1416],
["Jhunjhunu",28.1289,75.3995],
["Nagaur",27.1854,74.0300],
["Pali",25.7711, 73.3234],
["Sikar",27.6094,75.1399],
["Sirohi",24.7467,72.8043],
["Barmer",25.7532,71.4181],
];
for (var i = 0; i < planes.length; i++) {
marker = new L.marker([planes[i][1],planes[i][2]],{icon: myIcon}).addTo(map).bindPopup('<div id="chart" class="chart"></div>');
marker.on('click', onMarkerClick, this);
/*var currentMarker = planes[i][0];
currentMarker.on('mouseover', currentMarker.openPopup.bind(currentMarker));
*/
marker.on('mouseover', function(e) {
//open popup;
var popup = L.popup()
.setLatLng(e.latlng)
.setContent('Popup')
.openOn(map);
});
}

Filter your array to return the name based on lat and/or lng
marker.on('mouseover', function(e) {
var name = "";
$.each(planes,function(i,v){
if (v.indexOf(e.latlng[0]) > 0) {//test if the lat is in the array
name = v[0];//get the name
}
})
var popup = L.popup()
.setLatLng(e.latlng)
.setContent('District: '+name)
.openOn(map);
})
Note: i am assuming e.latlng is a array of [lat,lng]

You have to change the marker1 name as per your marker name.
var marker1 = L.marker(23.0225, 72.5714).addTo(mymap)
.bindPopup("Demo Content of Popup");
let isClicked = false
marker1.on({
mouseover: function() {
if(!isClicked) {
this.openPopup()
}
},
mouseout: function() {
if(!isClicked) {
this.closePopup()
}
},
click: function() {
isClicked = true
this.openPopup()
}
})
mymap.on ({
click: function() {
isClicked = false
},
popupclose: function () {
isClicked = false
}
})

Related

Extending L.control.zoom with custom button

I'm looking for a way to add an extra button to L.control.zoom. Leaflet is being loaded from a CDN and I'm using vanilla Javascript (no preprocessors or anything).
I was hoping there'd be something like L.control.zoom.extend({}), but unfortunately that doesn't exist. Trying L.Control.extend({...L.control.zoom}) didn't work either.
For context, doing it the long way by copy-pasting the original code and adding the code for my custom button at line 42 would look like this:
let zoomControls = L.Control.extend({
// #section
// #aka Control.Zoom options
options: {
position: 'topleft',
// #option zoomInText: String = '+'
// The text set on the 'zoom in' button.
zoomInText: '+',
// #option zoomInTitle: String = 'Zoom in'
// The title set on the 'zoom in' button.
zoomInTitle: 'Zoom in',
// #option zoomOutText: String = '−'
// The text set on the 'zoom out' button.
zoomOutText: '−',
// #option zoomOutTitle: String = 'Zoom out'
// The title set on the 'zoom out' button.
zoomOutTitle: 'Zoom out'
},
onAdd: function (map) {
var zoomName = 'leaflet-control-zoom',
container = L.DomUtil.create('div', zoomName + ' leaflet-bar'),
options = this.options;
let locationLink = L.DomUtil.create('a', 'leaflet-bar-part leaflet-bar-part-single', container);
L.DomEvent.disableClickPropagation(locationLink);
locationLink.title = 'My location';
let locationIcon = L.DomUtil.create('span', 'fa-lg fas fa-map-marker-alt', locationLink);
L.DomEvent.on(locationLink, 'click', () => {
alert('BUTTON CLICKED');
});
this._zoomInButton = this._createButton(options.zoomInText, options.zoomInTitle,
zoomName + '-in', container, this._zoomIn);
this._zoomOutButton = this._createButton(options.zoomOutText, options.zoomOutTitle,
zoomName + '-out', container, this._zoomOut);
this._updateDisabled();
map.on('zoomend zoomlevelschange', this._updateDisabled, this);
return container;
},
onRemove: function (map) {
map.off('zoomend zoomlevelschange', this._updateDisabled, this);
},
disable: function () {
this._disabled = true;
this._updateDisabled();
return this;
},
enable: function () {
this._disabled = false;
this._updateDisabled();
return this;
},
_zoomIn: function (e) {
if (!this._disabled && this._map._zoom < this._map.getMaxZoom()) {
this._map.zoomIn(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));
}
},
_zoomOut: function (e) {
if (!this._disabled && this._map._zoom > this._map.getMinZoom()) {
this._map.zoomOut(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));
}
},
_createButton: function (html, title, className, container, fn) {
var link = L.DomUtil.create('a', className, container);
link.innerHTML = html;
link.href = '#';
link.title = title;
/*
* Will force screen readers like VoiceOver to read this as "Zoom in - button"
*/
link.setAttribute('role', 'button');
link.setAttribute('aria-label', title);
L.DomEvent.disableClickPropagation(link);
L.DomEvent.on(link, 'click', L.DomEvent.stop);
L.DomEvent.on(link, 'click', fn, this);
L.DomEvent.on(link, 'click', this._refocusOnMap, this);
return link;
},
_updateDisabled: function () {
var map = this._map,
className = 'leaflet-disabled';
L.DomUtil.removeClass(this._zoomInButton, className);
L.DomUtil.removeClass(this._zoomOutButton, className);
if (this._disabled || map._zoom === map.getMinZoom()) {
L.DomUtil.addClass(this._zoomOutButton, className);
}
if (this._disabled || map._zoom === map.getMaxZoom()) {
L.DomUtil.addClass(this._zoomInButton, className);
}
}
});
While not being explicit in the Leaflet class customization tutorial, there is a subtle distinction between factories, which are lowerCased and that you cannot extend, and Classes, which are PascalCased and on which you can use Leaflet extend mechanism:
var MyNewZoomControl = L.Control.Zoom.extend({
onAdd: function (map) {
// your new method content
}
}
That being said, if your new button does not really share functionality with the zoom buttons or is not "merged" with them, you could simply make a separate Control and insert it in the same corner position. There is also Leaflet EasyButton plugin which can help in this regard.

Manually close layer control window (javascript)

I recently started programing in javascript.
I have added a layer control window to my map. It's open by default (This works.). Now I want to add a close button to the layer control window. Is that possible?
This my code:
$ (document).ready(function init(){
// initiate leaflet map
var map = new L.Map('cartodb-map', {
center: [51,9],
zoom: 4,
minZoom:3,
maxZoom: 16,
});
//load basemap
var OSM= new L.tileLayer('http://a{s}.acetate.geoiq.com/tiles/acetate-hillshading/{z}/{x}/{y}.png',
{attribution: '© OpenStreetMap'}).addTo(map);
//load data from CartoDB
var layerUrl= 'http://intermodalmap.cartodb.com/api/v2/viz/0931f4e4-76f8-11e4-0e9d821ea90d/viz.json';
//load satellit map
var Esri_WorldImagery = new L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community' });
var baseLayers = { "Standardkarte": OSM,
"Satellitenkarte": Esri_WorldImagery };
//create map
cartodb.createLayer(map, layerUrl,
{https: true,
legends: true,
cartodb_logo:false,
layerIndex: 1
})
.addTo(map)
.on('done', function() {
});
L.Control.Custom = L.Control.Layers.extend({
onAdd: function () {
this._initLayout();
this._addButton();
this._update();
return this._container;
},
_addButton: function () {
var elements = this._container.getElementsByClassName('leaflet-control-layers-list');
var button = L.DomUtil.create('button', 'my-button-class', elements[0]);
button.innerText = 'Close control';
L.DomEvent.on(button, 'click', function(e){
L.DomEvent.stop(e);
this._collapse();
}, this);
}
});
var control = new L.Control.Custom(baseLayers, {"Alle Terminals":layerUrl}, {collapsed:false}).addTo(map);
// create a fullscreen button and add it to the map
L.control.fullscreen({
position: 'topleft', // change the position of the button can be topleft, topright, bottomright or bottomleft, defaut topleft
title: 'Open fullscreen', // change the title of the button, default Full Screen
titleCancel: 'Exit fullscreen mode', // change the title of the button when fullscreen is on, default Exit Full Screen
content: null, // change the content of the button, can be HTML, default null
forceSeparateButton: true
}).addTo(map);
// events are fired when entering or exiting fullscreen.
map.on('enterFullscreen', function(){
console.log('entered fullscreen');
});
map.on('exitFullscreen', function(){
console.log('exited fullscreen');
});
//add scale
L.control.scale({metric:"m", position:"bottomright", imperial:false}).addTo(map);
//end of function init
}
)
You can extend L.Control.Layers and add elements to it's container, attach eventhandlers, whatever you want. Something like this:
L.Control.Custom = L.Control.Layers.extend({
onAdd: function () {
this._initLayout();
this._addButton();
this._update();
return this._container;
},
_addButton: function () {
var elements = this._container.getElementsByClassName('leaflet-control-layers-list');
var button = L.DomUtil.create('button', 'my-button-class', elements[0]);
button.innerText = 'Close control';
L.DomEvent.on(button, 'click', function(e){
L.DomEvent.stop(e);
this._collapse();
}, this);
}
});
Example: http://plnkr.co/edit/Je7c0m?p=preview
cartodb.createLayer(map, layerUrl, {
layerIndex: 1
}).addTo(map)
.on('done', function(layer) {
L.control.layers(baseLayers,
{data:layer},
{collapsed:false}
).addTo(map);
document.getElementById('closeBtn').addEventListener('click', function() {
layer.setAttribute('style', 'display: none;').hide();
});
});
// and more shortly if jquery exists
$('#closeBtn').click(function() {
layer.hide();
});

Automatically fill up the Google Map search bar (Address Picker)

I want to present my users with a text box wherein they can type in their address. As they type their address, there's a new window will open (Google map) and automatically fill up the search box in Google map. I want to provide the users with suggestions/predictions of what address they are trying to type. I'm also concerned about the relevance of this address (e.g. that the address is not an address halfway across the world).
How to automatically fill the search box in Google map from the inputted address text box from another website?
E.g In my website, there's a text box and I input an address in that text box and when I click enter in that text box there's a new window appear and display the Google Map with search bar (in that search bar, the address is already there)
Is this possible in javascript and jquery? Please help me. I'm newbie in those PL. Thank you
Here's the code:
(function($, window, document, undefined){
var defaults = {
bounds: true,
country: null,
map: false,
details: false,
detailsAttribute: "name",
autoselect: true,
location: false,
mapOptions: {
zoom: 14,
scrollwheel: false,
mapTypeId: "roadmap"
},
markerOptions: {
draggable: false
},
maxZoom: 16,
types: ['geocode'],
blur: false
};
var componentTypes = ("street_address route intersection political " +
"country administrative_area_level_1 administrative_area_level_2 " +
"administrative_area_level_3 colloquial_area locality sublocality " +
"neighborhood premise subpremise postal_code natural_feature airport " +
"park point_of_interest post_box street_number floor room " +
"lat lng viewport location " +
"formatted_address location_type bounds").split(" ");
var placesDetails = ("id url website vicinity reference name rating " +
"international_phone_number icon formatted_phone_number").split(" ");
// The actual plugin constructor.
function GeoComplete(input, options) {
this.options = $.extend(true, {}, defaults, options);
this.input = input;
this.$input = $(input);
this._defaults = defaults;
this._name = 'geocomplete';
this.init();
}
// Initialize all parts of the plugin.
$.extend(GeoComplete.prototype, {
init: function(){
this.initMap();
this.initMarker();
this.initGeocoder();
this.initDetails();
this.initLocation();
},
// Initialize the map but only if the option `map` was set.
// This will create a `map` within the given container
// using the provided `mapOptions` or link to the existing map instance.
initMap: function(){
if (!this.options.map){ return; }
if (typeof this.options.map.setCenter == "function"){
this.map = this.options.map;
return;
}
this.map = new google.maps.Map(
$(this.options.map)[0],
this.options.mapOptions
);
// add click event listener on the map
google.maps.event.addListener(
this.map,
'click',
$.proxy(this.mapClicked, this)
);
google.maps.event.addListener(
this.map,
'zoom_changed',
$.proxy(this.mapZoomed, this)
);
},
// Add a marker with the provided `markerOptions` but only
// if the option was set. Additionally it listens for the `dragend` event
// to notify the plugin about changes.
initMarker: function(){
if (!this.map){ return; }
var options = $.extend(this.options.markerOptions, { map: this.map });
if (options.disabled){ return; }
this.marker = new google.maps.Marker(options);
google.maps.event.addListener(
this.marker,
'dragend',
$.proxy(this.markerDragged, this)
);
},
// Associate the input with the autocompleter and create a geocoder
// to fall back when the autocompleter does not return a value.
initGeocoder: function(){
var options = {
types: this.options.types,
bounds: this.options.bounds === true ? null : this.options.bounds,
componentRestrictions: this.options.componentRestrictions
};
if (this.options.country){
options.componentRestrictions = {country: this.options.country};
}
this.autocomplete = new google.maps.places.Autocomplete(
this.input, options
);
this.geocoder = new google.maps.Geocoder();
// Bind autocomplete to map bounds but only if there is a map
// and `options.bindToMap` is set to true.
if (this.map && this.options.bounds === true){
this.autocomplete.bindTo('bounds', this.map);
}
// Watch `place_changed` events on the autocomplete input field.
google.maps.event.addListener(
this.autocomplete,
'place_changed',
$.proxy(this.placeChanged, this)
);
// Prevent parent form from being submitted if user hit enter.
this.$input.keypress(function(event){
if (event.keyCode === 13){ return false; }
});
// Listen for "geocode" events and trigger find action.
this.$input.bind("geocode", $.proxy(function(){
this.find();
}, this));
// Trigger find action when input element is blured out.
// (Usefull for typing partial location and tabing to the next field
// or clicking somewhere else.)
if (this.options.blur === true){
this.$input.blur($.proxy(function(){
this.find();
}, this));
}
},
// Prepare a given DOM structure to be populated when we got some data.
// This will cycle through the list of component types and map the
// corresponding elements.
initDetails: function(){
if (!this.options.details){ return; }
var $details = $(this.options.details),
attribute = this.options.detailsAttribute,
details = {};
function setDetail(value){
details[value] = $details.find("[" + attribute + "=" + value + "]");
}
$.each(componentTypes, function(index, key){
setDetail(key);
setDetail(key + "_short");
});
$.each(placesDetails, function(index, key){
setDetail(key);
});
this.$details = $details;
this.details = details;
},
// Set the initial location of the plugin if the `location` options was set.
// This method will care about converting the value into the right format.
initLocation: function() {
var location = this.options.location, latLng;
if (!location) { return; }
if (typeof location == 'string') {
this.find(location);
return;
}
if (location instanceof Array) {
latLng = new google.maps.LatLng(location[0], location[1]);
}
if (location instanceof google.maps.LatLng){
latLng = location;
}
if (latLng){
if (this.map){ this.map.setCenter(latLng); }
if (this.marker){ this.marker.setPosition(latLng); }
}
},
// Look up a given address. If no `address` was specified it uses
// the current value of the input.
find: function(address){
this.geocode({
address: address || this.$input.val()
});
},
// Requests details about a given location.
// Additionally it will bias the requests to the provided bounds.
geocode: function(request){
if (this.options.bounds && !request.bounds){
if (this.options.bounds === true){
request.bounds = this.map && this.map.getBounds();
} else {
request.bounds = this.options.bounds;
}
}
if (this.options.country){
request.region = this.options.country;
}
this.geocoder.geocode(request, $.proxy(this.handleGeocode, this));
},
// Get the selected result. If no result is selected on the list, then get
// the first result from the list.
selectFirstResult: function() {
//$(".pac-container").hide();
var selected = '';
// Check if any result is selected.
if ($(".pac-item-selected")['0']) {
selected = '-selected';
}
// Get the first suggestion's text.
var $span1 = $(".pac-container .pac-item" + selected + ":first span:nth-child(2)").text();
var $span2 = $(".pac-container .pac-item" + selected + ":first span:nth-child(3)").text();
// Get the inputted address from LAP
var
// Adds the additional information, if available.
var firstResult = $span1;
if ($span2) {
firstResult += " - " + $span2;
}
this.$input.val(firstResult);
return firstResult;
},
// Handles the geocode response. If more than one results was found
// it triggers the "geocode:multiple" events. If there was an error
// the "geocode:error" event is fired.
handleGeocode: function(results, status){
if (status === google.maps.GeocoderStatus.OK) {
var result = results[0];
this.$input.val(result.formatted_address);
this.update(result);
if (results.length > 1){
this.trigger("geocode:multiple", results);
}
} else {
this.trigger("geocode:error", status);
}
},
// Triggers a given `event` with optional `arguments` on the input.
trigger: function(event, argument){
this.$input.trigger(event, [argument]);
},
// Set the map to a new center by passing a `geometry`.
// If the geometry has a viewport, the map zooms out to fit the bounds.
// Additionally it updates the marker position.
center: function(geometry){
if (geometry.viewport){
this.map.fitBounds(geometry.viewport);
if (this.map.getZoom() > this.options.maxZoom){
this.map.setZoom(this.options.maxZoom);
}
} else {
this.map.setZoom(this.options.maxZoom);
this.map.setCenter(geometry.location);
}
if (this.marker){
this.marker.setPosition(geometry.location);
this.marker.setAnimation(this.options.markerOptions.animation);
}
},
// Update the elements based on a single places or geoocoding response
// and trigger the "geocode:result" event on the input.
update: function(result){
if (this.map){
this.center(result.geometry);
}
if (this.$details){
this.fillDetails(result);
}
this.trigger("geocode:result", result);
},
// Populate the provided elements with new `result` data.
// This will lookup all elements that has an attribute with the given
// component type.
fillDetails: function(result){
var data = {},
geometry = result.geometry,
viewport = geometry.viewport,
bounds = geometry.bounds;
// Create a simplified version of the address components.
$.each(result.address_components, function(index, object){
var name = object.types[0];
data[name] = object.long_name;
data[name + "_short"] = object.short_name;
});
// Add properties of the places details.
$.each(placesDetails, function(index, key){
data[key] = result[key];
});
// Add infos about the address and geometry.
$.extend(data, {
formatted_address: result.formatted_address,
location_type: geometry.location_type || "PLACES",
viewport: viewport,
bounds: bounds,
location: geometry.location,
lat: geometry.location.lat(),
lng: geometry.location.lng()
});
// Set the values for all details.
$.each(this.details, $.proxy(function(key, $detail){
var value = data[key];
this.setDetail($detail, value);
}, this));
this.data = data;
},
// Assign a given `value` to a single `$element`.
// If the element is an input, the value is set, otherwise it updates
// the text content.
setDetail: function($element, value){
if (value === undefined){
value = "";
} else if (typeof value.toUrlValue == "function"){
value = value.toUrlValue();
}
if ($element.is(":input")){
$element.val(value);
} else {
$element.text(value);
}
},
// Fire the "geocode:dragged" event and pass the new position.
markerDragged: function(event){
this.trigger("geocode:dragged", event.latLng);
},
mapClicked: function(event) {
this.trigger("geocode:click", event.latLng);
},
mapZoomed: function(event) {
this.trigger("geocode:zoom", this.map.getZoom());
},
// Restore the old position of the marker to the last now location.
resetMarker: function(){
this.marker.setPosition(this.data.location);
this.setDetail(this.details.lat, this.data.location.lat());
this.setDetail(this.details.lng, this.data.location.lng());
},
// Update the plugin after the user has selected an autocomplete entry.
// If the place has no geometry it passes it to the geocoder.
placeChanged: function(){
var place = this.autocomplete.getPlace();
if (!place || !place.geometry){
if (this.options.autoselect) {
// Automatically selects the highlighted item or the first item from the
// suggestions list.
var autoSelection = this.selectFirstResult();
this.find(autoSelection);
}
} else {
// Use the input text if it already gives geometry.
this.update(place);
}
}
});
// A plugin wrapper around the constructor.
// Pass `options` with all settings that are different from the default.
// The attribute is used to prevent multiple instantiations of the plugin.
$.fn.geocomplete = function(options) {
var attribute = 'plugin_geocomplete';
// If you call `.geocomplete()` with a string as the first parameter
// it returns the corresponding property or calls the method with the
// following arguments.
if (typeof options == "string"){
var instance = $(this).data(attribute) || $(this).geocomplete().data(attribute),
prop = instance[options];
if (typeof prop == "function"){
prop.apply(instance, Array.prototype.slice.call(arguments, 1));
return $(this);
} else {
if (arguments.length == 2){
prop = arguments[1];
}
return prop;
}
} else {
return this.each(function() {
// Prevent against multiple instantiations.
var instance = $.data(this, attribute);
if (!instance) {
instance = new GeoComplete( this, options );
$.data(this, attribute, instance);
}
});
}
};
})( jQuery, window, document );
AFIK, the search bar which is used in Google maps search api is a simple textbox (input type="text") and its id is pac-input
$('#pac-input').val($('your address element').val()); //copy the value
$('#pac-input').focus(); //focus might trigger automatically
JSfiddle
Read document for geocoder = new google.maps.Geocoder();
and try this:
var input_address = $('your address element').val();
geocoder.geocode({address: input_address}, reverseGeocodeResult);
function reverseGeocodeResult(results, status) {
currentReverseGeocodeResponse = results;
if (status == 'OK') {
if (results.length == 0) {
document.getElementById('cong_viec_dia_chi').innerHTML = 'None';
} else {
document.getElementById('cong_viec_dia_chi').innerHTML = results[0].formatted_address;
}
} else {
document.getElementById('cong_viec_dia_chi').innerHTML = 'can't get address';
}
}
Update: demo here
http://jsfiddle.net/HoangHieu/x8dSP/3626/
http://jsfiddle.net/HoangHieu/x8dSP/3631/

leaflet.draw trash button delete all polygons and save

Using javascript, how can I alter the leaflet.draw "Trash" button to delete all polygons that have been drawn and automatically save. Below is the code I've implemented but it is a complete hack. It removes the active polygon, but after I delete an object once I begin to get errors in the console when I click the "Trash" icon like NotFoundError: Node was not found and TypeError: this._deletedLayers is null
map.on('draw:editstart', function (e) {
if(e.handler == 'remove' && typeof drawnItem != 'undefined' && drawnItem !== null){
if(window.console) window.console.log('Drawing deleted...');
if(typeof drawnItem != 'undefined' && drawnItem !== null){
drawnItems.removeLayer(drawnItem);
}
$('.leaflet-draw.leaflet-control .leaflet-draw-actions').hide();
$('.leaflet-popup-pane .leaflet-draw-tooltip').remove();
}
});
Solved my own problem with a custom control (thanks to stackexchange - https://gis.stackexchange.com/questions/60576/custom-leaflet-controls):
UPDATED! added #SpiderWan suggestions (thanks!) so no need for custom CSS. Also, the event was previously attached to the entire control bar. Instead attached to just the controlUI button itself.
Javascript:
L.Control.RemoveAll = L.Control.extend({
options: {
position: 'topleft',
},
onAdd: function (map) {
var controlDiv = L.DomUtil.create('div', 'leaflet-control leaflet-bar');
var controlUI = L.DomUtil.create('a', 'leaflet-draw-edit-remove', controlDiv);
controlUI.title = 'Remove all drawn items';
controlUI.setAttribute('href', '#');
L.DomEvent
.addListener(controlUI, 'click', L.DomEvent.stopPropagation)
.addListener(controlUI, 'click', L.DomEvent.preventDefault)
.addListener(controlUI, 'click', function () {
drawnItems.clearLayers();
if(window.console) window.console.log('Drawings deleted...');
});
return controlDiv;
}
});
removeAllControl = new L.Control.RemoveAll();
map.addControl(removeAllControl);
Like jduhls's answer but using Leaflet.draw CSS classes :
L.Control.RemoveAll = L.Control.extend(
{
options:
{
position: 'topleft',
},
onAdd: function (map) {
var controlDiv = L.DomUtil.create('div', 'leaflet-draw-toolbar leaflet-bar');
L.DomEvent
.addListener(controlDiv, 'click', L.DomEvent.stopPropagation)
.addListener(controlDiv, 'click', L.DomEvent.preventDefault)
.addListener(controlDiv, 'click', function () {
drawnItems.clearLayers();
});
var controlUI = L.DomUtil.create('a', 'leaflet-draw-edit-remove', controlDiv);
controlUI.title = 'Remove All Polygons';
controlUI.href = '#';
return controlDiv;
}
});
var removeAllControl = new L.Control.RemoveAll();
map.addControl(removeAllControl);
You can also overwrite the delete tool's enable method to simply delete all layers instead of opening the delete menu:
L.EditToolbar.Delete.include({
enable: function () {
this.options.featureGroup.clearLayers()
}
})

Google Maps API v3 : Click events not triggered in firefox for custom marker

have created a map that I'm trying to have function similar to 'My Maps'. I have two dropdownlists on the right side, based on the selection in those ddl's, you can add a custom marker / icon. You select a marker type, then click the '+' button in the top right corner of the map, and then click where you want the marker added. My issue is, this works fine in IE, Safari, and Chrome, but not in firefox. The click event doesn't seem to fire.
Here is the location of the map : https://ait.saultcollege.ca/Michael.Armstrong/Index.html
The button to add the marker in the top right has an onclick event pointing to my 'placeMarker()' function. Here is the code for placeMarker(), createMarker() ...
function placeMarker() {
select("placeMarker");
var infowindow = new google.maps.InfoWindow({});
var catID = document.getElementById('category');
var typeID = document.getElementById('ddlType');
var category = catID.options[catID.selectedIndex].value;
var markerType = typeID.options[typeID.selectedIndex].value;
if (!markerType) {
alert("You must select an icon type.");
}
else {
var moveListener = google.maps.event.addListener(customMap, 'mousemove', function(event) {
if (mapMarker) {
mapMarker.setPosition(event.latLng);
} else {
mapMarker = createMarker(event.latLng, "test", markerType, "test");
}
});
var clickListener = google.maps.event.addListener(customMap, 'click', function(event) {
if (mapMarker) {
select("hand_b");
google.maps.event.clearListeners(customMap, 'mousemove');
google.maps.event.removeListener(listener);
mapMarker = createMarker(event.latLng, "test2", markerType, "test");
var htmlInfo = "" +
"Category:" + category + "" +
"Item:" + markerType + "" +
"Notes:" +
"Location:" + mapMarker.getPosition().toString() + "" +
"" +
"";
//infowindow.setContent(htmlInfo);
//infowindow.open(customMap, mapMarker);
}
});
}
}
function createMarker(latlng, title, icon, html) {
var mapMarker = new google.maps.Marker({
position: latlng,
map: customMap,
title: title,
icon: 'Images/' + icon + '.png'
});
return mapMarker;
}
function select(buttonId) {
document.getElementById("hand_b").className = "unselected";
document.getElementById("placeMarker").className = "unselected";
document.getElementById(buttonId).className = "selected";
}
Any help or suggestions would be awesome. Could this perhaps be a bug in ff?
I did something very similar for an open-source disaster software package. In this case, lets assume I selected "Fire" in my dropdown menu and this triggers addFire(). The listener on the markers will delete the point on a click or allow you to drag it. The map can only have one listener at a time, but each marker can still have its own listener at the same time.
Here is the code that worked on Chrome, Firefox and IE8:
//This function sets up the map for adding a fire icon
function addFire() {
//Kill old listener
if(listening)
google.maps.event.removeListener(listenerhandle);
//Start new listener
listenerhandle = google.maps.event.addListener(disasterMap, 'click', addFirePoint);
listening = true;
}//end addFire
//This function adds new fire points to the map and controls dragging and clicking
function addFirePoint(event) {
//Create the marker
var fireMarker = new google.maps.Marker({
icon: "./mapimgs/fire.png", position: event.latLng, map: disasterMap, draggable: true });
newFireMarkers.push(fireMarker);
fireMarker.setTitle("Fire");
//Listen for clicks on the new marker
google.maps.event.addListener(fireMarker, 'click', function() {
fireMarker.setMap(null);
//remove the marker from the array
for(i=0;i<newFireMarkers.length;i++) {
if(fireMarker.getPosition() == newFireMarkers[i].getPosition()) {
newFireMarkers.splice(i,1);
break;
}
}
}
); //end click listener
}//end addFirePoint

Categories