多维过滤

时间:2014-07-10 17:20:31

标签: javascript google-maps google-maps-api-3 filter

我想将多种类型的过滤器同时与“或”和“和”逻辑组合在一起。例如,我尝试过滤我的标记,如下例所示: http://codepen.io/patrickkunka/pen/ltgde

我已经放了多个标记,我创建了两个显示或隐藏标记的函数。 问题是,如果我显示来自GroupA的标记,然后我选择数字1的标记,我将使用数字1的所有标记。或者目标是同时具有来自GroupA和Number 1的标记。

对不起,这是我可以把它减少到最简单的:

<!DOCTYPE html>
<html> 
<head> 
  <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> 
  <title>Google Maps Multi-Filtering</title> 
  <script src="http://maps.google.com/maps/api/js?sensor=false" 
          type="text/javascript"></script>
</head> 
<body>
        <div id="map" style="width: 500px; height: 400px;"></div>
    <div id="multi_filters">
      <div class="Group"> 
        <a class="titre">Group</a></br>
        <input type="checkbox" value="GroupA" onclick="displayGroup('GroupA');" checked>
        <input type="checkbox" value="GroupB" onclick="displayGroup('GroupB');" checked>
      </div>
    </br>
      <div class="Number"> 
        <a class="titre">Number</a></br>
        <input type="checkbox" value="Number1" onclick="displayNumber(1);" checked>
        <input type="checkbox" value="Number2" onclick="displayNumber(2);" checked>
      </div>
    </div>
</body>
</html>

和Javascript:

    var markers =[];
    var locations = [
      ['GroupA','Bondi Beach', -33.890542, 151.274856, 2],
      ['GroupB','Coogee Beach', -33.923036, 151.259052, 2],
      ['GroupA','Cronulla Beach', -34.028249, 151.157507, 1],
      ['GroupB','Manly Beach', -33.80010128657071, 151.28747820854187, 2],
      ['GroupA','Maroubra Beach', -33.950198, 151.259302, 1]
    ];

    var map = new google.maps.Map(document.getElementById('map'), {
      zoom: 10,
      center: new google.maps.LatLng(-33.92, 151.25),
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });

    var marker, i; 
    for (i = 0; i < locations.length; i++) {  
      marker = new google.maps.Marker({
        position: new google.maps.LatLng(locations[i][2], locations[i][3]),
        map: map
      });
      marker.group= locations[i][0];
      marker.number = locations[i][4];
      markers.push(marker);   
    }

  function displayGroup(group) {
        var i;
       for (i = 0; i < markers.length; i++) {
         if (markers[i].group === group) {
          if(!(markers[i].getVisible(true))){markers[i].setVisible(true);}
           else{markers[i].setVisible(false);}
         }
       }
  }; 

  function displayNumber(number) {
        var i;
       for (i = 0; i < markers.length; i++) {
         if (markers[i].number === number) {
          if(!(markers[i].getVisible(true))){markers[i].setVisible(true);}
           else{markers[i].setVisible(false);}
         }
       }
  }; 

非常感谢任何帮助!谢谢

1 个答案:

答案 0 :(得分:0)

可能的解决方案:

假设有这样的标记(稍后将附加点击监听器):

<div id="multi_filters">
  <div class="Group"> 
    <a class="titre">Group</a></br>
    A<input type="checkbox" value="GroupA" data-prop="group" checked/>
    B<input type="checkbox" value="GroupB"  data-prop="group"/>
  </div>
</br>
  <div class="Number"> 
    <a class="titre">Number</a></br>
    1<input type="checkbox" value="1"  data-prop="number" checked/>
    2<input type="checkbox" value="2"  data-prop="number"/>
  </div>
</div>

属性应该是自我解释的,data-prop是为标记存储的属性名称,value是要测试的属性的值。

以下脚本基于选中的复选框创建正则表达式,它将存储在对象中。

(function(boxes){

    for(var i=0;i<boxes.length;++i){
      //add click-listener for the checkboxes
      google.maps.event.addDomListener(boxes[i],'click',function(){
         var props={},box,prop,val,any,marker;
         for(var i=0;i<boxes.length;++i){
          box=boxes[i];
          prop=box.getAttribute('data-prop');
          val=box.value;

          if(box.checked){
            //variable to determine if there is any checkbox checked
            any=true;
            //populate an object with arrays
            //(key is the property-name)
            if(!props[prop]){
              props[prop]=[];
            }
            //push the value to the particular array
            props[prop].push(val);
          }
         }
         //create RegExp's from the arrays 
         for(var k in props){
            props[k]=new RegExp('^('+props[k].join('|')+')$');
         }
         //iterate over the markers
         for(var m=0;m<markers.length;++m){
          marker=markers[m];
          //no checkbox is checked, hide all markers
          if(!any){
            marker.setMap(null);
          }
          //there is a condition, check it
          else{
             inner:
            //iterate over the RegExp's
            for(var k in props){
              //if condition doesn't match hide marker and run next loop 
              if(!String(marker[k]).match(props[k])){
                marker.setMap(null);
                break inner;
              }
              //all RegExp's match, show the marker
              marker.setMap(map);
            }
          }
         }
      });
    }
    if(boxes.length){
      //trigger the event to apply the initial marker-state
      google.maps.event.trigger(boxes[0],'click',{})
    }
  })(document.querySelectorAll('input[data-prop]'));

对于给定的标记(组:GroupA和数字:1被检查),得到的条件,例如将是:

{group:/^(GroupA)$/,number:/^(1)$/}

脚本将在这些条件下运行,如果有任何失败,它会隐藏标记,否则会显示标记。

演示:http://jsfiddle.net/doktormolle/QyMLg/