0

Im looking for a simple way to filter content based on attribue value(s). I have multiple attributes and I use checkboxes input to filter content. My problem is that I don't see how to make sure to validate one attribute before the second one.

What I mean is that one of my attribute would be a location, and my second would be an action tag. If one of the location checkboxes is disabled, I don't want any of the action tag to override the location. I don't see how to dissociate the checking conditions so if (in my example below) "paris" is disabled, unchecking or checking "have a coffee" would make the Result 1 appear.

here is what I have right now:

<div id="filtersContainer" class="tags">
    <div id="location" class="filcont"><h2>Mood</h2></div>
    <div id="action" class="filcont"><h2>Action</h2></div>
</div>
</div>

<div class="results">
        <div class="mark" location="paris" action="have-a-coffee eat">Result 1</div>
        <div class="mark" location="lyon" action="drink have-a-coffee eat">Result 2</div>
        <div class="mark" location="paris lyon" action="take-away drink eat">Result 3</div>
        <div class="mark" location="grenoble paris" action="drink">Result 4</div>
</div>

$( document ).ready(function() {

    $("#filtersContainer").css('top', '-1000px')

    //Building up filter options based on HTML data
    dynamicFiltering();

    //Activating all filters
    $('.mark').show();

    //On filter clicks
    $('.tags').find('input:checkbox').on('click', function () {
        $('.mark').hide();
        $('.tags').find('input:checked').each(function () {
            $('.mark[location~="'+$(this).attr('rel')+'"]').show();
        });
    });

    $('.tags').find('input:checkbox').on('click', function () {
           $('.mark').hide();
           $('.tags').find('input:checked').each(function () {
              $('.mark[action~="'+$(this).attr('rel')+'"]').show();
           });
        });
    });

Input elements are generated dynamically based on database content. it look like this though:

<p class="check-tooltip">'+locationFilters[k]+'</p>'+
'<div class="checkboxing"><input type="checkbox" id="'+locationFilters[k]+'" checked rel="'+locationFilters[k]+'" />'+
'<label for="'+locationFilters[k]+'"></label></div>'

UPDATED SOLUTION WORKING

$( document ).ready(function() {

    $("#filtersContainer").css('top', '-1000px')

    //Building up filter options based on HTML data
    dynamicFiltering();

    //Activating all filters
    $('.mark').show();

    $('.tags').find('input:checkbox').on('click', function () {
        var found = $.inArray($(this).attr('rel'), filterAre) > -1;
        if(!found){
            filterAre.push($(this).attr('rel'));
        }
        else{
            removeA(filterAre, $(this).attr('rel'));
        }

        // console.log(filterAre);
        filter();
    });
});

function filter(){
    // $(".mark").show();

    $.each(filterAre, function(index, value){
        $(".mark").each(function(){
            var rel = $(this).attr('filter-data');

            var array = rel.split(" ");

            var count = 0;


             for(var g=0; g<array.length; g++){
                 var found = $.inArray(array[g], filterAre) > -1;
                 if(!found){
                    $(this).hide();
                    break;
                 }
                 else{
                    $(this).show();
                 }
             }
        });
    });
}

function removeA(arr){
    var what, a= arguments, L= a.length, ax;
    while(L> 1 && arr.length){
        what= a[--L];
        while((ax= arr.indexOf(what))!= -1){
            arr.splice(ax, 1);
        }
    }
    return arr;
}
2
  • you don't have any input elements in your elements that have class tags Commented Feb 12, 2016 at 19:27
  • sorry about that, inputs are generated dynamically. It added the template in an edit. Commented Feb 12, 2016 at 19:32

1 Answer 1

1

What I do to filter elements by attributes:

Create a filter array containing the attributes that are required to show an element.

On filter click call the function setFilter() that adds/removes the attribute name from the filter array and then calls the function filter().

The filter() function shows all elements first and then loops trough all the elements for each attribute, if the attribute is not set or not a certain value hide the element.

If you want I can post some basic code example.

Here's some basic psuedo code(on phone):

var filters = {};
function setFilter(filter, value, add) {
    if(add) {
        filters[filter] = value;
    } else {
        remove filters[filter]
    }
    filter();
}
function filter() {
    elements.show();
    foreach(filters as filter=>value) {
        foreach(elements as element) {
            if(element.attr(filter) != value) {
                element.hide();
            }
        }
    }
}

This is code is not working lol, it's psuedo code but it shows clearly how an object can be used to filter on multiple attribute values.

Sign up to request clarification or add additional context in comments.

6 Comments

that would be nice. Unfortunately I think Im looping things in my mind without being able to clear thing out.. by the way, I added an input template Im using cause they are added dynamically and my html part was missing it.
Im on my phone so I hope you don't mind psuedo code.
Do you filter based on the existance of an attribute on a result or the attribute value?
location and action attr are always there, so it's only based on the value(s) they have. my point is that both paris and lyon divs could have the same action tags. but if I disable paris I don't want the action tag to show paris div again by being clicked.
Added some pseudo code that shows how it's possible to filter on multiple attributes.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.