Tag Editor

A powerful and lightweight tag editor plugin for jQuery.

Usage

Include the stylesheet jquery.tag-editor.css in the <head> section of your HTML document - and the JavsScript file jquery.tag-editor.min.js after loading jQuery and optional jQuery UI sortable/autocomplete. Tag Editor accepts settings from an object of key/value pairs, and can be assigned to any text input field or textarea.


$(selector).tagEditor({key1: value1, key2: value2});



// examples



// assign tag editor to textarea - existing text will be used as initial tags

$('textarea').tagEditor();



// assign tag editor to text input with initial tags

$('input[type="text"]').tagEditor({ initialTags: ['tag1', 'tag2', 'tag3'] });



// use jQuery UI autocomplete

$('#my_textarea').tagEditor({ autocomplete: { 'source': '/url/', minLength: 3 } });

Settings

PropertyDefaultDescription
initialTags[]Initial tags as an array of strings.
maxLength50maxlength attribute of the tag input field.
delimiter',;'

Required string of delimiters - characters for separating tags. The first character is used as default delimiter in the (hidden) original field.

placeholder''Placeholder text for empty tag editor.
forceLowercasetrueLowercase all tags.
clickDeletefalseDelete tags on right click and on Ctrl+click.
sortabletrueIf jQuery UI sortable is available and this option is set to true, tags are sortable by drag and drop.
autocompletenulljQuery UI autocomplete options as key/value pairs object. If provided, jQuery UI autocomplete must be loaded additionally.
 
Callbacks
onChange (field, editor, tags)Callback that fires after tags are changed. field is the (hidden) original field, editor is the editor's DOM element (an <ul> list of tag elements), and tags contains the list of current tags.
beforeTagSave (field, editor, tags, tag, val)Callback that fires before a tag is saved. field is the (hidden) original field, editor is the editor's DOM element. tags contains the list of current tags, tag is the value that is about to get overwritten (empty string, unless an existing tag gets changed), and val is the new value to be saved.
beforeTagDelete (field, editor, tags, val)Callback that fires before a tag is deleted. field is the (hidden) original field, editor is the editor's DOM element. tags contains the list of current tags, val is the tag that is about to get deleted. Return false to prevent this action.
 
Public Methods
getTags Returns a list of objects in the following format:
[{ field: selected input/textarea, editor: editor instance for field, tags: current tags }]
addTag(val, next)Adds val as a new tag. Set next to 'blur' if focus should not be set automatically into an empty, new tag after this action.
removeTag(val, next)Removes val as tag. Set next to 'blur' if focus should not be set automatically into an empty, new tag after this action.
destroyRemoves the tag editor instance an restores visibility of the original text field or textarea.

Demos

Basic settings


$('#demo1').tagEditor({

    initialTags: ['Hello', 'World', 'Example', 'Tags'],

    delimiter: ', ', /* space and comma */

    placeholder: 'Enter tags ...'

});

The original field - textarea or text input - is normally hidden automatically. We show it here to make value changes visible:

The placeholder is visible when all tags are deleted and the editor looses focus. jQuery UI is already loaded on this page - and by default, tags are then sortable via drag and drop.

Autocomplete

For enabling tag autocompletion, make sure to have jQuery UI autocomplete readily loaded. You can then pass any options that work with UI autocomplete to your tagEditor settings.


$('#demo2').tagEditor({

    autocomplete: {

        delay: 0, // show suggestions immediately

        position: { collision: 'flip' }, // automatic menu position up/down

        source: ['ActionScript', 'AppleScript', 'Asp', ... 'Python', 'Ruby']

    },

    forceLowercase: false,

    placeholder: 'Programming languages ...'

});

Public methods


$('#demo3').tagEditor({

    initialTags: ['Hello', 'World'],

    placeholder: 'Enter tags ...'

});

getTags addTag 'example' removeTag 'example' Remove all tags destroy


// actions on button clicks



// getTags

alert( $('#demo3').tagEditor('getTags')[0].tags );



// addTag

$('#demo3').tagEditor('addTag', 'example');



// removeTag

$('#demo3').tagEditor('removeTag', 'example');



// Remove all tags

function() {

    var tags = $('#demo3').tagEditor('getTags')[0].tags;

    for (i = 0; i < tags.length; i++) { $('#demo3').tagEditor('removeTag', tags[i]); }

}

// working shortcut for removing all tags

// $('#demo3').next('.tag-editor').find('.tag-editor-delete').click();



// destroy

$('#demo3').tagEditor('destroy');



// re-init editor

$('#demo3').tagEditor({ placeholder: 'Enter tags ...' });

Callbacks


$('#demo4').tagEditor({

    initialTags: ['Hello', 'World'],

    placeholder: 'Enter tags ...',

    onChange: function(field, editor, tags) {

        $('#response').prepend(

            'Tags changed to: ' + (tags.length ? tags.join(', ') : '----') + '<hr>'

        );

    },

    beforeTagSave: function(field, editor, tags, tag, val) {

        $('#response').prepend('Tag ' + val + ' saved' + (tag ? ' over ' + tag : '') + '.');

    },

    beforeTagDelete: function(field, editor, tags, val) {

        var q = confirm('Remove tag "' + val + '"?');

        if (q) $('#response').prepend('Tag ' + val + ' deleted.');

        else $('#response').prepend('Removal of ' + val + ' discarded.');

        return q;

    }

});

Callback response:

Starting tags: hello, world

Custom style and clickDelete

Use right mouse click or Ctrl+left click to delete tags.


$('#demo5').tagEditor({

    clickDelete: true,

    initialTags: [ ... ],

    placeholder: 'Enter tags ...'

});

/* overwrite default CSS for tiny, dark tags */



#demo5+.tag-editor { background: #fafafa; font-size: 12px; }

#demo5+.tag-editor .tag-editor-tag {

    color: #fff; background: #555;

    border-radius: 2px;

}

#demo5+.tag-editor .tag-editor-spacer { width: 7px; }

#demo5+.tag-editor .tag-editor-delete { display: none; }

This jQuery plugin was designed with custom styling in mind. In this example we've enabled the clickDelete feature while hiding all delete icons. Both options may be used at the same time, as well. By fiddling around with the default stylesheet, you can achieve almost any desired look for your Tag Editor. Comments inside the CSS file will help you understand what rule controls which object inside the editor.

Custom CSS classes for tags

Using the onChange callback for adding custom CSS classes to specific tags.


$('#demo6').tagEditor({

    initialTags: ['custom', 'class', 'red', 'green', 'demo'],

    onChange: tag_classes

});



function tag_classes(field, editor, tags) {

    $('li', editor).each(function(){

        var li = $(this);

        if (li.find('.tag-editor-tag').html() == 'red') li.addClass('red-tag');

        else if (li.find('.tag-editor-tag').html() == 'green') li.addClass('green-tag')

        else li.removeClass('red-tag green-tag');

    });

}



// first assign tag classes after initializing tagEditor; onChange is not called on init

tag_classes(null, $('#demo6').tagEditor('getTags')[0].editor);

In the onChange callback we iterate over all tags and assign custom CSS classes where appropriate. The DOM structure of the editor looks like this:

<ul>

    <li>

        <div class="tag-editor-spacer"></div>

        <div class="tag-editor-tag">Tag content</div>

        <div class="tag-editor-delete"><i></i></div>

    </li>

    [...]

</ul>

In the example, we simply add CSS classes to the <li> elements. This is just an exampe of what the onChange callback may be used for. Inside of it, addTag and removeTag may be called to dynamically change the current list of tags.