admin管理员组文章数量:1406945
I use Leaflet.Control.Search for searching markers by GeoJSON features and it works OK. Now I have to type first letters to find marker, but I want to choose them from drop down list with all markers in it. Is it way to do it?
I use Leaflet.Control.Search for searching markers by GeoJSON features and it works OK. Now I have to type first letters to find marker, but I want to choose them from drop down list with all markers in it. Is it way to do it?
Share Improve this question asked Mar 3, 2016 at 12:53 AntonAnton 4732 gold badges10 silver badges20 bronze badges 3- Is that a feature of this control? If not, you'll have to modify the source to add it yourself. – Squiggle Commented Mar 3, 2016 at 13:11
- I'm searching markers by their names, included in my GeoJSON like string values. Now I have to type letters «c», «i» etc. to find the place with name «City» for example. After I enter some characters, the plugin gives me short list with names corresponding my query. This is a plugin works by default. My purpose is choosing the name from entire drop down list with all names instead of typing a marker name. – Anton Commented Mar 3, 2016 at 13:51
- But is this a feature of the ponent? Refer to the documentation provided to see if this is possible. If it isn't, you'll have to modify the ponent yourself to acplish this... – Squiggle Commented Mar 3, 2016 at 15:24
2 Answers
Reset to default 4If you want a dropdown list with all your markers, you are better off creating a custom control rather than trying to modify Leaflet.Control.Search. Creating a control with a select
element that contains all your markers is a little plicated, but certainly far simpler than tweaking the code of someone else's finished project.
Start by creating an empty control:
var selector = L.control({
position: 'topright'
});
To put content within the control, you can use the control's .onAdd
method. Create a container div for the control using L.DomUtil.create
, which in this context will automatically assign the class leaflet-control
, allowing any content within the div to display on the map and behave like a control should behave. Then create a select
element within the div. Give it a default option if you want. Most importantly, give it an id
, so that you can refer to it later:
selector.onAdd = function(map) {
var div = L.DomUtil.create('div', 'mySelector');
div.innerHTML = '<select id="marker_select"><option value="init">(select item)</option></select>';
return div;
};
Now that the control knows what to do when added to the map, go ahead and add it:
selector.addTo(map);
To add all your markers as options in the selector, you can use the .eachLayer
method, which iterates through all the markers in the group and calls a function for each. For each layer, create an option
element and append it to the select
element, using the id
assigned above. Assuming that you have created a GeoJSON layer called markerLayer
, which has a property called STATION
that you want to use as the option text, it would look like this:
markerLayer.eachLayer(function(layer) {
var optionElement = document.createElement("option");
optionElement.innerHTML = layer.feature.properties.STATION;
optionElement.value = layer._leaflet_id;
L.DomUtil.get("marker_select").appendChild(optionElement);
});
Here, we're relying on the fact that each layer gets assigned a unique internal id number, _leaflet_id
, when created. We set each option's value
attribute to the corresponding layer's _leaflet_id
, so that when the option is selected, we have a way to access the marker.
Finally, to get the control to actually do something when you select one of the options, add some event listeners, using the id
of the selector element:
var marker_select = L.DomUtil.get("marker_select");
L.DomEvent.addListener(marker_select, 'click', function(e) {
L.DomEvent.stopPropagation(e);
});
L.DomEvent.addListener(marker_select, 'change', changeHandler);
The click
listener with the stopPropagation
method is to prevent clicks on the selector from propagating through to the map if they overlap with the map pane, which could immediately unselect the layer you are trying to highlight. The change
listener will run a handler function, which you can set to do anything you want. Here, I've set it to open the popup for a marker when its corresponding option is selected:
function changeHandler(e) {
if (e.target.value == "init") {
map.closePopup();
} else {
markerLayer.getLayer(e.target.value).openPopup();
}
}
And that's it! Here is an example fiddle with all this working together:
http://jsfiddle/nathansnider/ev3kojon/
EDIT:
If you are using the MarkerCluster plugin, you can modify the change handler function to work with clustered markers using the .zoomToShowLayer
method:
function changeHandler(e) {
if (e.target.value == "init") {
map.closePopup();
} else {
var selected = markerLayer.getLayer(e.target.value);
markerClusterLayer.zoomToShowLayer(selected, function() {
selected.openPopup();
})
}
}
Example:
http://jsfiddle/nathansnider/oqk6u0sL/
(I also updated the original code and example to use the .getLayer
method rather than ._layers[e.target.value]
, because this is a cleaner way to access the marker based on its id)
There would be a way to slightly modify Leaflet-search plugin so that it shows the full list of markers when user clicks on the magnifier button (i.e. when user expands the search control).
As if the search was triggered for 0 typed letter.
Using option minLength: 0
without modifying the plugin code does not trigger a search without typing unfortunately.
L.Control.Search.mergeOptions({
minLength: 0 // Show full list when no text is typed.
});
L.Control.Search.include({
_handleKeypress: function(e) {
switch (e.keyCode) {
case 27: //Esc
this.collapse();
break;
case 13: //Enter
if (this._countertips == 1)
this._handleArrowSelect(1);
this._handleSubmit(); //do search
break;
case 38: //Up
this._handleArrowSelect(-1);
break;
case 40: //Down
this._handleArrowSelect(1);
break;
case 37: //Left
case 39: //Right
case 16: //Shift
case 17: //Ctrl
//case 32://Space
break;
case 8: //backspace
case 46: //delete
this._autoTypeTmp = false;
if (this._collapsing) { // break only if collapsing.
break;
}
default: //All keys
this._doSearch(); // see below
}
},
// externalized actual search process so that we can trigger it after control expansion.
_doSearch: function() {
if (this._input.value.length)
this._cancel.style.display = 'block';
else
this._cancel.style.display = 'none';
if (this._input.value.length >= this.options.minLength) {
var that = this;
clearTimeout(this.timerKeypress);
this.timerKeypress = setTimeout(function() {
that._fillRecordsCache();
}, this.options.delayType);
} else
this._hideTooltip();
},
expand: function(toggle) {
toggle = typeof toggle === 'boolean' ? toggle : true;
this._input.style.display = 'block';
L.DomUtil.addClass(this._container, 'search-exp');
if (toggle !== false) {
this._input.focus();
this._map.on('dragstart click', this.collapse, this);
}
this.fire('search_expanded');
this._doSearch(); // Added to trigger a search when expanding the control.
return this;
},
collapse: function() {
this._hideTooltip();
this._collapsing = true; // added to prevent showing tooltip when collapsing
this.cancel();
this._collapsing = false; // added to prevent showing tooltip when collapsing
this._alert.style.display = 'none';
this._input.blur();
if (this.options.collapsed) {
this._input.style.display = 'none';
this._cancel.style.display = 'none';
L.DomUtil.removeClass(this._container, 'search-exp');
if (this.options.hideMarkerOnCollapse) {
this._markerLoc.hide();
}
this._map.off('dragstart click', this.collapse, this);
}
this.fire('search_collapsed');
return this;
}
});
Include this code in your JavaScript before instantiating L.Control.Search
.
Demo: http://jsfiddle/ve2huzxw/190/
The big drawback of this solution is that the list of markers is built within the map container. As such, if it is too big, it will be cropped on the bottom, whereas a true select (drop-down) input would "overflow" beyond the container, as in nathansnider's solution.
本文标签: javascriptSearching markers with LeafletControlSearch from drop down listStack Overflow
版权声明:本文标题:javascript - Searching markers with Leaflet.Control.Search from drop down list - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744362165a2602598.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论