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. 15
    Guillermo Rauch Says:

    @Nick
    This already works with an ajax -ajaj really, the last j being of json- response

  2. 14
    Nick Says:

    Very nice - exactly what I’ve been looking for

    I am trying to use this with an ajax response (so names are pulled in from db - any tips on how to do this would be a great help.

    Thanks again

    Nick

  3. 13
    Ali Pour Zahmatkesh Says:

    its very nice components with mooTools!
    nice and very nice;)

  4. 12
    Guillermo Rauch Says:

    @James
    It actually took me longer to post the update than to code it itself… I’ve just uploaded it for you to use it in your project !

  5. 11
    Devthought - Guillermo Rauch’s Blog » TextboxList: Fancy Facebook-Like dynamic inputs! Says:

    [...] New! TextboxList with autocompletion [...]

  6. 10
    James Pearson Says:

    Very nice, I almost included it in my project away.

    But it doesn’t seem to work when you click on one of the names in the drop down list, only when you use press enter. (Firefox 2.11, Windows XP)

    Is this on purpose or something that was overlooked?

  7. 9
    Guillermo Rauch Says:

    @Nuri
    Call the update function when you submit your form.

  8. 8
    Nuri Akman Says:

    Very useful and smart autocompletion! Simple to implement !

    But, How can I catch selected items after submitting form?

  9. 7
    Jacob Says:

    Of course the next step is to allow AJAX submissions for items not in the autocomplete list (on enter key).

    Looks awesome!

  10. 6
    Sanallinkler Bilgi Arşivi » Blog Archive » Facebook Tarzı Dinamik Input Says:

    [...] input’un aynısını yapmış. Gayet kullanılşı olmuş. Hatta başka bir örneğinde, bunu autocomplate özelliği ile de birleştirmiş ve tadından yenmez bir web kontrolüne [...]

  11. 5
    TextboxList + Autocomplete, los textbox del iPhone en tu web | aNieto2K Says:

    [...] Guillermo me avisa de que ha terminado la versión con automplete de TextBoxList. [...]

  12. 4
    Ahmed Says:

    thanks for such cool thing!

  13. 3
    Fanciest Javascript Autocompletion! Says:

    [...] read more | digg story [...]

  14. 2
    David Says:

    This is brilliant.

    Very slick and it seems to just work like you’d expect… Very neat, this definately has lots of potential.

  15. 1
    Facebook Tarzı Dinamik Input - katodivaihe Says:

    [...] input’un aynısını yapmış. Gayet kullanılşı olmuş. Hatta başka bir örneğinde, bunu autocomplate özelliği ile de birleştirmiş ve tadından yenmez bir web kontrolüne [...]

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

Leave a Reply