tags manager, tags, jquery plugin, tag handler, bootstrap

WellDoneThings.com

Little (hopefully) well designed pieces of code I want to share with you.

Tags Manager (a jQuery plugin)

I built this simple plugin while working on an online personal finance tool, I wanted a simple solution to manage tags for each expense users were entering, like in stackoverflow and many other sites.

Best way to understand what it does is to try it, so jump to the demo below:

Tags Manager Demo

Type some tags in the input field, separate them with comma (or tab).

And you can turn a simple input field into a tags manager with a line of code:


HTML markup

  <input type="text" name="tags" placeholder="Tags" class="tagManager"/>

Javascript

  jQuery(".tagManager").tagsManager();

Can have multiple instance on the same page

Type some tags in the input field (if the Ajax source is slow you may have to wait a couple of seconds to have the typeahead list show up), separate them with comma (or tab).

Just play with it.

How to retrieve tags on <form> submit

Tags manager does try to be very humble, if you place an input field in a form, and turn it into a tag manger with the code above, a hidden input field will be added to the form and filled with a comma separated list of the tags the user entered.

When processing the user input on form submit, server side, all you have to do is manage an additional hidden field with name="hiddenTagList".

If you have firebug installed or if you check the source code above in chrome developer tool or explorer developer tool you will see <input type="hidden" value="Pisa,Rome" name="hiddenTagList">

Example of Typeahead ajax source

Type some tags in the input field, separate them with comma (or tab).

The code below show how to use an ajax source, and an ajax destination for any added tag:

  jQuery(".tagManager").tagsManager({
        typeahead: true,
        typeaheadAjaxSource: '/ajax/countries',
        typeaheadAjaxPolling: true,
        AjaxPush: '/ajax/countries/push',
  });

Example of Typeahead function() source

Type some tags in the input field, separate them with comma (or tab).

The code below show how to use an ajax source, and an ajax destination for any added tag:

  jQuery(".tagManager").tagsManager({
        preventSubmitOnEnter: true,
        typeahead: true,
        typeaheadSource: your_function_here(),
        blinkBGColor_1: '#FFFF9C',
        blinkBGColor_2: '#CDE69C',
  });

Tags Manager is configurable

The code below show all the configurable options available (so far):

  jQuery(".tagManager").tagsManager({
    prefilled: ["Pisa", "Rome"],
    CapitalizeFirstLetter: true,
    preventSubmitOnEnter: true,
    typeahead: true,
    typeaheadAjaxSource: null,
    typeaheadSource: ["Pisa", "Rome", "Milan", "Florence", "New York", "Paris", "Berlin", "London", "Madrid"],
    delimeters: [44, 188, 13],
    backspace: [8]
    blinkBGColor_1: '#FFFF9C',
    blinkBGColor_2: '#CDE69C',
    hiddenTagListName: 'hiddenTagListA'
  });
prefilled Either a string of comma separate values or an array, the plugin will render these values as pre-selected tags.
CapitalizeFirstLetter If true all tags the user enter will be converted to lowercase but displaied capitalized.
preventSubmitOnEnter If true when the user hit enter inside the input field (and the input field is part of a <form>), nothing happen (the form is not submitted to the server).
typeahead If true a bootstrap typeahead is setup, typeahead is a nice plugin for bootstrap, when the user start typing something a popup below the input field show possible values matching the typed text.
Currently this features is available only if you also include bootstrap, if you are not using it tags manager typeahead won't work. Should be relatively easy to replace typeahead with jQuery UI autocomplete for the ones not using bootstrap, but I didn't. If anyone is really interested I can consider including that in a next releas that.
If you choose to use typeahead please check the typeahead specific paramenters in the bootstrap documentation.
And in case you don't want browsers autocomplete to mess with your own autocomplete learn to add autocomplete="off" on every Tags Manager input field.
typeaheadAjaxSource If you are a fan of bootstrap typeahead plugin you may love this, is a JSON AJAX source for the list of possible values to display in the typeahead popup. The JSON returned by your serverside code should look like this: {"tags":[{"tag":"Pisa"},{"tag":"Rome"},{"tag":"Milan"},{"tag":"Florence"},{"tag":"New York"},{"tag":"Paris"},{"tag":"Berlin"},{"tag":"London"},{"tag":"Madrid"}]}
typeaheadSource This is passed to standard Bootstrap typeahead source initialization option, so if you don't need an AJAX dynamically generated list you can provide a static one, or you can pass a function(), see typeahead docs for details. Of course in your very function() you can do ajax or whatever you want.
typeaheadAjaxPolling With Bootstrap v2.0 typeahead can request the list of entries to show to an ajax source everytime the user type something in the input field, provide "true" to this option to activate it. Otherwise the ajax source will be queried only at initialization.
AjaxPush Well, since we pull from an ajax source we can also push, don't we? So provide a url as AjaxPush and the added tag will be POSTed.
delimeters If you are not happy with comma separating your tags you can provide your list of delimeters, must be an array of char codes, the ones returned by javascript keyup/keydow/etc... See this table.
backspace When the input field is empty, and some tags are rendered on the left of the input field, and the user hit the backspace the plugin remove the rightest tag (which is the last the user entered).
With this option you can provide an array of char codes (like the delimeters above) you want the system to use in place of the backspace (char code 8), or provide an empty array if you don't want this feature at all.
blinkBGColor_1
blinkBGColor_2
When a duplicate tag is entered the user is notified with a blinking of the corresponding (duplicate) tag, here you can configure the colors.
hiddenTagListName You can define your own personalized name for the hidden tags list field.
PLEASE NOTE if you have multiple instance of tagmanager in a form you SHOULD give a different name to head hidden tags list field!
maxTags Define the maximum number of tags accepted, default is 0 which mean there's no limit and users can add as many tags as they want.
validator Provide a callback to validate the user input, only input field is the entered tag, the callback must return true or false.

You can use the following methods:

You can pop the last added tag (the rightmost being show)

  .tagsManager('popTag');

You can push a new tag

  .tagsManager('pushTag','I_am_a_new_tag');

You can remove all tags

  .tagsManager('empty');

You can style Tags Manager the way you want

Just override the styles defined in the .css file.

PLEASE NOTE, if you are not using bootstrap .css you may find out things doesn't look as nice as expected, that's just because you have to adapt the styles to your stylesheets, change the styles!

Alternatives to my Tags Manager

Before to develop my own tags manager I spent quite a lot of time investigating what other solutions where available, so I think I can spare you some time listing them here and explaining why I developed my own.

The four above are the best around in my opinion, but... I developed Tags Manager. I wanted it to be very simple, I didn't need a pencil mouse pointer when the user hover it. I didn't need inplace edit of the tag, I think it's confusing for the user. I didn't want the tag manager to generate a lot of html in the form.

And I wanted it to be fully integrated with bootstrap and its typeahead.

Further reading

If you have choosen to go this way and implement a tags system in one of your application you have probably already thought about a couple of things, like the database structure required to store tags.

But just in case... You can find some thoughts about that here.

Check the Tags Manager repository and download the scripts from github

Download from GitHub

Comments are welcome!