Combine javascript functions to work together

Tags: , ,



I am building a search form that filters the results based on the a text input as well as select options from four separate drop-downs (category, sub-category, location, etc).

The following two functions work well, but I just realized that if I type a search term in the input, make my drop-down selections and then go back and type a different search term, my drop-downs are ignored.

I’ve found solutions for similar problems across this site, but nothing that pertains to my particular situation.

This is the filter for the drop-downs:

$("select.filterby").change(function(){
    var filters = $.map($("select.filterby").toArray(), function(e){
        return $(e).val();
    }).join(".");

    $("div#flatdiv").find("article").hide();
    $("div#flatdiv").find("article." + filters).show();
});

and Here is the one the filters based on the search input:

$(document).ready(function(){
    $("#title").on("keyup", function() {
        var value = $(this).val().toLowerCase();
        $("#flatdiv article").filter(function() {

            $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
        });
   });
});

One is using true .filter() and the other is using .find to show() and hide().

I’m not sure where to go from here. I’ve made various attempts but each results in neither working so I’m hoping someone can help me out.

UPDATE: Here is the final that ended up working beautifully!

//apply selection form any drop down forms
$("select.filterby").change(function(){
   var filters = $.map($("select.filterby").toArray(), function(e){
      return $(e).val();
   }).join(".");
   $("div#flatdiv").find("article").addClass("hidden-by-category-filter");
   $("div#flatdiv").find("article." + filters).removeClass("hidden-by-category-filter");
});

//apply text input from search form
$("#title").blur(function(){
   var textFilters = $(this).val().toLowerCase();
   $("article:contains(" + textFilters +")").removeClass("hidden-by-text-filter");
   $("article:not(:contains(" + textFilters +"))").addClass("hidden-by-text-filter");
});

Answer

In such cases, instead of using .hide() and .show(), it is often better to just add CSS classes to elements to hide them.

I would create classes such as .hidden-by-text-filter and .hidden-by-category-filter, each would individually hide the elements:

.hidden-by-text-filter, .hidden-by-category-filter {
    display: none;
}

Then in the event handler just add or remove a specific class. For example, the event handler on text input would add/remove the class .hidden-by-text-filter, while the category drop-down would add/remove the class .hidden-by-category-filter.

$("select.filterby").change(function() {
  var filters = $.map($("select.filterby").toArray(), function(e) {
    return $(e).val();
  }).join(".");

  $("div#flatdiv").find("article").addClass(".hidden-by-text-filter");
  $("div#flatdiv").find("article." + filters).removeClass(".hidden-by-text-filter");
});

This way both those filters wouldn’t interfere with each other. If an element is meant to be hidden through both criteria, it would have both those classes, and still remain hidden. If one such element is made visible by one of the filters, it would still have the other class, and will remain hidden.



Source: stackoverflow