samedi 5 novembre 2016

How do I filter multiple list items using checkboxes?

How to create 2 checkboxes, displaying (i.e.) 1. Food and 2. Musician…

Where
1) if both checkboxes are checked, food and musicians are displayed;
2) if food is checked and musician is unchecked, the element is still visible, because it contains food, dispite it also contains musician;
3) if musician is checked and food is unchecked, it is also still visible, because it contains musician, dispite it also contains food;
4) if both food and musician are unchecked, the li item disappears.

My html is:

<html>
<head>
</head>
<body>

<ul class="filterSection">
<li>
<input checked="true" type="checkbox" value="Food"/>
<label>Food</label>
</li>
<li>
<input checked="true" type="checkbox" value="Musician"/>
<label>Musician</label>
</li>
</ul>

<ul id="itemsToFilter">
<li data-type="Food">Food</li>
<li data-type="Musician">Musician</li>
<li data-type="Food Musician">Food & Musician</li>
<ul>

</body>
</html>

And the following javascript code (integrated below the two lists):

<script>
// get all of our list items
var itemsToFilter = document.querySelectorAll("#itemsToFilter li");
  
//setup click event handlers on our checkboxes
var checkBoxes = document.querySelectorAll(".filterSection li input");
  
for (var i = 0; i < checkBoxes.length; i++) {
    checkBoxes[i].addEventListener("click", filterItems, false);
    checkBoxes[i].checked = true;
}
  
// the event handler!
function filterItems(e) {
    var clickedItem = e.target;
      
    if (clickedItem.checked == true) {
        hideOrShowItems(clickedItem.value, "hideItem", "showItem");
    } else if (clickedItem.checked == false) {
        hideOrShowItems(clickedItem.value, "showItem", "hideItem");
    } else {
        // deal with the indeterminate state if needed
    }
}
  
// add or remove classes to show or hide our content
function hideOrShowItems(itemType, classToRemove, classToAdd) {
    for (var i = 0; i < itemsToFilter.length; i++) {
        var currentItem = itemsToFilter[i];
          
        if (currentItem.getAttribute("data-type") == itemType) {
            removeClass(currentItem, classToRemove);
            addClass(currentItem, classToAdd);
        }
    }
}
  
//
// Helper functions for adding and removing class values
//
function addClass(element, classToAdd) {
    var currentClassValue = element.className;
        
    if (currentClassValue.indexOf(classToAdd) == -1) {
        if ((currentClassValue == null) || (currentClassValue === "")) {
            element.className = classToAdd;
        } else {
            element.className += " " + classToAdd;
        }
    }
}
        
function removeClass(element, classToRemove) {
    var currentClassValue = element.className;
  
    if (currentClassValue == classToRemove) {
        element.className = "";
        return;
    }
  
    var classValues = currentClassValue.split(" ");
    var filteredList = [];
  
    for (var i = 0 ; i < classValues.length; i++) {
        if (classToRemove != classValues[i]) {
            filteredList.push(classValues[i]);
        }
    }
  
    element.className = filteredList.join(" ");
}
</script>

I found out that in css you can do the following:

#itemsToFilter li[data-type*=Food] {background-color: green;}
#itemsToFilter li[data-type*=Musician] {background-color: yellow;}

(The asterisk causes one or multiple data-type attributes to be recognised)

No problems there, so I'm interested in the javascript-part:

Where
1) if both checkboxes are checked, food and musicians are displayed;
2) if food is checked and musician is unchecked, the element is still visible, because it contains food, dispite it also contains musician;
3) if musician is checked and food is unchecked, it is also still visible, because it contains musician, dispite it also contains food;
4) if both food and musician are unchecked, the li item disappears.

I want this without having to make a new checkbox called 'Food Musician'. Which could be done by adding

#itemsToFilter li[data-type*='Food Musician'] {background:pink;}

So only working with the checkboxes 'Food' and 'Musician'.

See or follow this example on http://ift.tt/2fsfn0b

My question was raised after reading this article from Kirupa:
http://ift.tt/2ezD9tE

I also found this example, which is kinda what I want:
Filter by multiple data attribute elements

Winning answer gets a bar of chocolate.
Thanks a lot in advance!




Aucun commentaire:

Enregistrer un commentaire