Search for numeric values between min/max values


(Andrea Crawford) #1

Hi!

I’m looking to create a property search, which will allow people to set a min/max price and see all the results that fall within that range.

I’m guessing it’s possible to do this by getting Matrix to output all the results that fit the other criteria (property type, beds, baths) and then using JavaScript to hide the results that fall outside the price range, but is there a better way to do this?

Any suggestions would be greatly appreciated :slight_smile:

Matrix Version:5.3.3.0


(Dcook) #2

Hmm I can’t think of a way unfortunately, it seems the only option to search for a range is on dates using the Calendar Events Search Page, which wouldn’t help you. You might be able to use a keyword modifier in the display format to show/hide based on a value (eg %begin_asset_metadata_price^gte:globals_get_price_min%), but this might not be very performant.
Would be good to hear if anyone else has ideas though.

For a small data set (<100), preloading all results and filtering with JS can actually be a pretty good option, as it allows for instantaneous results.


(Andrea Crawford) #3

Thanks for the reply! I did end up going with the filtering option, since I don’t have too much data to deal with.

I thought I’d write down what I did, in case anyone is looking at doing something similar, this could help as a starting point. It’s a bit rough for now but it does seem to work…

  • Create a metadata scheme containing all the fields you want to be able to search

  • Create a data record for each entry, and apply the metadata schema to it

  • Create an asset listing page which lists all the data records, putting the metadata inside data-* attributes
    (I sorted this asset listing by price, ascending. Later on it might be nice to have dynamic sorting)
     

    %asset_name%

    %asset_metadata_hostel^as_asset:asset_name%

    S$%asset_metadata_price% monthly rent per bed
    %asset_metadata_sharing% bed%asset_metadata_sharing^gt:1:s% per room %begin_asset_metadata_ensuite% | Ensuite%end_asset_metadata_ensuite% | %asset_metadata_distance% mins travel time

    Learn more about this hostel...

Create a form for the search portion of the page:

<form id="accommodation-search">
    <label for="min">Min Price (S$)</label><input min="0" type="number" value="0" name="min" id="min" />
    <label for="min">Max Price (S$)</label><br/><input min="0" type="number" value="1600" name="max" id="max" />
    <label for="distance">Max travel time (by public transport)</label>
    <select name="distance" id="distance">
        <option value="30">30 minutes</option>
        <option value="45">45 minutes</option>
        <option value="60" selected>1 hour</option>
    </select>
    <h4>Room Type</h4>
    <ul>
        <li><label><input type="checkbox" value="1" name="sharing" checked> Single Room</label></li>
        <li><label><input type="checkbox" value="2" name="sharing" checked> Twin Sharing</label></li>
        <li><label><input type="checkbox" value="3" name="sharing" checked> Triple Sharing</label></li>
        <li><label><input type="checkbox" value="4" name="sharing" checked> Quad Sharing</label></li>
    </ul>
    <h4>Extras</h4>
    <label><input type="checkbox" name="ensuite" id="ensuite" /> Ensuite</label>
</form>
<p id="matches"></p>

Show/hide the rooms based on whether or not they match the selected criteria. The update function runs when the input changes or a keyup event is fired in one of the inputs.

<script>
    $(document).ready(update);
    
    $('#accommodation-search input').change(update);
    $('#accommodation-search select').change(update);
    $('#accommodation-search input').keyup(update);
    
    var matches;
    
    function update(){
        if ($("input[name='sharing']:checked").length>0) {
            var sharing = $("input[name='sharing']:checked").map(function(i,x){return x.value});
        } else {
            var sharing = false;
        }
        var min = $('#min').val();
        var max = $('#max').val();
        var distance = $('#distance option:selected').val();
        var ensuite = $('#ensuite').prop('checked');
        matches = 0;
        $('.room').each(function(i,d){
            var match = true;
            if(sharing&&$.inArray($(d).data().sharing.toString(),sharing)==-1){match=false};
            if(ensuite&&$(d).data().ensuite!=ensuite){match=false};
            if($(d).data().price>max){match=false};
            if($(d).data().price<min){match=false};
            if($(d).data().distance>distance){match=false};
            if(!match){$(d).hide()}else{$(d).show(); matches++;};
        });
        
        if(matches==0){
            $('#matches').text('No matches found. Try broadening your search.');
        } else if (matches==1){
            $('#matches').text('1 match found');
        } else {
            $('#matches').text(matches + ' matches found');
        }
    }
</script>