Autocompleter

This is based on digitarald's excellent Autocompleter script. We've actually made enough changes to this for us to have refactored it so this code is not his library, but it's very, very close.

We've added two big things: JsonP support and multiple value support. We've added a few more options but these are less important. See our docs for details.

docs | svn

Autocompleter.Local.js

Using a local object already loaded:

Execute the script below and then type a letter into the input above.

new Autocompleter.Local($('local'), countries, {
  delay: 100,
  filterTokens: function() {
    var regex = new RegExp('^' + this.queryValue.escapeRegExp(), 'i');
    return this.tokens.filter(function(token){
      return (regex.test(token[0]) || regex.test(token[1]));
    });
  },
  injectChoice: function(choice) {
    var el = new Element('li')
      .setHTML(this.markQueryValue(choice[0]))
      .adopt(new Element('span', {'class': 'example-info'}).setHTML(this.markQueryValue(choice[1])));
    el.inputValue = choice[0];
    this.addChoiceEvents(el).injectInside(this.choices);
  }
});
execute this code

Autocompleter.Local, multiple

This is one of the things we added to the class, a "multi" option:

Execute the script below and then type a letter into the input above.

new Autocompleter.Local($('localmulti'), countries, {
  delay: 100,
  multi: true,
  filterTokens: function() {
    var regex = new RegExp('^' + (this.queryValue || '').escapeRegExp(), 'i');
    var filtered = this.tokens.filter(function(token){
      return (regex.test(token[0]) || regex.test(token[1]));
    });
    return filtered;
  },
  injectChoice: function(choice) {
    var el = new Element('li')
      .setHTML(this.markQueryValue(choice[0]))
      .adopt(new Element('span', {'class': 'example-info'}).setHTML(this.markQueryValue(choice[1])));
    el.inputValue = choice[0];
    this.addChoiceEvents(el).injectInside(this.choices);
  }
});
execute this code

Now, if you're doing to do multiple values it's far better to remove the entries from the field and instead inject them into another dom element to make a list. But if you want to support it within an input, you can.

Autcompleter.Remote.js

Autocompleter.Ajax.Json

This is the same as digitarald's example though it adds the option to allow multiple selections like all the examples here.

new Autocompleter.Ajax.Json($('ajaxJson'), 'server/auto.php' {
  postVar: 'query'
});

Autocompleter.Ajax.Xhtml

Again, the same as digitarald's example.

new Autocompleter.Ajax.Xhtml($('ajaxXhtml'), 'server/auto.php', {
  postData: {html: 1}, //some data to go along with the request
  //handle the data returned
  parseChoices: function(el) {
    var value = el.getFirst().innerHTML;
    el.inputValue = value;
    this.addChoiceEvents(el).getFirst().setHTML(this.markQueryValue(value));
  }
});

Autocompleter.JsonP.js

This adds support for our JsonP class. This example hits the CNET API and, because that data has a very esoteric format, I have to configure a lot of the class with code to handle that format. Here we also see two new options we've added: inheritWidth and dropDownWidth so that the results can be wider than the input.

Execute the script below and then type something like "ipod" into the input above.

new Autocompleter.JsonP($('jsonp'), 'http://api.cnet.com/restApi/v1.0/techProductSearch',
{
  jsonpOptions: {
    //this data gets added to the query string using JsonP's options
    data: {
      viewType: 'json',
      partKey: '19926949750937665684988687810562', //this is my code, user your own!
      iod:'none',
      start:0,
      results:10
    }
  },
	inheritWidth: false,
	dropDownWidth: 600,			
  //require at least a key stroke from the user
  minLength: 1,
  //this function filters the results based on the input
  filterResponse: function(resp) {
    //test it
    if(!choices || choices.length == 0) return [];
    //filter it and return it
    var regex = new RegExp('^' + (this.queryValue || '').escapeRegExp(), 'i');
    return choices.filter(function(choice){
      return (regex.test(choice.Name.$) || regex.test(choice['@id']));
    });
  },
  useSelection: false,
  //because the data returned has a unique structure, we must manage the parsing ourselves
  filterResponse: function(resp) {
    try {
      //this structure is unique to the CNET API
      choices = resp.CNETResponse.TechProducts.TechProduct;
      //test it
      if(!choices || choices.length == 0) return [];
      //filter it and return it
      return choices.filter(function(choice){
        return (choice.Name.$.test(this.getQueryValue(), 'i') || choice['@id'].test(this.getQueryValue()), 'i');
      }.bind(this));
    } catch(e){'filterResponse error: ', dbug.log(e)}
  },
  injectChoice: function(choice) {
    //again, the structure of these items is unique to the CNET API
    if(! choice.Name.$)return;
    var el = new Element('li')
      .setHTML(this.markQueryValue(choice.Name.$))
      .adopt(new Element('span', {'class': 'example-info'}).setHTML(this.markQueryValue(choice['@id'])));
    el.inputValue = choice.Name.$+' ('+choice['@id']+')';
    this.addChoiceEvents(el).injectInside(this.choices);
  }
});
execute this code

cnet-libraries/06-3rdpartycode/autocompleter.txt · Last modified: 2007/06/15 10:24 by aaron-n

On this page:

Page index