TextboxList meets Autocompletion

TextboxList Autocompletion

Demo here

In my previous blogpost I explained how to extend TextboxList to add closing functionality via a link added to each box. But it was missing an important ingredient: autocompletion!

Again, all we have to do is extend the TextboxList class, override some methods, some events, and create some new ones (all prefixed by auto)

Click here to see Javascript code

  1. var FacebookList = new Class({
  2.  
  3. Extends: TextboxList,
  4.  
  5. data: [],
  6.  
  7. options: {
  8. onInputFocus: function() { this.autoShow(); },
  9. onInputBlur: function(el) {
  10. el.value = '';
  11. this.autoHide();
  12. },
  13. onBoxDispose: function(item) {
  14. this.autoFeed(item.$attributes.$text);
  15. },
  16. autocomplete: {
  17. 'opacity': 0.8,
  18. 'maxresults': 10,
  19. 'minchars': 1
  20. }
  21. },
  22.  
  23. initialize: function(element, autoholder, options) {
  24. arguments.callee.parent(element, options);
  25. this.autoholder = $(autoholder).set('opacity', this.options.autocomplete.opacity);
  26. this.autoresults = this.autoholder.getElement('ul');
  27. var children = this.autoresults.getElements('li');
  28. children.each(function(el) { this.add(el.innerHTML); }, this);
  29. },
  30.  
  31. autoShow: function(search) {
  32. this.autoholder.setStyle('display', 'block');
  33. this.autoholder.getElements('*').setStyle('display', 'none');
  34. if(! search || ! search.trim() || (! search.length || search.length < this.options.autocomplete.minchars ))
  35. {
  36. this.autoholder.getElement('.default').setStyle('display', 'block');
  37. this.resultsshown = false;
  38. } else {
  39. this.resultsshown = true;
  40. this.autoresults.setStyle('display', 'block').empty();
  41. this.data.filter(function(str) { return str ? str.test(search, 'i') : false; }).each(function(result, ti) {
  42. if(ti >= this.options.autocomplete.maxresults) return;
  43. var el = new Element('li').set('html', this.autoHighlight(result, search)).inject(this.autoresults);
  44. el.$attributes.$result = result;
  45. if(ti == 0) this.autoFocus(el);
  46. }, this);
  47. }
  48. },
  49.  
  50. autoHighlight: function(html, highlight) {
  51. return html.replace(new RegExp(highlight, 'gi'), function(match) {
  52. return '<em>' + match + '</em>';
  53. });
  54. },
  55.  
  56. autoHide: function() {
  57. this.resultsshown = false;
  58. this.autoholder.setStyle('display', 'none');
  59. },
  60.  
  61. autoFocus: function(el) {
  62. if(! el) return;
  63. if(this.autocurrent) this.autocurrent.removeClass('auto-focus');
  64. this.autocurrent = el.addClass('auto-focus');
  65. },
  66.  
  67. autoMove: function(direction) {
  68. if(!this.resultsshown) return;
  69. this.autoFocus(this.autocurrent['get' + (direction == 'up' ? 'Previous' : 'Next')]());
  70. },
  71.  
  72. autoFeed: function(text) {
  73. if(this.data.indexOf(text) == -1)
  74. this.data.push(text);
  75. },
  76.  
  77. autoAdd: function(el) {
  78. if(!el || ! el.$attributes.$result) return;
  79. this.add(el.$attributes.$result);
  80. delete this.data[this.data.indexOf(el.$attributes.$result)];
  81. this.autoHide();
  82. this.current.$attributes.$input.value = '';
  83. },
  84.  
  85. createInput: function(options) {
  86. var li = arguments.callee.parent(options);
  87. var input = li.$attributes.$input;
  88. input.addEvents({
  89. 'keydown': function(e) {
  90. e = new Event(e);
  91. this.dosearch = false;
  92. switch(e.code) {
  93. case Event.Keys.up: return this.autoMove('up');
  94. case Event.Keys.down: return this.autoMove('down');
  95. case Event.Keys.enter:
  96. this.autoAdd(this.autocurrent);
  97. this.autocurrent = false;
  98. this.autoenter = true;
  99. break;
  100. default: this.dosearch = true;
  101. }
  102. }.bind(this),
  103. 'keyup': function() {
  104. if(this.dosearch) this.autoShow(input.value);
  105. }.bind(this)
  106. });
  107. input.addEvent(Browser.Engine.trident ? 'keydown' : 'keypress', function(e) {
  108. if(this.autoenter) new Event(e).stop();
  109. this.autoenter = false;
  110. }.bind(this));
  111. return li;
  112. },
  113.  
  114. createBox: function(text, options) {
  115. var li = arguments.callee.parent(text, options);
  116. li.addEvents({
  117. 'mouseenter': function() { this.addClass('bit-hover') },
  118. 'mouseleave': function() { this.removeClass('bit-hover') }
  119. });
  120. li.adopt(new Element('a', {
  121. 'href': '#',
  122. 'class': 'closebutton',
  123. 'events': {
  124. 'click': function(e) {
  125. new Event(e).stop();
  126. if(! this.current) this.focus(this.maininput);
  127. this.dispose(li);
  128. }.bind(this)
  129. }
  130. }));
  131. li.$attributes.$text = text;
  132. return li;
  133. }
  134.  
  135. });
  136.  
  137. window.addEvent('domready', function() {
  138. // init
  139. var tlist2 = new FacebookList('facebook-demo', 'facebook-auto');
  140.  
  141. // fetch and feed
  142. new Request.JSON({'url': 'json.html', 'onComplete': function(j) {
  143. j.each(tlist2.autoFeed, tlist2);
  144. }}).send();
  145. });

It works by caching all the results from a JSON Request and feeding them to the autocompleter object. When a item is added as a box, it’ removed from the feed array, and when the box is disposed it’s added back, so that it becomes available in the list when the user types.

Another new feature is that you’ll be able to let it add boxes from the HTML directly:

Click here to see HTML code

  1. <label>FacebookList input</label>
  2. <input type="text" value="" id="facebook-demo" />
  3. <div id="facebook-auto">
  4. <div class="default">Type the name of an argentine writer you like</div>
  5. <ul class="feed">
  6. <li>Jorge Luis Borges</li>
  7. <li>Julio Cortazar</li>
  8. </ul>
  9. </div>

The constructor now takes new parameters to configure the autocompletion, like the minimum number of characters to trigger the dropdown, and more.

Changelog

  • 0.1: initial release
  • 0.2: added click support, removed $attributes use, code cleanup

Download

Click here to download the zip with code and examples

118 Responses to “TextboxList meets Autocompletion”

Pages: « 8 7 [6] 5 4 3 2 1 » Show All

  1. 90
    Pablo Rey Says:

    nice and usefull ;)

  2. 89
    Pablo Rey Says:

    loco, no se cuanto sabes de ajax… pero me parece que de literatura argentina sabes bastante ;)

  3. 88
    Delapouite Says:

    Here is an example code to put in the domready :

    window.addEvent(’domready’, function() {

    var tlist2 = new FacebookList(’facebook-demo’, ‘facebook-auto’);

    // fetch and feed
    new Request.JSON({’url’: ‘json.html’, ‘onComplete’: function(j) {
    j.each(tlist2.autoFeed, tlist2);
    }}).send();

    $(’facebook-form’).addEvent(’submit’, function(){ //facebook-form is the form id
    tlist2.update();
    })
    });

    One problem remaining on IE :
    pressing enter while the autocomplete list opened submit the form instead of just adding the list item like the Fx / Opera behavior

  4. 87
    Will Says:

    I’m with JP. I’m not sure where to put the update function. So if someone could explain it that would great!

    Thanks.

  5. 86
    JP! Says:

    after several hours of fustration i figured it out ! (Using ninja’s method) but it was even easier. I left the update function as is!

    // Like ninja said. Placing tlist2 outside the addEvent.
    var tlist2 = BandsList;

    window.addEvent(’domready’, function() {

    tlist2 = new BandsList(’bands’, ‘bands-auto’);

    // fetch and feed
    new Request.JSON({’url’: ‘json.php’, ‘onComplete’: function(j) {
    j.each(tlist2.autoFeed, tlist2);
    }}).send();
    });

    //// === in the HTML form ==== ///
    <input type=”submit” onClick=”javascript:tlist2.update();” value=”Submit” />

  6. 85
    JP! Says:

    after several hours of fustration i figured it out ! (Using ninja’s method) but it was even easier. I left the update function as is!

    // Like ninja said. Placing tlist2 outside the addEvent.
    var tlist2 = BandsList;

    window.addEvent(’domready’, function() {

    tlist2 = new BandsList(’bands’, ‘bands-auto’);

    // fetch and feed
    new Request.JSON({’url’: ‘json.php’, ‘onComplete’: function(j) {
    j.each(tlist2.autoFeed, tlist2);
    }}).send();
    });

    //// === in the HTML form ==== ///

  7. 84
    JP! Says:

    Hello everyone!

    Where do i put the update() function!? People say they figured it out but don’t post the solution!

  8. 83
    Korayem Says:

    Oppps..ditch that asp.net part in my comment, it was a stupid copy paste error….

    Thanks for sharing, this is super cool

  9. 82
    Korayem Says:

    mega slick…loong live ASP.NET

  10. 81
    NextMint Says:

    Hi,
    Could anybody post a working example of how to get the data posted? What needs to be changed, and where?

    Many thanks

  11. 80
    Fusion Says:

    Hi. This is wonderful stuff. I’ve used this in one of my projects and has proved a great success. But like everything, it has some issues. Here’s what it is..
    I’m updating the dropdown list, i.e. fetchfile on every keyword selection. e.g. If i search abc and get 10 results. I select one of them. Then i search again (type again). Now i’m making a new JSONString which returns say 2 results. But my drop down is showing 9 keywords options.
    In short, the issue is i want to update the drop down list on every hit. The JSONString i’m returning is updated but the drop down list is not..
    can the authors or anyone else please help me out on this.. Kinda urgent matter.
    Many thanks.

  12. 79
    ulas Says:

    i made my own list for autocomplete, but i want that box be empty at first - how can i ?

  13. 78
    Magus Creo » Blog Archive » People Searchin’ Says:

    [...] YUI Autocomplete AJAX Select Drowdown with ID AutoCompleter Tutorial - jQuery(Ajax)/PHP/MySQL Yahoo! AutoComplete jQuery Autocomplete Mod FaceBoox style autosuggest with jQuery Implementing AJAX Suggest and Autocomplete Ajax autosuggest/autocomplete from database Ajax Auto Suggest v.2 Facebook List TextboxList with AutoCompletion Proto!MultiSelect 0.2 TextboxList meets Autocompletion [...]

  14. 77
    facebook textboxlist — award tour Says:

    [...] Facebook TextboxList with Autocompletion. that’s a pretty good trick of having the input box inside a fake input box. [...]

  15. 76
    Mark Says:

    is there anyway to only allow only one name to be submitted, instead of an unlimited amount?

Pages: « 8 7 [6] 5 4 3 2 1 » Show All

Leave a Reply