json - 具有多个 HTML 选择过滤器和数组值的 Google Maps JS API
问题描述
我正在开发基于 Google Maps JS API 的自定义商店定位器,并且正在从 JSON 文件中检索所有位置数据。每个商店都可以通过选择过滤器的组合进行过滤。
我的目标是按“商店类型”(字符串)、“品牌”(品牌数组)和“裁缝”(字符串)进行过滤。按字符串(单个值)过滤效果很好,但我被困在“品牌”过滤器上。脚本无法匹配数组中的值。所以我的问题是:我需要修改什么来实现字符串+数组过滤器的组合?
我正在使用以下代码:https ://codepen.io/xtiggerk/pen/GBNPdO
var json = [
{
"title" : "Store A",
"type" : "boutique",
"brands" : ["Brand A", "Brand B", "Brand C"],
"tailor" : "tailora",
"geometry": {
"type": "Point",
"coordinates": [
0.48339843749999994,
46.89023157359399
]
}
},
{
"title" : "Store B",
"type" : "boutique",
"brands" : ["Brand D", "Brand E", "Brand F"],
"tailor" : "tailorb",
"geometry": {
"type": "Point",
"coordinates": [
2.7685546874999996,
47.76148371616669
]
}
},
{
"title" : "Store C",
"type" : "mall",
"brands" : ["Brand A", "Brand B", "Brand C"],
"tailor" : "tailora",
"geometry": {
"type": "Point",
"coordinates": [
2.57080078125,
45.882360730184025
]
}
},
{
"title" : "Store D",
"type" : "mall",
"brands" : ["Brand D", "Brand E", "Brand F"],
"tailor" : "tailorb",
"geometry": {
"type": "Point",
"coordinates": [
-0.098876953125,
44.52001001133986
]
}
},
{
"title" : "Store E",
"type" : "popupstore",
"brands" : ["Brand A", "Brand B", "Brand C"],
"tailor" : "tailora",
"geometry": {
"type": "Point",
"coordinates": [
4.54833984375,
45.874712248904764
]
}
},
{
"title" : "Store F",
"type" : "popupstore",
"brands" : ["Brand D", "Brand E", "Brand F"],
"tailor" : "tailorb",
"geometry": {
"type": "Point",
"coordinates": [
4.822998046875,
45.920587344733654
]
}
}
]
var jsonStringify = JSON.stringify(json)
var jsonParse = JSON.parse(jsonStringify);
var markers = [];
var markerCluster;
var searchInput = jQuery('#searchMap input');
var filterSelect = jQuery('.filter');
var resetButton = jQuery('#resetFilter');
var filterResults = [];
for (var i = 0; i < json.length; i++) {
var filters = json[i];
var filtertype = filters.type;
var filterbrands = filters.brands;
var filtertailor = filters.tailor;
filterResults.push(filtertype, filterbrands, filtertailor);
}
var filterStringify = JSON.stringify(filterResults)
var filterParse = JSON.parse(filterStringify);
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 6,
center: new google.maps.LatLng(45.882360730184025, 2.57080078125)
});
for (var i = 0; i < json.length; i++){
setMarkers(json[i], map);
}
markerCluster = new MarkerClusterer(map, markers, {ignoreHiddenMarkers: true, imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'});
}
function setMarkers(marker, map) {
var markerMap = marker.geometry.coordinates;
var title = marker.title;
var type = marker.type;
var brands = marker.brands;
var tailor = marker.tailor;
var pos = new google.maps.LatLng(markerMap[1], markerMap[0]);
var content = marker;
markerMap = new google.maps.Marker({
position: pos,
title: title,
type: type,
brands: brands,
tailor: tailor,
map: map
});
markers.push(markerMap);
var infowindow = new google.maps.InfoWindow({
content: title + '<br/>' + type + '<br/>' + brands + '<br/>' + tailor
});
// Marker click listener
google.maps.event.addListener(markerMap, 'click', (function (marker1, content) {
return function () {
infowindow.setContent(content);
infowindow.open(map, markerMap);
map.panTo(this.getPosition());
// map.setZoom(15);
}
})(markerMap, content));
}
function clusterManager(array) {
markerCluster.clearMarkers();
if (!array.length) {
jQuery('.alert').addClass('is-visible');
} else {
jQuery('.alert').removeClass('is-visible');
for (i=0; i < array.length; i++) {
markerCluster.addMarker(array[i]);
}
}
}
//@todo add inputsearch
function newFilter(filterType1 = 'all', filterType2 = 'all', filterType3 = 'all') {
var criteria = [
{ Field: "type", Values: [filterType1] },
{ Field: "brands", Values: [filterType2] },
{ Field: "tailor", Values: [filterType3] },
// { Field: ["type", "tailor", "brands"], Values: [filterTyped] }
];
var filtered = markers.flexFilter(criteria);
clusterManager(filtered);
}
Array.prototype.flexFilter = function(info) {
// Set our variables
var matchesFilter, matches = [], count;
// Helper function to loop through the filter criteria to find matching values
// Each filter criteria is treated as "AND". So each item must match all the filter criteria to be considered a match.
// Multiple filter values in a filter field are treated as "OR" i.e. ["Blue", "Green"] will yield items matching a value of Blue OR Green.
matchesFilter = function(item) {
count = 0
for (var n = 0; n < info.length; n++) {
if (info[n]["Values"].indexOf(item[info[n]["Field"]]) > -1) {
count++;
}
//if value = all, return all item
else if (info[n]["Values"] == "all") {
count++;
}
}
// If TRUE, then the current item in the array meets all the filter criteria
return count == info.length;
}
// Loop through each item in the array
for (var i = 0; i < this.length; i++) {
// Determine if the current item matches the filter criteria
if (matchesFilter(this[i])) {
matches.push(this[i]);
}
}
// Give us a new array containing the objects matching the filter criteria
return matches;
}
jQuery(document).ready(function() {
jQuery('.filter-type').on('change', function(){
var filter2 = jQuery('.filter-brands').val();
var filter3 = jQuery('.filter-tailor').val();
newFilter(jQuery(this).val(), filter2, filter3);
});
jQuery('.filter-brands').on('change', function(){
var filter1 = jQuery('.filter-type').val();
var filter3 = jQuery('.filter-tailor').val();
newFilter(filter1, jQuery(this).val(), filter3);
});
jQuery('.filter-tailor').on('change', function(){
var filter1 = jQuery('.filter-type').val();
var filter2 = jQuery('.filter-brands').val();
newFilter(filter1, filter2, jQuery(this).val());
});
searchInput.on('keyup', function () {
var searchTyped = $(this).val();
var arr = [];
if (searchTyped.length > 0) {
jsonParse.filter(function() {
for (i = 0; i < json.length; i++) {
marker = markers[i];
var markerFilter = [];
var filtertype = marker.type;
var filterbrands = marker.brands;
var filtertailor = marker.tailor;
markerFilter.push(filtertype, filterbrands, filtertailor);
var markerFilterStringify = JSON.stringify(markerFilter);
if( markerFilterStringify.indexOf(searchTyped) >= 0) {
arr.push(marker);
} else {
console.log('dont fit requirement')
}
}
});
clusterManager(arr);
} else {
newFilter();
}
});
resetButton.on('click', function() {
searchInput.val('');
filterSelect.val('all');
newFilter();
});
//delete all duplicated value from the previous array
var uniqueValue = [];
jQuery.each(filterResults, function(i, el){
if(jQuery.inArray(el, uniqueValue) === -1) {
uniqueValue.push(el);
}
});
var substringMatcher = function(strs) {
return function findMatches(q, cb) {
var matches, substringRegex;
matches = [];
substrRegex = new RegExp(q, 'i');
jQuery.each(strs, function(i, str) {
if (substrRegex.test(str)) {
matches.push(str);
}
});
cb(matches);
};
};
searchInput.typeahead({
hint: true,
highlight: true,
minLength: 1
},
{
tailor: 'customFilter',
source: substringMatcher(uniqueValue)
});
});
jQuery(window).on('load', function(){
initMap();
});
解决方案
您可以尝试matchesFilter
按如下方式更改您的功能:
matchesFilter = function(item) {
count = 0
for (var n = 0; n < info.length; n++) {
var values = info[n]["Values"];
var fieldArr = item[info[n]["Field"]];
if (values.indexOf(fieldArr) > -1) {
count++;
}
//if value = all, return all item
else if (values == "all") {
count++;
} else {
//if value is an array, loop through it to find a match using includes() method
if (values instanceof Array) {
for (var j = 0; j < values.length; j++) {
if (fieldArr.includes(values[j])) {
count++;
}
}
}
}
}
// If TRUE, then the current item in the array meets all the filter criteria
return count == info.length;
}
希望这可以帮助!
推荐阅读
- amazon-web-services - 备份和恢复多个帐户中的 Cognito 用户
- c# - 当 DataContext 更改时,带有 datatemplated ContentControl 的 UserControl 会引发绑定错误
- python - 列出数据框
- dns - 如何知道 Dnsmasq 的最大 TTL 的默认值
- postgresql - 如何将postgres的列日期更新为提前几天
- javascript - 当我尝试它时颜色不会改变 ti 改变
- arrays - 数组天气API
- ruby - | 之间有什么规则吗?x | 在块函数中?
- excel - 无法以 SYSTEM 身份运行 Excel COM 对象
- java - 如何在我的 android 应用程序中访问我的 Spring Boot Websocket (Stomp)?