简体   繁体   中英

jQuery filtering by data attribute via two select inputs

I'm having trouble filtering resulting div's with jQuery via two different inputs. Users can decide to filter by office , specialty or both office and specialty . The filtering is set from data attributes on the div that correspond to the select inputs values.

<div>
  <label for="officeSearch">Search by office:</label>
  <select name="Office Search" id="officeSearch">
    <option value="all"></option>
    <option value="communication">Communication</option>
    <option value="internal medicine">Internal Medicine</option>
  </select>
</div>
<div>
  <label for="specialtySearch">Search by specialty:</label>
  <select name="Specialty Search" id="specialtySearch">
    <option value="all"></option>
    <option value="Bone Cancer">Bone Cancer</option>
    <option value="Breast Cancer">Breast Cancer</option>
    <option value="Oral Cancer">Oral Cancer</option>
  </select>
</div>

<div class="module-sm profile" data-office="communication" data-specialty="Oral Cancer">
  <p>Person A</p>
</div>
<div class="module-sm profile" data-office="communication" data-specialty="Breast Cancer">
  <p>Person B</p>
</div>
<div class="module-sm profile" data-office="internal medicine" data-specialty="Bone Cancer">
  <p>Person C</p>
</div>

Here's the jQuery I'm using that fires on change of the selects:

$(document).ready(function() {
  $("#officeSearch").on('change', function(){
    var selectedOffice = $('#officeSearch').val();
    var selectedSpecialty = $('#specialtySearch').val();
    var person = $('#filterList .profile').not('.out');
    var allPersons = $('#filterList .profile');
    var allPersonsOffice = $('#filterList .profile').data('office');
    var allPersonsOut = $('#filterList .profile.out');

    var office = $('.profile[data-office="' + selectedOffice +'"]');

    alert(''+ selectedOffice + ' ' + selectedSpecialty +'');

    if (selectedOffice == 'all' && selectedSpecialty == 'all'){
        $(allPersons).removeClass('out').fadeIn(500);
    }
    else {
        $(person).not(office).addClass('out').fadeOut(500);
        office.removeClass('out').fadeIn(500);
    }
  });
  $("#specialtySearch").on('change', function(){
    var selectedOffice = $('#officeSearch').val();
    var selectedSpecialty = $('#specialtySearch').val();
    var person = $('#filterList .profile').not('.out');
    var allPersons = $('#filterList .profile');
    var allPersonsOffice = $('#filterList .profile').data('office');
    var allPersonsOut = $('#filterList .profile.out');

    var specialty = $('.profile[data-specialty="' + selectedSpecialty +'"]');

    alert(''+ selectedOffice + ' ' + selectedSpecialty +'');

    if (selectedOffice == 'all' && selectedSpecialty == 'all'){
        $(allPersons).removeClass('out').fadeIn(500);
    }
    else {
        $(person).not(specialty).addClass('out').fadeOut(500);
        specialty.removeClass('out').fadeIn(500);
    }
  });
});

If it helps, I've made a codepen to demonstrate what I'm trying to do and where I'm at so far.

I've done some searching and have been scratching my head on how to get this working for weeks. Any help making this code more concise or examples to how others have solved this problem are greatly appreciated!

  1. Call a single update from either selection changing.
  2. Create a filter based on the selections (appended).
  3. Hide the ones not in the matches
  4. show the matches.

JSFiddle: http://jsfiddle.net/TrueBlueAussie/2u7NY/

$(document).ready(function () {
    var onChange = function () {

        var selectedOffice = $('#officeSearch').val();
        var selectedSpecialty = $('#specialtySearch').val();
        var filter = "#filterList .profile";
        var allPersons = $(filter);
        if (selectedOffice != "all")
        {
            filter += '[data-office="' + selectedOffice + '"]'
        }
        if (selectedSpecialty != "all")
        {
            filter += '[data-specialty="' + selectedSpecialty + '"]'
        }
        var $matching = allPersons.filter(filter);
        $(allPersons).not($matching).removeClass('out').fadeOut(500);
        $matching.removeClass('out').fadeIn(500);        
    }

    $("#officeSearch, #specialtySearch").on('change', onChange );
});

Update: http://jsfiddle.net/TrueBlueAussie/2u7NY/2/

The filter can be made slightly more efficient as "#filterList .profile" is not needed to filter allPersons based on attributes.

I also removed the function variable and placed the function inline on the change event.

$(document).ready(function () {
    $("#officeSearch, #specialtySearch").on('change',
        function () {
            var selectedOffice = $('#officeSearch').val();
            var selectedSpecialty = $('#specialtySearch').val();
            var allPersons = $("#filterList .profile");
            var filter = "";
            if (selectedOffice != "all") {
                filter = '[data-office="' + selectedOffice + '"]'
            }
            if (selectedSpecialty != "all") {
                filter += '[data-specialty="' + selectedSpecialty + '"]'
            }
            var $matching = allPersons.filter(filter);
            $(allPersons).not($matching).removeClass('out').fadeOut(500);
            $matching.removeClass('out').fadeIn(500);
        });
});

OK. Try something like this....

var match = function(office, specialty, profile) {
    var show = ((office == 'all' || office == $(profile).data('office')) &&
               (specialty == 'all' || specialty == $(profile).data('specialty')));

    if (show && !$(profile).is(':visible')) {
        $(profile).fadeIn();
    }

    if (!show && $(profile).is(':visible')) {
        $(profile).fadeOut();
    }
}

var filter = function() {
    var selectedOffice = $('#officeSearch').val();
    var selectedSpecialty = $('#specialtySearch').val();

    $.each($('#filterList .profile'), function(i, profile) {
        match(selectedOffice, selectedSpecialty, profile);
    });
};

$("#officeSearch").on('change', function(){
    filter();
});
$("#specialtySearch").on('change', function(){
    filter();
});

working fiddle here.... http://jsfiddle.net/6Q8FF/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM