在传单地图上显示多个搜索结果



https://www.website.ro/harta这是使用leaflet.js和https://github.com/stefanocudini/leaflet-search,但我只能搜索单个位置。

https://www.website.ro/public/ajax?q=electri

如果我搜索";电气;它有3个位置,我想在点击回车时显示它们,而不是显示";未找到";。

stackoverflow已经在谷歌上搜索过了,但没有找到类似的答案/问题。

这可以通过仔细使用传单搜索提供的选项来完成。首先,让我们创建一个数组来保存潜在的结果,并创建一个featureLayer来渲染显示的任何结果:

const results = [];
var resultsLayer = L.featureGroup();

现在,我们可以将buildTip选项覆盖为一个函数,该函数几乎完成了默认情况下已经完成的操作,但也将结果推送到一个数组:

var controlSearch = new L.Control.Search({
...options,
// hijack buildtip function, push results to array
buildTip: (text, loc) => {
results.push(loc); // <---- crucial line here
// the rest of this is lifted from the source code almost exactly
// so as to keep the same behavior when clicking on an option
const tip = L.DomUtil.create("div");
tip.innerHTML = text;
L.DomEvent.disableClickPropagation(tip)
.on(tip, "click", L.DomEvent.stop, controlSearch)
.on(
tip,
"click",
function (e) {
controlSearch._input.value = text;
controlSearch._handleAutoresize();
controlSearch._input.focus();
controlSearch._hideTooltip();
controlSearch._handleSubmit();
},
controlSearch
);
return tip;
},
// only move to the location if there are not multiple results
moveToLocation: results.length
? () => {}
: L.Control.Search._defaultMoveToLocation
});

现在,我们在搜索的输入中添加一个事件侦听器,如果用户按下回车键,并且有多个结果,则推送到results数组中的结果将作为标记添加到resultsLayer中,并添加到映射中:

inputEl.addEventListener("keypress", function (e) {
if (e.key === "Enter" && results.length) {
markersLayer.remove();
results.forEach((result) => {
const marker = L.marker(result);
resultsLayer.addLayer(marker);
});
map.fitBounds(resultsLayer.getBounds());
}
});

工作代码沙箱

请注意,这可能需要一些清理工作(即在新的或空的搜索中清空数组(,或者在搜索为空时读取完整的数据集,等等,但这应该足以让您开始。

编辑-完整项目信息

你在评论中问我们如何获得项目的全部细节并将其放入弹出窗口。通过阅读传单搜索的文档和源代码,似乎没有任何地方的代码"捕捉"到整个数据对象。buildTip函数实际上只需要一个项中的两条数据-要在工具提示中显示的文本和它所指的位置。有很多关于将源数据保存在缓存中的TODO,但它们仍然是待办事项。

我要做的是使用结果中返回的titleloc来过滤原始数据,并在原始数据中找到相应的项:

const getFullItem = (title, loc) => {
return data.find((item) => item.title === title && loc.equals(item.loc));
};

我们还可以创建一个通用函数来为所有制造商和结果构建弹出文本,因此弹出窗口都是一致的:

const buildPopupText = (item) => {
return `
<h4>Title: ${item.title}</h4>
<p>Phone: ${item.telefon}</p>
<p>more stuff from ${item.whatever}</p>
`;
};

当我们点击回车键并通过results进行映射时,我们将使用结果来获得原始项目:

inputEl.addEventListener("keypress", function (e) {
if (e.key === "Enter" && results.length) {
results.forEach((result) => {
const originalItem = getFullItem(result.text, result.loc);
const marker = L.marker(result.loc);
marker.bindPopup(buildPopupText(originalItem));
resultsLayer.addLayer(marker);
});
map.fitBounds(resultsLayer.getBounds());
}
});

因此,现在结果弹出窗口从originalItem构建了一个弹出窗口,它具有您需要的所有属性。

工作代码沙箱

最新更新