TextboxList: Fancy Facebook-Like dynamic inputs!
This post discusses a project which has its own page. Please refer to TextboxList for the most up-to-date information.
Check out a demo of TextboxList before reading!
While working on my big and exciting new project, I decided to include an input that resembles the famous Apple Mail to: textfield. 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)
I created my own, MooTools 1.2 compatible, in just 5kb. It’s not only small, but also really frexible! Here are some notes of the creation process and how to implement it in your own projects.
Anatomy of the control
As usual, I try to come up with a semantic, unobstrusive approach. I start with the CSS and the markup that will be my end result.
I want to go from something like this:
<li id="facebook-list" class="input-text"> <label>FacebookList input</label> <input type="text" value="" id="input-demo2" /> </li>
to something like this (only one possible scenario, naturally)
<li id="facebook-list" class="input-text"> <label>FacebookList input</label> <ul class="holder"> <li class="bit-input"><input type="text" value="" class="smallinput" /></li> <li class="bit-box">Jorge Luis Borges <a href="#" class="closebutton"></a></li> <li class="bit-input"><input type="text" value="" class="smallinput" /></li> <li class="bit-box">Julio Cortazar <a href="#" class="closebutton"></a></li> <li class="bit-input"><input type="text" value="" class="maininput" /></li> </ul> </li>
Basically, it’s a group of pieces (that I’ll call bits), that can be either a box or an input (small, except for the main one). The user is able to move around between the bits by using his keyboard or his mouse.
Javascript
As far as the javascript goes, I try to first think about reusable code (usually classes) that I may use. I thus first coded the class that adds resizing capabilities to the small fields as the user types, and a small utility method to find the caret position.
The only challenges I found was handling the complex events while keeping everything crossbrowser. Again, none of this would have been possible if it wasn’t for MooTools (1.2).
Using it
All you have to do is:
new TextboxList('input-demo');
Where input-demo is the id of the desired input to replace
The constructor can take these options:
- onInputFocus (event, fired when an input gets focus)
- onInputBlur (event, fired when an input loses focus)
- onBoxFocus (event, fired when a box gets focus)
- onBoxBlur (event, fired when a box loses focus)
- onBoxDispose (event, fired when a box is removed)
- resizable (option, hash, passed to ResizableTextbox constructor)
- className (option, string, prefix of the classnames of the generated objects)
- extrainputs (option, boolean, adds small inputs between boxes if true)
- startinput (option, boolean, adds a small input before the first box if true)
- hideempty (option, boolean, hides the small inputs by default)
Extending it
One of the my favorite features of MooTools is how easily you can create and extend classes. It makes you feel in a truly Object-Oriented environment, overcoming all Javascript limitations and complexities to handle functionalities like this by default.
I decided that, for the sake of simplicity, the class would not incorporate stuff like boxes removal through clicks, or even autocompletion (like Facebook does), since the scenarios to use this control are multiple and diverse.
Here is an example of how easily you can add the small remove links next to the name (and some CSS, of course)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | var FacebookList = new Class({ Extends: TextboxList, 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) } })); return li; } }); |
Changelog
- 0.1: initial release
- 0.2: code cleanup, small blur/focus fixes
Download
Click here to download a zip file containing examples, TextboxList documented (8kb) and compressed (5kb)
New! TextboxList with autocompletion
Displaying only a subset of the comments. Click here to display all comments.
-
-
Mark, in your autoTag function you’ve incorrectly checked to see if this.autoTag is true, rather that this.options.autoTag. I replaced the first line by removing it to after ‘a’ is set, and returning false but also setting the value of a[0] to an empty string, so when autotag is off and they hit the autoTag key, it just empties the text input.
autoTag:function(){
var a=this.maininput.getChildren(‘input’);
if(!this.options.autoTag){
a[0].set(‘value’,”);
return this;
}
if(!a.length)return this;
var b=a[0].get(‘value’);
if(!b.length)return this;
while(b.substr(b.length-1,b.length)==String.fromCharCode(this.options.autoTagSeparator))b=b.substr(0,b.length-1);
if(!b.length)return this;
this.add(b);
a[0].set(‘value’,”);
return this
}
-
If you want this working with mootools 1.2 (the newer, non-beta one), only a few changes are necessary.
You can get it here:
http://www.learningtoshred.com/js/textboxlist.js
This version also lets you “auto tag” when entering text in the last text entry (it does not do this if you enter text in the small text inputs between the tags).
When typing in the box, if you hit the space key it will turn that previous word into a new tag. If you want another key to trigger this instead of space (such as comma), then pass the ascii code of the character with the option ‘autoTagSeparator’.
- mark