Google Maps API v3 checkbox / filter database

2020-07-29 17:18发布

I am building a site about real estate. As such, it needs to have multiples filters (city, zip code, bedrooms, style, etc.).

I read William's tutorial, and it's working with my database. The limitations of this tutorial is that we have one place per category. Ex: 123 Abc St is a golf course; 987 Zxy Ave is a Theather. In my case, the theater would be just another filter and could overlap golf course. Think of city and zip-code.

My filters (mostly checkboxes) are intersecting. I cannot toggle on and off (not OR, but AND).

Finally:

1) Is this query to database? 2) Is this query to viewport? 3) KML?

Thank you for your time and help. I’ve been stuck on this for a couple of weeks now.

Another example that almost fits the bill is this one. However, when you click a box in the surface field (please uncheck them all, click asphalt and move to the right, and check all in the difficult column - the number of spots get bigger and bigger), I think one should narrow as you go to the right. Asphalt may have 10 spots (any number). Easy trails would be 4, moderate 3 and challenging the balance to get 10 altogether (or any proportion to add 10 at the end). Or 10 asphalt, 5 easy, 1 walking. This is what I am trying to accomplish. The current site has a different path (or code).

The more check boxes you check, the more filters you apply.

UPDATE

Bass Jobsen: I really really appreciate your help. I have been stuck in the checkbox issue for weeks (everything else sort of works).

It's very impressive what you did! Your code is elegant, concise... Does in 10 lines what I was trying with 100 with no success.

I tried to learn some basics of jQuery. W3School, JQuery, played with some tutorials in order to understand your code. This is also very good.

Please look at this code. I changed a few things to accomplish the following: be closer to my field so it can be clear the intersection of fields I was talking about;

1) is there are a way to have all boxes unchecked but all the markers on? Tried with HTML, but it didn't work and jQuery is very new to me. In this way, the first boxchecked would be the first filter & user doesn't need to uncheck 30-40 boxes (the final webpage).

2)Marker/array. Am i being naive that I can consider them just as a XML file or Json ?(Reason: real web page has forms where users enter Open Houses, others will see the Open Houses - therefore I had Ajax to Server to bring data as either XML or Json, display markers/arrays in map).

So I added some "real" items. After changing the && and || a hundred times, I would like to ask for help one more time. My code does not filter properly. Tried all options I could come up with. There is one final observations: I have one sort of filtering while unchecking, different experience when all is unchecked and start to check boxes again to get markers. It seems that my code does not reflect real search. This is my mistake, not yours.

Here is the new code (based in your nice and kind code - Thank you!)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>Markers example</title>

    <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<style>
    html, body {
  height: 100%;
  margin: 0;
  padding: 0;
}

#map-canvas {

  width: 500px;
  height: 300px;
}


</style>    
  </head>
  <body>
<div id="map-canvas"></div>

<div style="float:left;">City:<br />
<input type="checkbox" name="city" value="north" checked=""/>Northen Territory<br />
<input type="checkbox" name="city" value="south" checked=""/>South Astraulia <br />
</div> 

<div style="float:left;">Style:<br />
<input type="checkbox" name="style" value="victorian" checked=""/>victorian<br />
<input type="checkbox" name="style" value="craftsman" checked=""/>craftsman<br />
</div> 

<div style="float:left;">Type:<br />
<input type="checkbox" name="type" value="sfh" checked=""/>Sinfle Family<br />
<input type="checkbox" name="type" value="condo" checked=""/>Condo<br />
<input type="checkbox" name="type" value="multi" checked=""/>Multi<br />

</div> 

<div style="float:left;">Bedrooms:<br />
<input type="checkbox" name="bedrooms" value="1" checked=""/>1<br />
<input type="checkbox" name="bedrooms" value="2" checked=""/>2<br />
<input type="checkbox" name="bedrooms" value="3" checked=""/>3<br />
<input type="checkbox" name="bedrooms" value="4" checked=""/>4<br />
</div>   

<br />

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>   
    <script>

var markersmap = [];
var markers = [];       

function initialize() {


markers[0] = {long:-25.363882,lat:133.044922,'city':['north'],'style':['victorian'],'type':['sfh'],'bedrooms':['1']};
markers[1] = {long:-26.363882,lat:133.044922,'city':['south'],'style':['victorian'],'type':['condo'],'bedrooms':['2']};
markers[2] = {long:-27.363882,lat:133.044922,'city':['south'],'style':['victorian'],'type':['sfh'],'bedrooms':['3']};
markers[3] = {long:-28.363882,lat:133.044922,'city':['south'],'style':['victorian'],'type':['sfh'],'bedrooms':['4']};
markers[4] = {long:-25.363882,lat:130.044922,'city':['north'],'style':['craftsman'],'type':['condo'],'bedrooms':['1']};
markers[5] = {long:-26.363882,lat:130.044922,'city':['south'],'style':['craftsman'],'type':['sfh'],'bedrooms':['2']};
markers[6] = {long:-27.363882,lat:130.044922,'city':['south'],'style':['craftsman'],'type':['sfh'],'bedrooms':['3']};
markers[7] = {long:-28.363882,lat:130.044922,'city':['south'],'style':['craftsman'],'type':['multi'],'bedrooms':['4']};

  var mapOptions = {
    zoom: 4,
    center: new google.maps.LatLng(-25.363882,131.044922),
    mapTypeId: google.maps.MapTypeId.ROADMAP
  }
  var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);






$.each(markers, function(index, m) {


      markersmap[index] = new google.maps.Marker({
      position: new google.maps.LatLng(m.long,m.lat),
      map: map

      });   

  });
    jQuery.get(markers, {}, function() {
        jQuery().find("marker").each(function() {
            var markers = jQuery(this);
            var latlng = new google.maps.LatLng(
                parseFloat(markers.attr("lat")),
                parseFloat(markers.attr("long"))
            );
            var marker = new google.maps.Marker({position: latlng, map: map});
        });
    });
}
google.maps.event.addDomListener(window, 'load', initialize);


$("input:checkbox").bind( "change", function() 
{
    $.each(markers, function(index, m) 
    {
        if(

        (
        ($.inArray('south',m.city)>-1 && $("input:checkbox[name='city'][value='south']").is(':checked')) ||
        ($.inArray('north',m.city)>-1 && $("input:checkbox[name='city'][value='north']").is(':checked'))
        ) &&
        (
        ($.inArray('victorian',m.style)>-1 && $("input:checkbox[name='style'][value='victorian']").is(':checked')) ||
        ($.inArray('craftsman',m.style)>-1 && $("input:checkbox[name='style'][value='craftsman']").is(':checked'))
        ) &&
        (
        ($.inArray('sfh',m.type)>-1 && $("input:checkbox[name='type'][value='sfh']").is(':checked')) ||
        ($.inArray('condo',m.type)>-1 && $("input:checkbox[name='type'][value='condo']").is(':checked')) ||
        ($.inArray('multi',m.type)>-1 && $("input:checkbox[name='type'][value='multi']").is(':checked')) 
        )&&
        (
        ($.inArray('1',m.bedrooms)>-1 && $("input:checkbox[name='bedrooms'][value='1']").is(':checked')) ||
        ($.inArray('2',m.bedrooms)>-1 && $("input:checkbox[name='bedrooms'][value='2']").is(':checked')) ||
        ($.inArray('3',m.bedrooms)>-1 && $("input:checkbox[name='bedrooms'][value='3']").is(':checked')) ||
        ($.inArray('4',m.bedrooms)>-1 && $("input:checkbox[name='bedrooms'][value='4']").is(':checked')) 
        )
        )
        {
            markersmap[index].setVisible(true);
        } 
        else
        {
            markersmap[index].setVisible(false);
        }
    })  
});

</script>    
  </body>
</html>

As you can see, it works well as you first load it in the map. But once all check boxes are clear (not checked), you need to check all the way to bedroom to see the markers. Of Course, && explains it, but I tried many combinations... If I change everything to ||, it works right when you click only one box, but it adds when you click condo + 2 bedroom. The right thing is all condos that are 2 bedrooms, not all condos + all 2 bedrooms.

UPDATE AFTER ALMOST A YEAR I decided to do all filters in the backend with php. The jquery solution was not ideal. And I am not sure if it was even possible to do that in a large scale with hundredes of markers and dozens of filters. Doing complex filters is a popular question, never saw a full answer, and it was a very complicated code to concatenate all filters. My final route was server side filter

1条回答
聊天终结者
2楼-- · 2020-07-29 17:52

To show a solution for your problem i use jQuery. I also read and draw all the markers once. When a filter is applied (uncheck a checkbox) the visibilty of the marker changed.

First create a array with marker points and properties like:

var markers = [];
markers[0] = {long:-25.363882,lat:131.044922,'type':'moutains',stars:1};

Iterate this array when you draw a marker on the map. When doing this build a second array with refereces to your markers and the same index as the first array:

$.each(markers, function(index, m) {


  markersmap[index] = new google.maps.Marker({
  position: new google.maps.LatLng(m.long,m.lat),
  map: map

  });   

});

When your filters change iterate the first array again. Check your filters and use the second array to change the visibilty of the markers.

For each filter you can use something like:

    $("input[name=stars]:checkbox").bind( "change", function() {

        var typevalue = $(this).val();
        var typechecked = $(this).is(':checked')
        $.each(markers, function(index, m) 
        {

                if(m.stars===parseInt(typevalue))
                {
                    if(typechecked) 
                    {
                        markersmap[index].setVisible(true);
                    } 
                    else
                    {
                        markersmap[index].setVisible(false);
                    }   
                }
        });
    });

The problem here is you don't want to show the marker when a other filter is on (unchecked). To solve this change if(typechecked) to if(typechecked && $("input:checkbox[name='type'][value='"+m.type+"']").is(':checked')). If you got a lot of filters this become to complex. So refactor this code to:

$("input:checkbox").bind( "change", function() 
{
    $.each(markers, function(index, m) 
    {
        if(
        $("input:checkbox[name='stars'][value='"+m.stars+"']").is(':checked') &&
        $("input:checkbox[name='type'][value='"+m.type+"']").is(':checked')
        )
        {
            markersmap[index].setVisible(true);
        } 
        else
        {
            markersmap[index].setVisible(false);
        }
    })  
});

I'm not 100% sure if this also fix: "In my case, the theater would be just another filter and could overlap golf course". Maybe one marker can be mountains AND desert in this example? If so you could make array of your poperties like:

markers[0] = {long:-25.363882,lat:131.044922,'type':['mountains','desert'],stars:1};

change your check in this case to:

    if(
    $("input:checkbox[name='stars'][value='"+m.stars+"']").is(':checked') &&
    (
    ($.inArray('mountains',m.type)>-1 && $("input:checkbox[name='type'][value='mountains']").is(':checked')) ||
    ($.inArray('desert',m.type)>-1 && $("input:checkbox[name='type'][value='desert']").is(':checked'))
    )
    )

Example:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>Markers example</title>

    <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<style>
    html, body {
  height: 100%;
  margin: 0;
  padding: 0;
}

#map-canvas {

  width: 500px;
  height: 300px;
}


</style>    
  </head>
  <body>
<div id="map-canvas"></div>

<div style="float:left;">Type:<br />
<input type="checkbox" name="type" value="mountains" checked="checked"/>Mountains<br />
<input type="checkbox" name="type" value="desert" checked="checked"/>Desert<br />
</div> 

<div style="float:left;">Stars:<br />
<input type="checkbox" name="stars" value="1" checked="checked"/>1<br />
<input type="checkbox" name="stars" value="2" checked="checked"/>2<br />
<input type="checkbox" name="stars" value="3" checked="checked"/>3<br />
</div>   

<br />

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>   
    <script>

var markersmap = [];
var markers = [];       

function initialize() {


markers[0] = {long:-25.363882,lat:131.044922,'type':['mountains','desert'],stars:1};
markers[1] = {long:-26.363882,lat:132.044922,'type':['mountains'],stars:1};
markers[2] = {long:-27.363882,lat:133.044922,'type':['mountains'],stars:2};
markers[3] = {long:-28.363882,lat:133.044922,'type':['mountains'],stars:2};
markers[4] = {long:-25.363882,lat:130.044922,'type':['desert'],stars:1};
markers[5] = {long:-26.363882,lat:130.044922,'type':['desert'],stars:2};
markers[6] = {long:-27.363882,lat:130.044922,'type':['desert'],stars:3};
markers[7] = {long:-28.363882,lat:130.044922,'type':['desert'],stars:3};

  var mapOptions = {
    zoom: 4,
    center: new google.maps.LatLng(-25.363882,131.044922),
    mapTypeId: google.maps.MapTypeId.ROADMAP
  }
  var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);



$.each(markers, function(index, m) {


      markersmap[index] = new google.maps.Marker({
      position: new google.maps.LatLng(m.long,m.lat),
      map: map

      });   

  });

}
google.maps.event.addDomListener(window, 'load', initialize);

$("input:checkbox").bind( "change", function() 
{
    $.each(markers, function(index, m) 
    {
        if(
        $("input:checkbox[name='stars'][value='"+m.stars+"']").is(':checked') &&
        (
        ($.inArray('mountains',m.type)>-1 && $("input:checkbox[name='type'][value='mountains']").is(':checked')) ||
        ($.inArray('desert',m.type)>-1 && $("input:checkbox[name='type'][value='desert']").is(':checked'))
        )
        )
        {
            markersmap[index].setVisible(true);
        } 
        else
        {
            markersmap[index].setVisible(false);
        }
    })  
});

</script>    


  </body>


</html>
查看更多
登录 后发表回答