Skip to content

Instantly share code, notes, and snippets.

@matteodelabre
Last active August 29, 2015 14:04
Show Gist options
  • Save matteodelabre/d19ca9aecff5fb332c41 to your computer and use it in GitHub Desktop.
Save matteodelabre/d19ca9aecff5fb332c41 to your computer and use it in GitHub Desktop.
jQuery plugin that enables to easily add tags into an input

Tagger

jQuery plugin that enables to easily add tags into an input, graciously degrading when JS is disabled.
Can filter tags content but still need server-side check.

NOTE: you need to add a js class to the body element when JS is enabled for this plugin to work.

How to use:

$('.myinput').tagger();

Parameters

  • text
    • placeholder: tags input placeholder
    • remove: cta for removing tag
  • forbid: forbidden characters in tags

License

None, do what you want.

body.js input.tagger {
display: none;
}
body:not(.js) input.tagger + div.tagger-list {
display: none;
}
div.tagger-list, input.tagger {
border: 1px solid black;
position: relative;
min-width: 150px;
max-width: 400px;
margin: 5px 2px;
min-height: 23px;
padding: 2px 0 0 6px;
}
div.tagger-list .tagger-add {
position: absolute;
bottom: 0;
left: 0;
padding: 0 6px;
margin: 0;
border: 0;
background: transparent;
line-height: 27px;
overflow: hidden;
font-size: 14px;
font-family: Verdana;
box-sizing: border-box;
z-index: 1;
resize: none;
width: 100%;
height: 26px;
}
div.tagger-list .tagger-add:focus {
outline: none;
}
div.tagger-list .tag {
display: inline-block;
background: #e67e22;
color: white;
position: relative;
z-index: 2;
user-select: none;
vertical-align: middle;
min-height: 15px;
padding: 2px 5px;
font-size: 13px;
line-height: 15px;
margin: 0 5px 3px 0;
cursor: pointer;
word-break: break-all;
overflow: hidden;
transition: background, width 1s, 0.2s ease-out;
}
div.tagger-list .tag.animate {
word-break: initial;
}
div.tagger-list .tag:after {
content: " ×";
}
div.tagger-list .tag:hover {
background: #F0671D;
}
/*jslint browser: true, regexp: true */
/*globals jQuery */
(function ($) {
'use strict';
$.fn.tagger = function (params) {
var defaults = {
forbid: /[^a-zA-Z0-9\-]/g,
text: {
placeholder: 'Write tags then press return…',
remove: 'Click to remove'
}
}, nextTagId = 0;
params = $.extend(defaults, params);
return this.each(function () {
var jq, taggerList, taggerAdd;
jq = $(this);
jq.addClass('tagger');
taggerList = $('<div />', {
'class': 'tagger-list'
}).insertAfter(jq);
taggerAdd = $('<textarea />', {
'class': 'tagger-add'
}).appendTo(taggerList);
// updates text input with tags divs
function updateInput() {
var tagList = [], lastTag = taggerList.find('.tag').last(),
padding;
// list all tags in text/object form
$('.tag').each(function () {
tagList.push(($(this)).text());
});
// adds a padding to the textbox depending on last tag position
if (lastTag.length > 0) {
padding = lastTag.position().left +
lastTag.outerWidth(true);
} else {
padding = parseInt(taggerList.css('padding-left'), 10);
}
taggerAdd.css('padding-left', padding);
// display placeholder
if (tagList.length === 0) {
taggerAdd.attr('placeholder', params.text.placeholder);
} else {
taggerAdd.attr('placeholder', '');
}
// update text input with real values
jq.val(tagList.join(','));
}
// adds a new tag
function addTag(tag) {
tag = tag.replace(params.forbid, '');
if (!tag) {
return;
}
var width, el;
el = $('<div />', {
'class': 'tag',
'data-tagid': nextTagId,
'title': params.text.remove
});
el.
text(tag).
appendTo(taggerList);
width = el.width();
updateInput();
el.addClass('animate').width(0);
el.width(width);
setTimeout(function () {
el.removeClass('animate');
}, 500);
nextTagId += 1;
}
// deletes a tag
function deleteTag(id) {
taggerList.find('[data-tagid="' + id + '"]').remove();
updateInput();
}
// delete a tag by clicking it
taggerList.on('click', '.tag', function () {
deleteTag($(this).attr('data-tagid'));
});
// add/delete tag on return/back
taggerAdd.on('keyup', function (e) {
var tags, length, i, lastTagId;
if (e.which === 13 || e.keyCode === 13) {
tags = taggerAdd.val().split(',');
length = tags.length;
for (i = 0; i < length; i += 1) {
addTag($.trim(tags[i]));
}
taggerAdd.val('');
// prevents from sending form
e.preventDefault();
}
if ((e.which === 8 || e.keyCode === 8)
&& taggerAdd.val() === '') {
lastTagId = taggerList.find('.tag').last().attr('data-tagid');
deleteTag(parseInt(lastTagId, 10));
// prevents from going back
e.preventDefault();
}
});
// inital update
updateInput();
});
};
}(jQuery));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment