imbagila
imbagila

Reputation: 513

How to get jQuery live search in javascript array more accurate?

I want to make live search using jQuery AJAX and PHP, with one input textbox as the filter of the data. So on the background I have JSON data like this:

[
    ["1","Your Name 1","button_field"],
    ["2","Your Name 2","button_field"],
    ["3","Your Name 3","button_field"]
]

This is my jQuery code, for the live search when user start typing on the textbox:

$('input[name="search_value"]').on('keydown', function() {
    $.ajax({
        url: 'http://localhost/myapp/ajax/get',
        type: 'GET',
        dataType: 'json',
        success: function(data) {
            var search = $('input[name="search_value"]').val();
            var output = '';

            for (i = 0; i < data.length; i++) {
                if (($.inArray(search, data[i]) !== -1) || (search === '')) {
                    output += '<tr>';

                    for (j = 0; j < data[i].length; j++) {
                        output += '<td>' + data[i][j] + '</td>';
                    }

                    output += '</tr>';
                }
            }

            $('.table-data > table > tbody').html(output);
        }
    });
});

I try to using search, by typing Your Name 2, and it works. But when I try to typing your name 2 (no uppercase for each first word) and try to typing our name 2 (with missing y), the result is not shown.

And my question is : How to make the search results is ignoring the uppercase (make case insensitive) and start showing the data even the search value is incomplete ? Thanks for all your answers :)

Upvotes: 0

Views: 1840

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074268

It sounds like you want a case-insensitive substring match. If so, $.inArray isn't the right tool.

I'd use Array#some for this. First I'd modify the line getting search to get it in lower case:

var search = $('input[name="search_value"]').val().toLowerCase();

Then when you're checking to see if data[i] contains it:

if (!search || data[i].some(function(entry) { return entry.toLowerCase().indexOf(search) != -1; })) {

Array#some calls the callback you give it once for each entry in the array until the callback returns a truthy value (in which case it stops). some returns true if the callback ever returns a truthy value, or false if it gets through the entire array without that ever happening.

That looks a bit better in ES2015, thanks to the arrow function and String#includes:

if (!search || data[i].some(entry => entry.toLowerCase().includes(search))) {

Live Example:

$('input[name="search_value"]').on('input', function() {
  // setTimeout to simulate ajax
  setTimeout(function() {
    var data = [
      ["1","Your Name 1","button_field"],
      ["2","Your Name 2","button_field"],
      ["3","Your Name 3","button_field"]
    ];
    var search = $('input[name="search_value"]').val().toLowerCase();
    var output = '';

    for (var i = 0; i < data.length; i++) {
      if (!search || data[i].some(function(entry) { return entry.toLowerCase().indexOf(search) != -1; })) {
        output += '<tr>';

        for (j = 0; j < data[i].length; j++) {
          output += '<td>' + data[i][j] + '</td>';
        }

        output += '</tr>';
      }
    }

    $('.table-data > table > tbody').html(output);
  });
});
<input type="text" name="search_value">
<div class="table-data">
  <table>
    <tbody>
    </tbody>
  </table>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Two other notes, both fixed it the example above:

  • I'd use input, not keydown, so you respond to all inputs (including pasting)
  • Your code is falling prety to The Horror of Implicit Globals.¹ Declare your variables (i in this case). :-)

¹ That's a post on my anemic little blog.

Upvotes: 2

Related Questions