IT IS HERE! Get Smashing Node.JS on Amazon Kindle today!
Show Posts
← Back to homepage

TextboxList turns normal textboxes into a widget which can be navigated with the keyboard, effectively turning your input into a “list” of items that can be easily deleted. It comes with an Autocomplete plugin.

TextboxList

Demo

Click here to see it in action.

License

You can use and modify TextboxList freely for any non-commercial use. Otherwise you need to purchase a one-time per-domain license of $20, by clicking on the link on the right.

Browsers support

TextboxList has been tested and is officially supported on IE6, IE7, IE8, Firefox, Safari and Chrome. You may report bugs concerning other browsers, but they’ll get a lower priority.

Size

TextboxList + TextboxList.Autocomplete are only 4.3K minified (YUI) and gzipped.

How to use

TextboxList is essentially very easy to use, but is extremely configurable and extensible. Let’s review some sample usage scenarios:

new TextboxList('form_tags_input');

This turns the <input id="form_tags_input"> into a TextboxList widget. By default, as shown in the demo, the user can add new boxes by pressing enter, write between boxes, delete them with backspace and delete keys. Additionally, a delete button is shown in each of the added items. All these behaviors can be configured, as shown in the sections below.

var t = new TextboxList('form_tags_input');
t.add('Tag 1').add('Tag 2').add('Tag 3');

In this example we call the public add() method of the TextboxList instance to add items from JavaScript.

The anatomy of TextboxList

This section will be useful for those interested in customizing the default behavior of TextboxList, extending the main classes or writing their own plugins.

The parts that constitute a TextboxList widget are called bits. These parts have common characteristics: they can be focused, blurred, deleted, hidden, they are a fragment of the overall value, etc. TextboxList has two essential bits: the editable and the box bit.

Some options involved in the behavior and appearance of the widget are specific to the editable bits, and some are specific to the box bits, which are separate classes from TextboxList ((Even though they are separate classes and you can instantiate them from your code, usually you’ll want to use the add or create methods.)). To easily pass them from the main class, you use the bitsOptions property. For example, to disable the delete button in boxes bits, and use the shift key for adding items instead of the enter key:

new TextboxList('form_tags_input', {bitsOptions: {
    box: {deleteButton: false},
    editable: {addKeys: Event.Keys.shift}
}});

Knowing this gives you more customization power. If you want to target the blur event of any bit, attach a onBitBlur listener. If you want to target boxes, you can use onBitBoxBlur. You can see a complete list of options and events at the bottom of this page.

The anatomy of a bit

Each bit has a value of the format [id, plaintext, html]. For boxes, this can mean that one that says “John Doe” really passes the value “3″ when making a POST. And it even allows you to customize the content of the box by using a different HTML representation. The id and html, however, are optional, like shown in the first example above. We called add() with just the plain text, and not an id or html, which are the second and third arguments of the method ((If we had wanted to add an item with an id 31 and html, we could have done t.add(‘Entry’, 31, ‘<img src=”some_entry_image.png” /> Entry’); )).

There’s an abstract TextboxListBit class from which TextboxListBit.Box and TextboxListBit.Editable are inherited. These classes deal with the creation, focusing, blurring, removal and display of the bits, and communicate with the main class by firing events/callbacks. There’re still many tasks that have to be taken care of by the TextboxList class, such as making sure the name of bits doesn’t exceed the value the user specified with the max option.

Autocompletion

Autocompletion is another chapter in the TextboxList story. Again, if you plan to use Autocompletion, it’d be wise to read the sections above.

Autocomplete (like other plugins) is initialized like this:

var t = new TextboxList('input_id', {plugins: {autocomplete: {options}});

You can then access the TextboxList.Autocomplete instance from the plugins property:

var autocomplete = t.plugins['autocomplete'];
// autocomplete.someMethod();

The autocompleter plugin is independent of the datasource. In order for autocompletion to be enabled, you have to supply a valid array of would-be bits by calling setValues(). The searches are performed on the bit plain text.

// continues from the last example
autocomplete.setValues([
  [31, 'Bit Plain Text', 'Bit html', 'Suggestion item html'],
  // ...
]);

Naturally, you can call that very function with a result from Request.JSON, Request.JSONP, Swift or construct the array from DOM elements.

Autocompletion: querying the server as the user types

The autocomplete can also query the server as the user types. When the user types at least as many characters as specified by the minLength option, a XHR request is performed to the server, which has to respond with a subset of results in JSON.

var t5 = new TextboxList('form_tags_input_4', {unique: true, plugins: {autocomplete: {
	minLength: 3,
	queryRemote: true,
	remote: {url: 'autocomplete2.php'}
}}});

Binary search is a very efficient searching algorithm which you can use by including the TextboxList.Autocomplete.Binary.js file and passing the method: 'binary' option to the Autocomplete plugin:

new TextboxList('input_id', {plugins: {autocomplete: {method: 'binary'}}});

Only use it under these conditions:

  • You have many values to filter
  • The values array is sorted alphabetically
  • You can afford searching only the beginning of the strings

The method works by first locating the first match of the user input in the values. As an example, if we search for ‘z’ in the demo, it takes linear, standard filtering 62 tries to determine there’re no results. For binary search, it takes 6.

Since binary search was conceived to find a single match, what the filtering method does is look up and down through the array for other matches and come up with a list of suggestions.

Custom styling

Please refer to the comments in TextboxList.css and TextboxList.Autocomplete.css for style customization guidelines.

Extending TextboxList

The core functionality can be extended easily:

var MyTextboxList = new Class({
      Extends: TextboxList,

      // your methods or overrides
});

If you wish to extend the Bits, make sure you override the create method:

var MyTextboxList = new Class({
      Extends: TextboxList,

      create: function(klass, value, options){
          // ...
	  return new MyTextboxListBit[klass.capitalize()]...
      }
});

MyTextboxListBit = {};
MyTextboxListBit.Box = new Class({
    Extends: TextboxListBit.Box,
    // ...
});
MyTextboxListBit.Editable = new Class({
    Extends: TextboxListBit.Editable,
    // ...
});

API

Options

  • prefix (default to ‘textboxlist’) Prefix of the HTML classes of the different parts of the widget.
  • max (defaults to null) If set to a value other than null or false, a maximum number of boxes that can be added.
  • unique (defaults to false) If set to true, an id (or plain text if id not present) of a bit can’t be repeated.
  • uniqueInsensitive (defaults to true) If set to true and an id is not present for a bit, the check for a repeated plain text disregards case.
  • endEditableBit (defaults to true) Whether an editable bit at the end of the widget is added by default.
  • startEditableBit (defaults to true) Whether an editable bit can be added to the left of the first box (ie: beginning of the widget)
  • hideEditableBits (defaults to true) Whether to hide editables bit that are not currently focused
  • inBetweenEditableBits (defaults to true) Whether to add editable bits between to boxes
  • keys (defaults to left key and right key) An object consisting of a previous and next key whose values are event codes for moving to previous and next bits.
  • plugins (defaults to {}) An object with maps a plugin name and its options, for initialization. The plugin name is camelcased and capitalized to find the class ((If you pass plugins: {‘some-plugin’: {}} it’ll try to initialize TextboxList.SomePlugin))
  • check A function that filters out (and prevents the addition of) a bit. For example, if the item is not an email address.
  • encode A function that turns an array into the string that is sent along with the form. The default takes the values and comma-separes them. Receives all the values of all bits as parameter.
  • decode Does the opposite of encode. Used when initializing textboxlist, which tries to read values from the element. The default looks for commas to split the string.

Events

  • focus: when the widget is focused
  • blur: when the widget is blurred
  • bitFocus: when a bit is focused. Passes the bit object as parameter
  • bitBlur: when a bit is blurred. Passes the bit object as parameter
  • bitAdd: when a bit is added. Passes the bit object as parameter
  • bitRemove: when a bit is removed. Passes the bit object as parameter
  • bitBoxFocus: when a box bit is focused. Passes the bit object as parameter
  • bitBoxBlur: when a box bit is blurred. Passes the bit object as parameter
  • bitBoxAdd: when a box bit is added. Passes the bit object as parameter
  • bitBoxRemove: when a box bit is removed. Passes the bit object as parameter
  • bitEditableFocus: when a editable bit is focused. Passes the bit object as parameter
  • bitEditableBlur: when a editable bit is blurred. Passes the bit object as parameter
  • bitEditableAdd: when a editable bit is added. Passes the bit object as parameter
  • bitEditableRemove: when a editable bit is removed. Passes the bit object as parameter

Public Methods

  • create (klass, value, options) Creates a bit of class klass, with value value and options options. Returns the bit
  • focusRelative (dir, element) Moves the focus to the dir (previous, next) element of the element element, if supplied. Otherwise it uses the current element
  • focusLast Focuses the last bit
  • add (plain, id, html, afterEl) Adds a box bit with value [id, plain, html], and injects it after the last available box, unless afterEl is supplied.
  • getValues Returns an array with the values from all the box bits.
  • setValues (values) Creates the box bits from the values array.
  • update (values) Updates the input with the values from getValues. This is done for you automagically, and is rarely needed.

Editable Bits Options

Refer to the bit anatomy section to see how to pass these.

  • tabIndex (defaults to null) Don’t set this option directly. Set the tabindex attribute to the original input
  • grows (defaults to true) Whether a GrowingInput instance is created for the input
  • growingOptions (defaults to {}) An options object passed to GrowingInput
  • stopEnter (defaults to true) Whether the event propagation is stopped when enter is pressed. Useful because enter triggers form submission
  • addOnBlur (defaults to false) Whether a box is added with the input content when the input is blurred.
  • addKeys (defaults to Event.Keys.enter) A key or array of keys that trigger adding a box with the input content.

Box Bits Options

Refer to the bit anatomy section to see how to pass these.

  • deleteButton (defaults to true) Whether a delete button is added in the box.

Autocomplete Options

Refer to the binary search section to see how to pass these.

  • minLength (defaults to 1) Minimum number of characters typed in to trigger search.
  • maxResults (defaults to 10) Maximum number of results to display.
  • insensitive (defaults to true) Whether to perform a case-insensitive search
  • highlight (defaults to true) Whether to highlight results.
  • highlightSelector (defaults to null) Optionally, A CSS3 selector to determine on which elements of the autocomplete suggestion to perform highlighting.
  • mouseInteraction (defaults to true) Whether to allow mouse (hovering and clicking) interaction.
  • onlyFromValues (defaults to false) If set to true, the user can only pick values from the suggestions.
  • queryRemote (defaults to false) If set to true, the script attempts to retrieve suggestions from a remote URL, set by the remote option.
  • remote (defaults to {}) Options object

    • url URL to query by Request.JSON to retrieve the suggestions.
    • param (defaults to 'search') Name of the parameter in which to send the string to search
    • extraParams An object with extra parameters to send, or a function that returns that object.
    • loadPlaceholder Placeholder text to display when loading.
  • method (defaults to 'standard') Search/highlighting method defined in TextboxList.Autocomplete.Methods
  • placeholder (defaults to 'Type to receive suggestions') A placeholder text to display. If it evaluates to false, placeholder is not shown or inserted.

Autocomplete Public Methods

Refer to autocompletion section to see how to call these.

  • setValues (values) Seeds the autocompleter with suggestions from the values array.

Changelog

  • 0.1: first release
  • 0.2: TextboxList completely rewritten (current)
  • 0.3:
    • HTML for bits not showing properly fixed
    • highlightSelector not working (due to a typo) fixed
    • GrowingInput missing pad function added (only affected if you customized growing.mini option)
    • Improved clicking the whole widget behavior
    • Other tiny enhancements / cleanup
  • 0.4:
    • check added, filter deprecated
    • queryRemote and remote added to Autocomplete
    • encode now receives all the values of all bits
    • Fixed but with id 0 translating to null.
    • autocomplete2.php added
    • Demos updated
  • 0.5: fixes a problem with non-remote use of Autocomplete.

109 Comments

Guest said

For my usage I found it useful to add the following at the bottom of TextboxListBit.Editable.initialize():

this.element.addEvent(‘blur’, function(ev) {
this.toBox();
}.bind(this));

This way if users forget to hit enter after their last item, the last item is still added.

    MaishN said

    Where do you make this change. Which file? Thanks for your help.

Alex said

Is it possible to add a non existing tag?
Lets say. User types a tag and it’s not in our “tags collection”. Then the user should be asked for whether he/she want to add this tag in a modal form.

Ahmad said

Hi, that a very cool.
But where can I download it? I couldn’t find any download link for version 0.5 in your site!
Can you help me please?

Thankss

pripa said

I have set the search method to standard still the search is only being made from the beginning of every word not in between char of word. ex. if i have text “this is my test”. If I type “es” or “hi” then it doesn’t return anything. Its only searching for the beginning of every words.

Mike said

Great!….How can i download this?…Can anyone help, Thanks!

For now, just download the files inside the demo page.

Mike said

Thanks Greg Daynes for the download link!

Samantha said

The functionality that I’m trying to build into the Textboxlist is to VALIDATE users input.

If the bit does not validate then I will try to change its background color to red. This will be real sweet and user friendly if I can add this functionality. If any gurus out there has done this already please share.

Ben said

Hi, I’m making an ajax web app and as I don’t reload pages, the add function tag keeps chaining. How could I clear my textarea from all the tags inside when I’m doing a new action ?

Thanks !

    Kim said

    Hi Ben,

    This is not a full answer but hope this can give u a start on implementing what you wish. In the file textboxlist.js look at line 105 – 109 i think thats how u remove items. U can try to modify it for ur use.

    -Kim ( Can someone help me resolve my issue i posted above?)

    Tim V. said

    Here’s a method that I am using for now. Might be a cleaner way to do it, but I am hacking at the moment. The “id” parameter is the id of the control that TextboxList initialization was called on.

    var ClearTextboxList = function( id ) {
    $(“#”+id).parent().find(“.textboxlist-bit-box-deletebutton”).each(function(){
    $(this).click();
    });
    };

    I just added a clear function to my version of TextboxList.
    I added this code on line 159:

    var clear = function(){
    var values = [];
    list.children().each(function(){
    var bit = getBit(this);
    if (!bit.is(‘editable’)){
    bit.remove();
    }
    });
    };

    And then this code on line 281:
    this.clear = clear;

    This will then clear your TextboxList.TextboxList.clear();

Kim said

Has anyone notice this problem when setting onlyFromValues = true for Autosuggest text box.

In Internet Explorer when you type a letter and the Auto-suggest box appears below, that wen hovering to an item with your mouse. it does not highlight the item or takes a veeeeeerry long time to do so?

How can i resolve this issue in Internet Explorer? Thanks in advance guys!

Tom said

Hey Yes Auto suggest does not work in IE when setting “onlyFromValues = true”. Help please!

TimHussey said

I feel pretty dumb…
How to you get an instance of the TextBoxList after creating it from another function…

So example: i’ve already created it :
var emailToField = new $.TextboxList(‘#recipient’, {
unique: true,
plugins: { autocomplete: { minLength: 0 } },
bitsOptions: { box: { deleteButton: true}, editable: { addKeys: [188] } }
});

but due to scoping the emailToField doesn’t exist…
is there a way to just do something like this?

var toField = $(‘#recipient’).textboxlist();
without it creating ANOTHER textboxlist on that element??

if anyone can help, please e-mail me

timhussey – at – gmail – dot – com

Lyx_haven said

I found that the download projects didn’t have a dropdownlist for autocomplete while the demo really has one.
And anyone can tell me how to link database to the data in the dropdownlist?
Thinks a lot!

JH said

Hello, where has the link gone for purchasing a commercial license?

maxargentina said

Hi, im wonder if can be a possibility to avoid editing text… only write the tags with js

jlvs said

is it beatifull

Thanx for sharing this great plugin! :)

I have a question… is there a way to programmatically populate the textboxlist? and, more importantly, to clear it???

Thanx in advance for your reply.

Cyngus106 said

Anyone else notice that this does not work in IE9… is there anyone who has a solution?

Cyngus106 said

Anyone else notice that this does not work in IE9… is there anyone who has a solution?

Alexander said

It looks to me than this plugin is unfornunately not maintained any more, there is no more link for commecial licenses and not a single answer from the author on the comments. Maybe someone should take over this ?

Cyngus106 said

if anyone is able and willing to help i will pay… please contact me @ cyngus106@gmail.com

    Guest said

    just use jquery version.. is a compatible view problem.. 

Lee Gee said

I’m writing a non-commercial demo that will end up as a commercial service, and TextboxList looks ideal for the project. But I can’t find a mailing list for support — is there one around? I have issues calling .update to set the initial value of the box, and with allow ENTER to submit the form if a tag is not being chosen.

Tim Kock said

Ok trying to fix the “missing clear” issue, insert this code after update: function() { somecode… }
clear: function() { this.list.getChildren().map(function(el){ var bit = this.getBit(el); if (bit.is(‘editable’)) return null; bit.remove(); }, this); }

    ldiqual said

    It’s also necessary to clear the bit index with this.index.empty():

    clear: function() { this.list.getChildren().map(function(el){ var bit = this.getBit(el); if (bit.is(‘editable’)) return null; bit.remove(); }, this); this.index.empty(); }  

Barisahmet said

You can’t use “add bit on press comma”, with autocomplete plugin enabled. I am looking forward that to get fixed. Nice work :)

Aasdfda said

这个在哪下载源码?

Mo said

Solution to the question I just asked: I took out the MinLength setting and it works perfectly fine now.

Just awesome code, I will read it and probably use it in my social network. Thanks for sharing.

Whisperofcp said

 seem  not support chinese inputs,is there a way ?

Xpallicer said

Hi all

using {unique: true, plugins: {autocomplete: {onlyFromValues: true}

¿How can autocomplete list be updated when using add()?

I’m using add to add selected elements, but I need that elements to not show again in autocomplete list.

Anybody else has this issue?

    Xpallicer said

    I guess it has something to do with index

      Xpallicer said

      I’ve added this method to TextboxList.Autocomplete

              setSelected: function(selected){            for (var i = 0; i < selected.length; i++){                var value = selected[i]; var b = this.textboxlist.create('box', value.slice(0, 3)); if (b){ b.autoValue = value; if (this.index != null) this.index.push(value);                        var afterEl = this.textboxlist.list.getLast('.' + this.textboxlist.options.prefix + '-bit-box'); b.inject(afterEl || this.textboxlist.list, afterEl ? 'after' : 'top'); }            }        },

      I had problems at showResults:
      if (this.index) results = results.filter(function(v){ return !this.index.contains(v); }, this);

      so id changed that line by 

                      if(this.index.length){                    var resultsok = [];                    for (var i = 0; i < this.index.length; i++){                        for (var j = 0; j < results.length; j++){                            if(this.index[i][0] != results[j][0]){                                resultsok.push(results[j]);                            }                        }                    }                    results = resultsok;                }

      hope this can help

Yi Wang said

Hi, The project does not work in ie9. this bug can be repaired.!

Gerbert Olivé Vázquez has an bugfixed jquery version in his git repository:
https://github.com/golive/TextboxList

Azim said

I want to handle dragged or pasted text please?

Sébastien said

Any chance to have MooTools 1.3 compatible library  ?

    Florin said

    mootools sucks…. go with jQuery

Rosario said

Hi, first of all, congratulations! It works really well but I am having troubles with the GrowInput. I want to stop the main box from growing, but I can’t get it working, could you please provide an example? I basically want the bits to be inserted and navigated horizontally, but not vertically, is this possible at all? Thanks!

tim said

i cannot get anything to post from any of the autocomplete examples on my own, anything i am missing?

moeenkhurshid said

excellent work just what I was looking for, save me the trouble of going into ajax, blah, blah…. we are using it for commercial use and you earned your 20$, yup. let me know how to pay you or your pay pal address

Snehal Desai said

Hi, I want to buy this software. Please let me know how to buy it? I can not find any link or the contact number to call.

Thanks,
Snehal

Max said

where can i download the file?

Amy Wong said

Hi,

We have been able to successfully use TextBoxList on our site until recently. The person who originally implemented this has left, and it appears to have stopped working in IE 9 (the editor does not have any autocomplete functionality). Do you have any plans to update TextBoxList to support IE 9 or suggestions on how we might be able to fix it? Any help would be appreciated.

Thanks,
Amy

Rahul said

great man Its very use full to me when we needed some more values in one field like some mail Ids , some names etc.

shereen said

there are error in file TextboxList.Autocomplete.js
if (values[i][1].test(regexp)) newvals.push(values[i]);

values[i][1] undefined

Tolgay said

Hi How can I use “blur” ?

Ralosoft said

Sabe alguien como tendria que hacer mi archivo autocomplete2.php por que es lo unico que me faltaria, muchas gracias de antemano

Ralosoft said

Sorry i wrote in spanish, i need to create autocomplete2.php to get the results what i wrote in the input. AnyBody can help me with a functional example?
Just i need that to finish the application.

Thanks!

Sedat said

IE9 Not Working ??

Brad said

For those of you looking to not require your users to hit enter after the last entry (in case they type and then just click submit), a quick change:

Line 319 in TextboxLixt.js reads:

addOnBlur: false,

Change it to:

addOnBlur: true,

And life gets better!

Dav said

Good work!
However in the Editable Bits Options is listed the “grows” attribute, that does not exist. The correct one should be “growing”.

Your thoughts?

About Guillermo Rauch:

CTO and co-founder of LearnBoost / Cloudup (acquired by Automattic in 2013). Argentine living in SF.