blog-banner

Ajax Autocomplete Customization for Textfield in Drupal

  • Ajax Cache
  • Autocomplete
  • Drupal Planet

Ajax Autocomplete Customization 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 customized 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 behavior 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 autocompleteSubstitute "Min" here with your preferred number of characters
    if (searchString.length < Min || searchString.charAt(searchString.length - 1) == ',')
  3. Increasing/Decreasing autocomplete timeout adds "this.delay = 400;" anywhere above the 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 problemChange the ajax dataType from "json" to "jsonp"
    dataType: 'jsonp',
  5. Passing more parameters in search string
    searchString = searchString + "/" + $("#otherfield").val();

 

Get awesome tech content in your inbox