0

I'm setting up an autocomplete form in which I need that every keyword/term is matched.

I'm using an ajax callback to get my results list and I tried many workarounds to convert json results to a autocomplete-capable array but I couldn't get it to work.


        $(this).autocomplete({
            source: function (request, response) {
            $.ajax({
                 url: 'autocomplete.php',
                 data: request.term,
                 dataType: "json",
                 success: function (data) { 
                    var dataArray = [];

                    for(var i in data)
                        dataArray.push(data[i]);

                    var matchArray = dataArray.slice();
                    var srchTerms   = $.trim (request.term).split (/\s+/);
                    $.each (srchTerms, function (J, term) {
                        var regX    = new RegExp (term, "i");
                        matchArray   = $.map (matchArray, function (item) {
                            return regX.test (item)  ?  item  : null; 
                        } );
                    } );

                    response(matchArray);

                 },
                 error: function () {
                     response([]);
                 }
             });
            },
            autoFocus: true
         });

I think the code itself is working because if I push a normal javascript array it works just fine but as long as I get results from ajax and convert it to a javascript array, it doesn't work anymore.

What I trying to get is that if a given results is equal to "example book title", it should pop up even if my keywords are "example title" or "title book example" etc...

demetriomontalto
  • 111
  • 1
  • 1
  • 11
  • I would recommend to debug this, as we don't know whar you are getting back. Put a 'debugger' word on top of your success function, open devtools (F12) and run the code. It will stop there and you will be able to investigate your response and will allow to walk through the code to see the issue – arnuga3 Jul 10 '19 at 18:20
  • What do you mean by "put a debugger word"? I tried to `console.log` the `dataArray` right after the `for` cycle and it showed up like I wanted to, just like a normal js array so `['sentence 1', 'sentence 2', 'sentence 3']` but still not working. – demetriomontalto Jul 10 '19 at 18:24
  • Where is `q` defined? Why not use `request.term`? – Twisty Jul 10 '19 at 18:40
  • Please provide a Minimal, Reproducible Example: https://stackoverflow.com/help/minimal-reproducible-example including an example of the results your PHP is sending back. – Twisty Jul 10 '19 at 18:42
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger Hopefully, that will help you find your issue – arnuga3 Jul 10 '19 at 18:46
  • Sorry `q` was a typo, the code is correctly working when feeded with a javascript array but not when the ajax call is turned into an array, php is returning a clean and correct json encoded data like this `{"0":"title one","1":"title two","2":"title three"}` – demetriomontalto Jul 10 '19 at 19:10
  • This (https://codepen.io/anon/pen/xoMjvJ) is a working codepen of the code with js array, I just need to integrate it prorperly with the ajax callback result. – demetriomontalto Jul 10 '19 at 19:19
  • @demetriomontalto the codepen makes a bit more sense yet it's still not clear what you want to have happen. If the user entered "win heart" what type of results are you expecting? – Twisty Jul 10 '19 at 21:22
  • what I want is exactly what the codepen does but I need to get results from ajax and not from a simple array, I can't get this to work – demetriomontalto Jul 11 '19 at 11:49

1 Answers1

0

Based on your description, if the user enters multiple words, you want it to show the results for each of the searches for each of those words. For example, if the user enters "hot air", results would include all the results for "hot" and all the results for "air".

Consider the following example.

$(function() {
  var availableTags = [
    "win the day",
    "win the heart of",
    "win the heart of someone"
  ];

  $("#tags").autocomplete({
    source: function(req, resp) {
      // Trim Query and split by " " (Space)
      var srchTerms = req.term.trim().split(" ");
      // Prepare result Arrays
      var results = [],
        uniqueResults = [];
      // Iterate each search term and combine the results into one array
      $.each(srchTerms, function(i, t) {
        results = results.concat($.ui.autocomplete.filter(availableTags, t));
      });
      // Remove duplicates by iterating each result item
      $.each(results, function(i, r) {
        if ($.inArray(r, uniqueResults) === -1) uniqueResults.push(r);
      });
      // Send back to Autocomplete
      resp(uniqueResults);
    }
  });
});
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="demo">
  <div class="ui-widget">
    <label for="tags">Multi-word search: </label>
    <input id="tags">
  </div>
</div>

If the user enters "win" or "win ", it will still hit the source data. If the user enters "win heart", it will filter the source data for both terms individually, combining all the results into one array. There will likely be duplicates. In the steps, we can filter those duplicates out and send the resulting array back.

In your code, you will want send each search term to PHP, which should return an Array or an Array of Objects. In the same way you'll collect all the results into one array and then filter.

Alternatively, you can do all the work on the PHP Side, send the entire chunk to PHP and have it perform the search and filtering (potentially faster) and return all the results.

Update

If all you want to do is get the array via ajax, review the following:

function (request, response) {
  $.getJSON("autocomplete.php", {term: request.term}, function(data){
    var matchArray = [];
    $.each(data, function(key, val){
      matchArray.push(val);
    });
    var srchTerms = $.trim(request.term).split(/\s+/);

    $.each (srchTerms, function (J, term) {
      var regX = new RegExp (term, "i");
      matchArray = $.map (matchArray, function (item) {
        return (regX.test(item) ?  item : null);
      });
    });
    response (matchArray);
  });
}

This assumes that PHP will return JSON Data that is an array of results. Since you have not provided an example of the results nor a snippet of your PHP, it's hard to help further.

Hope this helps.

Twisty
  • 30,304
  • 2
  • 26
  • 45
  • thank you for your answer, but the codepen I posted is actually what I need! I need what the codepen does but I have to get results from ajax and not from a simple array. I just can't integrate ajax with the codepen example, does this makes sense? – demetriomontalto Jul 11 '19 at 11:44
  • @demetriomontalto I updated my answer yet I am not sure if it will help you much. – Twisty Jul 11 '19 at 15:18
  • it doesn't work because autocomplete apparently require a js array, and what I get is a json object, in the original question I tried to loop thorugh the json object and push results in a normal array which creates a good array if I dump it, but apparently no luck – demetriomontalto Jul 11 '19 at 15:49
  • @demetriomontalto Autocomplete can accept an Array or an Object, but it does require the right indexes: `{ label, value }`. Using `$.getJOSN()`, it will accept JOSN from PHP and make it an Object for JS. Again, if you include an example of what is returned by PHP, it would help everyone help you. – Twisty Jul 11 '19 at 16:59
  • php returns a `json_encode`d array of strings, for example `{"0":"title one","1":"title two","2":"title three"}` – demetriomontalto Jul 11 '19 at 18:20
  • @demetriomontalto that looks like an Object, not an Array. So `data.0` instead to access it. You may want to edit your post and include the content of your PHP. – Twisty Jul 11 '19 at 18:50
  • @demetriomontalto my mistake, it would be `data['0']`. I don't recall if dot notation works with numerical indexes like that. And I think you'd want to iterate iover each part and populate it into an Array for later use. Will add to my update. https://stackoverflow.com/questions/39336556/how-can-i-slice-an-object-in-javascript – Twisty Jul 12 '19 at 19:57
  • Actually I’m doing it in my main example, as you can see I’m pushing data’s into dataArray, and logged it looks okay, but it won’t work for mixed words, just inline ones – demetriomontalto Jul 13 '19 at 06:56
  • @demetriomontalto I have requested that you update the case with a proper example a number of times. Am unable to assist further until you do that. – Twisty Jul 16 '19 at 16:33