TextboxList meets Autocompletion

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
var FacebookList = new Class({Extends: TextboxList,data: [],options: {onInputFocus: function() { this.autoShow(); },onInputBlur: function(el) {el.value = '';this.autoHide();},onBoxDispose: function(item) {this.autoFeed(item.$attributes.$text);},autocomplete: {'opacity': 0.8,'maxresults': 10,'minchars': 1}},initialize: function(element, autoholder, options) {arguments.callee.parent(element, options);this.autoholder = $(autoholder).set('opacity', this.options.autocomplete.opacity);this.autoresults = this.autoholder.getElement('ul');var children = this.autoresults.getElements('li');children.each(function(el) { this.add(el.innerHTML); }, this);},autoShow: function(search) {this.autoholder.setStyle('display', 'block');this.autoholder.getElements('*').setStyle('display', 'none');if(! search || ! search.trim() || (! search.length || search.length < this.options.autocomplete.minchars )){this.autoholder.getElement('.default').setStyle('display', 'block');this.resultsshown = false;} else {this.resultsshown = true;this.autoresults.setStyle('display', 'block').empty();this.data.filter(function(str) { return str ? str.test(search, 'i') : false; }).each(function(result, ti) {if(ti >= this.options.autocomplete.maxresults) return;var el = new Element('li').set('html', this.autoHighlight(result, search)).inject(this.autoresults);el.$attributes.$result = result;if(ti == 0) this.autoFocus(el);}, this);}},autoHighlight: function(html, highlight) {return html.replace(new RegExp(highlight, 'gi'), function(match) {return '<em>' + match + '</em>';});},autoHide: function() {this.resultsshown = false;this.autoholder.setStyle('display', 'none');},autoFocus: function(el) {if(! el) return;if(this.autocurrent) this.autocurrent.removeClass('auto-focus');this.autocurrent = el.addClass('auto-focus');},autoMove: function(direction) {if(!this.resultsshown) return;this.autoFocus(this.autocurrent['get' + (direction == 'up' ? 'Previous' : 'Next')]());},autoFeed: function(text) {if(this.data.indexOf(text) == -1)this.data.push(text);},autoAdd: function(el) {if(!el || ! el.$attributes.$result) return;this.add(el.$attributes.$result);delete this.data[this.data.indexOf(el.$attributes.$result)];this.autoHide();this.current.$attributes.$input.value = '';},createInput: function(options) {var li = arguments.callee.parent(options);var input = li.$attributes.$input;input.addEvents({'keydown': function(e) {e = new Event(e);this.dosearch = false;switch(e.code) {case Event.Keys.up: return this.autoMove('up');case Event.Keys.down: return this.autoMove('down');case Event.Keys.enter:this.autoAdd(this.autocurrent);this.autocurrent = false;this.autoenter = true;break;default: this.dosearch = true;}}.bind(this),'keyup': function() {if(this.dosearch) this.autoShow(input.value);}.bind(this)});input.addEvent(Browser.Engine.trident ? 'keydown' : 'keypress', function(e) {if(this.autoenter) new Event(e).stop();this.autoenter = false;}.bind(this));return li;},createBox: function(text, options) {var li = arguments.callee.parent(text, options);li.addEvents({'mouseenter': function() { this.addClass('bit-hover') },'mouseleave': function() { this.removeClass('bit-hover') }});li.adopt(new Element('a', {'href': '#','class': 'closebutton','events': {'click': function(e) {new Event(e).stop();if(! this.current) this.focus(this.maininput);this.dispose(li);}.bind(this)}}));li.$attributes.$text = text;return li;}});window.addEvent('domready', function() {// initvar tlist2 = new FacebookList('facebook-demo', 'facebook-auto');// fetch and feednew Request.JSON({'url': 'json.html', 'onComplete': function(j) {j.each(tlist2.autoFeed, tlist2);}}).send();});
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:
<label>FacebookList input</label><input type="text" value="" id="facebook-demo" /><div id="facebook-auto"><div class="default">Type the name of an argentine writer you like</div><ul class="feed"><li>Jorge Luis Borges</li><li>Julio Cortazar</li></ul></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
Tags: on January 12th, 2008
May 14th, 2008 at 11:06 pm
After going through all the notes, I summary some Q&A hereAfter going through all the notes, I summary some Q&A here:
Q:The script doesn’t work on dropdown list? Or No dropdown list ?
A: Please change the following file name to .php, .asp or .jsp rather than .html
Eg:
json.html ->json.php
test.html -> test.php
Q: Can’t upload the list?
A: 2 steps
1. Modify test.php (if you had change the extension of test.html) or test.html
a. Add name and id to the form as “facebook-form”;
b. Add name to the input where id = “facebook-demo”;
c. Add submit button within the form
2. Add a script to the file test.js at line 172 or add the script within the funciton window.addEvent(‘domread’,function()) as
$(’facebook-form’).addEvent(’submit’,function(){ // facebook-form is the form id
tlist2.update();
})
After the change the function should be:
window.addEvent(’domready’, function() {
// init
var tlist2 = new FacebookList(’facebook-demo’, ‘facebook-auto’);
// fetch and feed
new Request.JSON({’url’: ‘namelist.php’, ‘onComplete’: function(j) {
j.each(tlist2.autoFeed, tlist2);
}}).send();
$(’facebook-form’).addEvent(’submit’,function(){ // facebook-form is the form id
tlist2.update();
})
});
HTH!!!!
May 14th, 2008 at 10:53 pm
That’s a great script. Thanks!!
Well, I met a problem here that I can’t input any other name but only the name from file.
How can I submit the name from either the list file or from the input by myself?
Thanks for the help.
Rainmore
May 13th, 2008 at 6:02 pm
[...] TextboxList / Mootools [...]
May 5th, 2008 at 2:23 am
[...] Facebook Style Input Box The approach to re-create the autocomplete method of adding multiple recipients to messages used on Facebook. “I’d seen it in Facebook before, which has a really decent implementation of this concept (it work well, but it doesn’t respect any modern programming principles; basically, it’s a big tag soup with lots of inline Javascript)” [...]
May 1st, 2008 at 3:34 pm
Thanks for the script
April 21st, 2008 at 6:12 pm
Great idea to improve the feedback for the user. Beside that thank you the possibility to get the source coude for free
Ralph
April 21st, 2008 at 6:26 am
[...] 一款Facebook风格的自动完成输入框 [...]
April 20th, 2008 at 1:19 pm
[...] Facebook Style Input Box The approach to re-create the autocomplete method of adding multiple recipients to messages used on Facebook. “I’d seen it in Facebook before, which has a really decent implementation of this concept (it work well, but it doesn’t respect any modern programming principles; basically, it’s a big tag soup with lots of inline Javascript)” [...]
April 18th, 2008 at 11:37 am
[...] TextboxList meets Autocompletion (tags: JavaScript Forms Ajax web2.0 JQuery) [...]
April 16th, 2008 at 8:45 pm
@Craig
The update() method takes care of that. You can either call it yourself or add it to the blur() method, which is what the upcoming version does (since so many people asked).
Nice website, by the way.
April 16th, 2008 at 8:38 pm
Excellent work by the way. Love it. Ive noticed though that it isnt populating any kind of hidden fields so that you can POST the information with a submit button? Is this something you are looking to add?
April 16th, 2008 at 4:54 pm
[...] Facebook Style Input Box Скрипт комбинирует метод автодополнения и добавление нескольких адресатов к сообщению, такой инструмент используется в Facebook. “I’d seen it in Facebook before, which has a really decent implementation of this concept (it work well, but it doesn’t respect any modern programming principles; basically, it’s a big tag soup with lots of inline Javascript)” [...]
April 16th, 2008 at 11:25 am
Very Cool. Any jQuery implementation of this, or something similar?
April 16th, 2008 at 9:12 am
[...] text : à la Facebook, ou [...]
April 15th, 2008 at 12:03 pm
[...] Facebook Style Input BoxThe approach to re-create the autocomplete method of adding multiple recipients to messages used on Facebook. “I’d seen it in Facebook before, which has a really decent implementation of this concept (it work well, but it doesn’t respect any modern programming principles; basically, it’s a big tag soup with lots of inline Javascript)” [...]