BlueDogRanch
BlueDogRanch

Reputation: 536

Why doesn't addClass show and hide the element as expected?

What are the differences in hide(), show() and .addClass in these two examples, and why does .addClass not work in the second example?

These two examples are simple jQuery search functions that use :contain to find the search terms in the .record divs.

This example works with hide() and show().

$(document).ready(function() {
  $('#search').keyup(function() {

    var text = $(this).val().toLowerCase();

    $('.record').hide();

    $('.record').each(function() {

      if ($(this).text().toLowerCase().indexOf("" + text + "") != -1) {
        $(this).closest('.record').show();
      }
    });
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Search <input type='text' id='search' placeholder='Search Text'>

<br /><br />

<div class="record">Now is the time for all good men to come to the aid of their city</div>
<div class="record">Now is the time for all good women to come to the aid of their country</div>
<div class="record">Now is the time for all droids to come to the aid of their universe</div>
<div class="record">Now is the time for all fluffy bears to come to the aid of their wilderness</div>
<div class="record">Now is the time for all short people to come to the aid of their county</div>

But what I need to do in the example below is

  1. use the classes .display-none and .display-block, rather than hide() and show(), as I am using hide() and show() in another Javascript function with the same .reason html markup.

  2. Unlike the above example, initially display:none all the .record divs, so they are hidden and only shown with display:block when they are actually search results.

$(document).ready(function() {
  $('#search').keyup(function() {

    var text = $(this).val().toLowerCase();

    $('.record').addClass("display-none");

    $('.record').each(function() {

      if ($(this).text().toLowerCase().indexOf("" + text + "") != -1) {
        $(this).closest('.record').addClass("display-block");
      }
    });
  });
});
.display-block {
  display: block !important;
}

.display-none {
  display: none !important;
}

.record {
  display: none !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Search <input type='text' id='search' placeholder='Search Text'>

<br /><br />

<div class="record">Now is the time for all good men to come to the aid of their city</div>
<div class="record">Now is the time for all good women to come to the aid of their country</div>
<div class="record">Now is the time for all droids to come to the aid of their universe</div>
<div class="record">Now is the time for all fluffy bears to come to the aid of their wilderness</div>
<div class="record">Now is the time for all short people to come to the aid of their county</div>

Upvotes: 0

Views: 834

Answers (3)

Kinglish
Kinglish

Reputation: 23664

As mentioned, you are not removing a class which has an !important modifier tacked onto it. In fact, all your classes (here) do, which is going to be a headache as your application grows. All those !important rules can get messy. Here's a simplification: Instead of show() and hide() you can simply use a toggle(evaluation)

https://api.jquery.com/toggle/

$(document).ready(function() {
  $('#search').keyup(function() {
      let val = $(this).val().toLowerCase();
      $('.record').each(function() {
          $(this).toggle(val != '' && $(this).text().toLowerCase().indexOf(val) > -1)
      });
  });
});
.record {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Search <input type='text' id='search' placeholder='Search Text'>

<br /><br />

<div class="record">Now is the time for all good men to come to the aid of their city</div>
<div class="record">Now is the time for all good women to come to the aid of their country</div>
<div class="record">Now is the time for all droids to come to the aid of their universe</div>
<div class="record">Now is the time for all fluffy bears to come to the aid of their wilderness</div>
<div class="record">Now is the time for all short people to come to the aid of their county</div>

Upvotes: 1

epascarello
epascarello

Reputation: 207527

Look at this small example of what you are running into. You have multiple classes being applied to each other with the same CSS specificity

.three { color: red; }
.two { color: yellow; }
.one { color: blue; }


.one { background-color: green; }
.two { background-color: black; }
.three { background-color: silver; }
<div class="one two three">one two three</div>
<div class="one two">one two</div>
<div class="one">one</div>

So when the rules all have the same specificity. The last one in the list wins. Since the last one is display none, they are all hidden.

You are also using closest when there is no need. You are on the record so no bother to look it up again.

Change your code to add one class to hide the element. Make the specificity higher so you do not have to deal with important.

$(document).ready(function() {
  $('#search').keyup(function() {
    var text = $(this).val().trim().toLowerCase();
    $('.record.display-block').removeClass("display-block");
    if (!text.length) return;
    $('.record').each(function() {
      if ($(this).text().toLowerCase().includes(text)) {
        $(this).addClass("display-block");
      }
    });
  });
});
.record.display-block {
  display: block;
}

.record {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Search <input type='text' id='search' placeholder='Search Text'>

<br /><br />

<div class="record">Now is the time for all good men to come to the aid of their city</div>
<div class="record">Now is the time for all good women to come to the aid of their country</div>
<div class="record">Now is the time for all droids to come to the aid of their universe</div>
<div class="record">Now is the time for all fluffy bears to come to the aid of their wilderness</div>
<div class="record">Now is the time for all short people to come to the aid of their county</div>

Upvotes: 1

user8539669
user8539669

Reputation: 104

It looks like you're conflating different kinds of things.

show() and hide() are JS functions. You can say: show everything where the search string is found.

.show-results and .hide-results are HTML classes. You can say: add show-results to everything where the search string is found, and define the class show-results with the style display: block.

display:none is a CSS style. You can say: apply this style to everything where the search string is not found.

Upvotes: 0

Related Questions