0

I have code setup like on this fiddle but autocomplete isn't filtering results while typing.

jQuery(document).ready(function($) {

    var autocompleteTerms = JSON.parse( posts );

    $('#post-search').autocomplete({
        minLength: 2,
        source: function (request, response) {
            response($.map(autocompleteTerms, function (value, key) {
                return {
                    label: value.post_title,
                    value: value.ID
                }
            }));
        },
        focus: function(event, ui) {
            $('#post-search').val(ui.item.post_title);
            return false;
        },
        change: function (event, ui) {
            if (!ui.item) {
                $("#post-search").val('');
                $('#post-search-result').val('');
            }
        },
        select: function(event, ui) {
            $('#post-search').val(ui.item.label);
            $('#post-search-result').val(ui.item.value);
            return false;
        }
    });

});

This is part of the wordpress plugin and data to post variable is passed using

wp_localize_script('post-title-autocomplete', 'posts', [json_encode($results)]);

Do I need to incorporate this answer about Filter response in jQuery autocomplete in my code?

Maistrenko Vitalii
  • 994
  • 1
  • 8
  • 16
Moirae
  • 139
  • 3
  • 14
  • How is `posts` populated? You may want to `console.log(autocompleteTerms);` after you define it, this will ensure it has some value to it before you filter it. Also, if it were me, I would `$.each()` versus `$.map()`. – Twisty Apr 12 '18 at 20:13
  • Looking at your fiddle `data`, the index `post_title` does not exist. What are you trying to search against when a user types something in? First Name? Last Name? Both? – Twisty Apr 12 '18 at 20:19
  • @Twisty there is a line that says that data to posts var is passed using wp_localize_script, since this is used in WordPress. Code attached in post is done according to the fiddle, it is not identical. – Moirae Apr 12 '18 at 20:40
  • Right, but how does that get from the server variable to the client side JavaScript? – Twisty Apr 12 '18 at 20:41
  • 1
    @Twisty basically I query the data from the DB, and json_encode it. Then when using wp_localize_script('post-title-autocomplete', 'posts', [json_encode($results)]); it will create JS object posts and fill it with data (in my case json_encode part) – Moirae Apr 12 '18 at 20:50

2 Answers2

1

Try this. I have only added on key up listener after your autocomplete config and invoking the search when the key goes up.

jQuery(document).ready(function($) {

    var autocompleteTerms = JSON.parse( posts );

    $('#post-search').autocomplete({
        minLength: 2,
        source: function (request, response) {
            response($.map(autocompleteTerms, function (value, key) {
                return {
                    label: value.post_title,
                    value: value.ID
                }
            }));
        },
        focus: function(event, ui) {
            $('#post-search').val(ui.item.post_title);
            return false;
        },
        change: function (event, ui) {
            if (!ui.item) {
                $("#post-search").val('');
                $('#post-search-result').val('');
            }
        },
        select: function(event, ui) {
            $('#post-search').val(ui.item.label);
            $('#post-search-result').val(ui.item.value);
            return false;
        }
    });

    $('#post-search').on("keyup", function() {
        $(this).autocomplete( "search", $(this).val() );
    });

});

This is what I've added.

$('#post-search').on("keyup", function() {
    $(this).autocomplete( "search", $(this).val() );
});

Updated Fiddle you have posted: JSFiddle

  • Thank you both for your help. Answer from Jakub didn't work for me, but the one from @Twisty did fine – Moirae Apr 12 '18 at 20:53
1

Looking at your fiddle, I forked it and made a working example.

http://jsfiddle.net/Twisty/j3jLwwfm/5/

the way you are usinmg $.map(), you're just returning all the data with specific formatting. None of this gets filtered or adjusted to match what the user has entered. response() will get the entire data set and return it to the user every keystroke. You can adjust your function to match and filter results.

To fix this, you must iterate over each possible value and have an algorithm that will pick out the items you want to show as the results. As I commented, I would use $.each() like so:

source: function(request, response) {
  var r = [];
  var q = request.term.toLowerCase();
  $.each(data, function(k, v) {
    if (v.first_name.toLowerCase().indexOf(q) != -1) {
      r.push({
        label: v.first_name + " " + v.last_name,
        value: v.ID
      });
    }
  });
  response(r);
}

r is the result array. q is the users query. To make it ignore cases, I convert both the query and the data value to lower case. Using .indexOf() I can check to see if the query string is a part of the data value. the returned value will be -1 if query is not found and will be 0 or higher depending on the position of index it was found at.

If the query is "wi", then the result would be 0 and the value will be passed to the r. If the query was "ill", this would be done in the same way. You could adjust this to === 0 if you'd like to ensure that "wil" will hit on a name, but "il" will not hit on a result.

Hope this helps.

Twisty
  • 30,304
  • 2
  • 26
  • 45