Skip to main content
Ajax Autocomplete

Ajax Autocomplete Customization for Textfield in Drupal

Autocomplete is a feature for textfields in Drupal. It provides a dropdown list of matching options from the server. It is implemented through AJAX. To know how to add an autocomplete form element in Drupal visit https://www.drupal.org/node/854216

 

For customizing autocomplete we need to override the Drupal system file "misc/autocomplete.js". This can be achieved ideally in two ways:

  • Replace the entire "autocomplete.js" with your customised version

    function MY_MODULE_js_alter(&$javascript) {
      $javascript['misc/autocomplete.js']['data'] = drupal_get_path('module', 'MY_MODULE') . '/js/autocomplete.js';
    }
  • Override "Drupal.ACDB.prototype.search" with a custom behaviour in theme script.js or module js file, as long as it's added after /misc/autocomplete.js it will override it.

    /** * Performs a cached and delayed search. */
    Drupal.ACDB.prototype.search = function (searchString) {
      var db = this;
      this.searchString = searchString;
      // See if this string needs to be searched for anyway.
      searchString = searchString.replace(/^\s+|\s+$/, '');
      if (searchString.length <= 0 || searchString.charAt(searchString.length - 1) == ',') {
        return; 
      }
      // See if this key has been searched for before.
      if (this.cache[searchString]) {
        return this.owner.found(this.cache[searchString]);
      }
      // Initiate delayed search.
      if (this.timer) {
        clearTimeout(this.timer);
      }
      this.timer = setTimeout(function () {
        db.owner.setStatus('begin');
        // Ajax GET request for autocompletion. We use Drupal.encodePath instead of // encodeURIComponent to allow autocomplete search terms to contain slashes.
        $.ajax({
          type: 'GET',
          url: db.uri + '/' + Drupal.encodePath(searchString),
          dataType: 'json',
          success: function (matches) {
            if (typeof matches.status == 'undefined' || matches.status != 0) {
              db.cache[searchString] = matches;
              // Verify if these are still the matches the user wants to see.
              if (db.searchString == searchString) {
                db.owner.found(matches);
              }
              db.owner.setStatus('found');
            }
          },
          error: function (xmlhttp) {
            alert(Drupal.ajaxError(xmlhttp, db.uri));
          }
        });
      }, this.delay); 
    };

Now we tweak the traits of autocomplete one by one:

  1. Disabling Cache - Sometimes you might want to disable caching for autocomplete, to make it bring updated data.

    i. Remove or comment out this line, which caches the search string

    db.cache[searchString] = matches;

    ii. Flush cache

    jQuery("#autocomplete_ElementName").result(function() {
      jQuery("#autocomplete_ElementName").flushCache(); 
    });
  2. Enforcing minimum number of characters for autocomplete

    Substitute "Min" here with your preferred number of characters

    if (searchString.length < Min || searchString.charAt(searchString.length - 1) == ',')
  3. Increasing/Decreasing autocomplete timeout

    Add "this.delay = 400;" anywhere above timeout function for the prototype (400 milliseconds delay). If the delay value was very low, the cache values are stored for every substring. For example, if you type "abcd" the results of [a][ab][abc][abcd] will be cached !

    this.delay = 'time_in_milliseconds';
  4. Resolving cross domain problem

    Change the ajax dataType from "json" to "jsonp"

    dataType: 'jsonp',
  5. Passing more parameters in search string

    searchString = searchString + "/" + $("#otherfield").val();

 

Comments

Leo (not verified)

Fri, 12/05/2014 - 08:01

On #1 where should I place this code:
jQuery("#autocomplete_ElementName").result(function() {
jQuery("#autocomplete_ElementName").flushCache();
});