2

I am using jQuery UI autocomplete for a city search on my site. It starts to search after the user has entered 3 characters.

I'm wondering how to change this script to abort the last query if the user continues typing.

function enableCitiesAutocomplete() {
    var url = LIST.urls.api_cities_search;

    $('#txt_search_city').autocomplete({
        source: url,
        minLength: 3,
        select: function( event, ui ) {
            $(this).val( ui.item.value );
            $( "#id_city" ).val( ui.item.id );
            $(this).closest('form').submit();
        }
    });
}
Andrew Whitaker
  • 119,029
  • 30
  • 276
  • 297
Brenden
  • 6,473
  • 14
  • 39
  • 70
  • If you abort the query, then there will be no result for the autocomplete to show. You want to wail till the user stops typing then render result? – Paul Feb 08 '12 at 01:40
  • Basically, I want it to abort a last query if a new query is sent. So for instance, if they pause while typing and it sends a query, and then they keep typing, I'd like the previous query to abort – Brenden Feb 08 '12 at 01:45
  • Does this question help you at all? http://stackoverflow.com/q/9040929/497356 – Andrew Whitaker Feb 08 '12 at 03:15
  • Also, aborting of XHR should already occur. See [these lines](https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.autocomplete.js#L310) of the source. This has been implemented since at least 1.8.5. – Andrew Whitaker Feb 08 '12 at 03:53

1 Answers1

1

I don't know if you can "abort" a completion that has already begun. But you may be able to get what you want by interrupting the render part of the autocomplete. This might work if the autocomplete consists of a query and a render, and the query involves a network transaction.
If there's a query and a render, and the query is just a search through a locally-stored list, then this probably won't work, because the latency is too low.

This SO question describes how to monkey-patch the renderMenu and renderItem fns in the jQuery autocomplete package. I'm thinking you can use the same monkey-patch approach.

You'd need to specify, as the source, a function, not a URL. This SO question describes how. Then, in that function, increment a count variable that says "a search is in process". Then perform the search by doing an "ajax get". Also patch the renderMenu to (a) only render if a single search is in process, and (b) decrement the search count.

It will probably look something like this:

var queriesInProcess = 0;
var ac = $('#txt_search_city').autocomplete({ 
    minLength: 3, 
    select : .... ,
    // The source option can be a function that performs the search, 
    // and calls a response function with the matched entries. 
    source: function(req, responseFn) { 
        var url = baseUrl + req.term;
        queriesInProcess++;
        $.ajax({
          url: url,
          //data: data,
          success: function(json,xhr) {
              queriesInProcess--;
              var a = ....retrieve from the json .... 
              responseFn( a ); 
            },
            errpr : function () { queriesInProcess--; },
          dataType: 'json'
        });
    } 
}); 

ac.data( "autocomplete" )._renderMenu = function( ul, items ) { 
  if (queriesInProcess > 0) return; 
  var self = this; 
  $.each( items, function( index, item ) { 
    self._renderItem( ul, item ); 
  }); 
}; 

If you want to get more sophisticated, you can also try to abort the pending ajax request. This would need to happen in the source function; you'd need to cache/stash the XHR returned from the $.ajax() call, and call abort() when a new one comes through.

Community
  • 1
  • 1
Cheeso
  • 180,104
  • 92
  • 446
  • 681