# Tag Manager (a jQuery plugin)

Type some tags in the input field, and separate them with enter, comma, or tab:

### Turn a simple input field into a tags manager with a line of code:

HTML markup

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

Javascript

    jQuery(".tm-input").tagsManager();

## Using multiple tag manager instances on the same page

Note you can have as many instances of tag manager on a single page as you want, with no conflicts; but please read below how to manage them when retrieving user input during <form> submit.

## Using tag manager in conjunction with typeahead.js

Note before v3.0 tagmanager was using bootstrap-typeahead, but bootstrap deprecated typeahead from bootstrap v3.0; in this example we are using twitter-typeahead, which is different from bootstrap-typeahead. Both bootstrap-typeahead and twitter-typeahead are developed by the same developers, but they have a different API; and twitter-typeahead is much more feature rich.

        var tagApi = jQuery("#your_pretty_id").tagsManager({
          prefilled: ["Angola", "Laos", "Nepal"]
        });

        jQuery("#your_pretty_id").typeahead({
          name: 'countries',
          limit: 15,
          prefetch: '/ajax/countries/json'
        }).on('typeahead:selected', function (e, d) {

          tagApi.tagsManager("pushTag", d.value);

        });

## Typeahead via Ajax source

Now that we are using typeahead.js from tag manger v3.0 it make sense to use typeahead.js own API to load typeahead from an ajax source, it's very flexible, it's very powerful, and we strongly suggest to read the docs on github to learn how to configure it, to give you a hint, look above at example explaining how to set up tag mangager in conjunction with typeahead.js and check the typeahead.js parameter `prefetch`.

## Typeahead via function() source

Again, now that we are using typeahead.js from tag manger v3.0 you can use the powerful typeahead.js API to load from any source. Check the docs on github to learn how to configure a local source as a `function()`, look in the docs for typeahead.js parameter `local`.

## Retrieving tags on <form> submit

By default, Tag Manager creates a hidden input field with a random generated name and stores its data in this hidden field as a comma separated list.

When processing the user input on form submit, simply parse the data of this hidden field.

Look for this hidden field in the examples above using a browser developer tool (such as Firefox Firebug). In the example you should see: `<input type="hidden" value="Pisa,Rome" name="hidden-somerandomgeneratedcode">`

It is also possible to give this field a customer name using the `hiddenTagListName` parameter, or create your own hidden field and use the `hiddenTagListId` parameter.

Note if you are using javascript to post the list of tags you may be much more interested in tag manage API, see below how to retrieve the list of tags entered by the user using the API or how to have tag manager automatically push the tags to a ajax location.

## Pushing Tags via Ajax

Tagmanager can push entered tag values on-the-fly via Ajax as the user creates/deletes tags to a user-specified destination. Use the `AjaxPushAllTags` option to push all tag values on every update, rather than incrementally per created tag. Use the `AjaxPushParameters` option to add additional parameters on each ajax request. Refer to documentation for additional parameters.

        jQuery(".tm-input").tagsManager({
            AjaxPush: '/ajax/countries/push',
            AjaxPushAllTags: true,
            AjaxPushParameters: { 'authToken': 'foobar' }
        });

Note to see this working, open firebug or chrome developer tools and chech the XHR ajax request being generated when you add or remove tags from the input field above.

## Using API

Tagmanager has a nice API you can use to programmatically add or remove tags, see below an example, and check the complete list of methods in the configuration section.

        jQuery(".tm-input").tagsManager({
            AjaxPush: '/ajax/countries/push',
            AjaxPushAllTags: true,
            AjaxPushParameters: { 'authToken': 'foobar' }
        });

Note to see this working, open firebug or chrome developer tools and chech the XHR ajax request being generated when you add or remove tags from the input field above.

## Tagmanager Configuration

The code below show all the configurable options available (as of version 3.0.0):

        jQuery(".tm-input").tagsManager({
          prefilled: null,
          CapitalizeFirstLetter: false,
          preventSubmitOnEnter: true, // deprecated
          isClearInputOnEsc: true, // deprecated
          AjaxPush: null,
          AjaxPushAllTags: null,
          AjaxPushParameters: null,
          delimiters: [9, 13, 44], // tab, enter, comma
          backspace: [8],
          maxTags: 0,
          hiddenTagListName: null, // deprecated
          hiddenTagListId: null, // deprecated
          replace: true,
          output: null,
          deleteTagsOnBackspace: true, // deprecated
          tagsContainer: null,
          tagCloseIcon: 'x',
          tagClass: '',
          validator: null,
          onlyTagList: false
        });

prefilled | Populates the initial tag values. Default: null. Allowed formats: an Array of strings an Array of objects (if externalTagId is set to true, use prefillIdFieldName and prefillValueFieldName to configure) a String delimited by the first char code in the delimiters parameter (comma by default) a Function which returns an array if prefill is not provided output will be used as a fallback if provided. Note the value in output should be a string delimited by the first char code in the delimiters parameter (comma by default)
CapitalizeFirstLetter | If true, all tags will be displayed with first letter capitalized. Default: false.
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.
AjaxPushAllTags | If true, enables a mode to sync the entire tag state via AJAX (rather than incrementally) each time a tag is added/deleted. Default: false.
AjaxPushParameters | Adds an additional parameter payload to push with each AJAX request, for example server authentication parameters. Default: null.
delimiters | Default: `[9,13,44]` (tab, enter, comma). Delimiters should be numeric ASCII char codes. Please note the following: The following values are handled as key codes: 9 (tab), 13 (enter), 16 (shift), 17 (ctrl), 18 (alt), 19 (pause/break), 37 (leftarrow), 38 (uparrow), 39 (rightarrow), 40 (downarrow) Note that codes 45 (key = insert, char = -) and 46 (key = delete, char = .) are handled as chars, so currently insert and delete keys cannot be used as delimiters The first char code (non-key code) specified in the array will be used as the base delimiter for parsing tags to/from the hidden field "list string". This will default to comma if not specified. See http://unixpapa.com/js/key.html for a full explanation of ASCII versus key codes.
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 delimiters 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. Note this is working only if you also include jQuery UI in your project.
output | Should be a valid CSS selector, if present this input field will receive the comma separated list of tags entered; tag manager does not check if this selector is really an input field, just tries to fill the value with jQuery `.val()`.
replace | (true|false) If set, the element name of the input field will be transfered to the hidden input field storing the comma separated list of tags entered; in other words if you have `<input name="tags"/>` and you turn it into a tagmanager with this parameter true on form submit you will find the tags posted with `name="tag"`.
maxTags | Optionally defines the maximum number of tags accepted. Default: 0 (no limit)
tagCloseIcon | Sets the HTML string to be used as the tag close icon. Default: ×
tagsContainer | Optional jQuery selector for the element to contain the tags. Default: tags appear immediately before the tag input.
tagClass | Optional class to be applied to all tags. Please as see note about automatic tag styling. Default: none
validator | An optional callback function to validate the user input. Takes the tag string as input, and must return true or false. Default: null (no validation function used).
onlyTagList | If true, rejects tags which do not appear in the typeahead list. Default: false
externalTagId | Optionally instead of incrementing id of tags, you could pass it as argument to pushTag and use it later. (.tagsManager('pushTag','I_am_a_new_tag', false, 1);) Default: false
prefillIdFieldName | Optional. If externalTagId and prefilled is set to true: This option will be used to get Tag Id from prefilled objects. Default: 'Id'
prefillValueFieldName | Optional. If externalTagId and prefilled is set to true: This option will be used to get Tag Value(name) from prefilled objects. Default: 'Value'
fillInputOnTagRemove | If true, fills back the content of the removed tag to the input field. Default: false

## Tag Manager 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 retrieve the list of all tags entered so far

    .tagsManager('tags');

## Tag Manager Styles

Tag Manager comes bundled with a Bootstrap-themed set semantic colors/sizes, and provides multiple methods to define tag styles:

1. the CSS base class `tm-tag` is applied to all tags
2. classes assigned to the input are used to infer the semantic tag classes, for example `<input class='tm-input tm-input-success tm-input-small'/>` will apply classes `tm-tag-success` and `tm-tag-small` to the tags.
3. you can apply a custom class(es) to the tags using the `tagClass` parameter

In order to have correct alignment we recommend that you give the input the class `tm-tag`. If using TagManager within a Bootstrap `control-group` container, please also add `tm-group` class to the container node.

## History

I built Tagmanager 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.

## Alternatives to my Tagmanager

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.

- Tag it! by Levy Carneiro Jr, one of the very first one as far as I know, which inspired all the others.
- Tag Handler by ioncache, in my opinion is probably the best general purpose tags manager around.
- jQuery Tags Input Plugin, it's really very cute.
- Stack Overflow Tag Manager, if you want to mimic StackOverflow behavior.

The four above are the best around in my opinion, but... I developed Tagmanager. 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 typeahead.

## Version 3.0 is in beta.

Version 3.0 is in beta, there are a couple of things which doesn't work as they should when used in conjunction with typeahes.js, please check discussion on github, we are trying to fix this.

## Third-Party Add-ons

- tagmanager-rails by tmaier integrates TagManager with the Rails asset pipeline.

## 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.

/ul