├── .gitignore
├── Gruntfile.js
├── README.md
├── bower.json
├── dist
├── jquery.tagsinput.min.css
└── jquery.tagsinput.min.js
├── example.html
├── grunt-tasks
├── assets_production.js
└── options
│ ├── cssmin.js
│ └── uglify.js
├── package.json
├── src
├── jquery.tagsinput.css
└── jquery.tagsinput.js
└── test
├── fake_json_endpoint.html
└── fake_plaintext_endpoint.html
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | bower_components/
3 | lib/
4 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | function loadConfig(path) {
2 | var glob = require('glob');
3 | var object = {};
4 | var key;
5 |
6 | glob.sync('*', {cwd: path}).forEach(function(option) {
7 | key = option.replace(/\.js$/,'');
8 | object[key] = require(path + option);
9 | });
10 |
11 | return object;
12 | }
13 |
14 | module.exports = function(grunt) {
15 | grunt.loadTasks('grunt-tasks');
16 |
17 | require('time-grunt')(grunt);
18 |
19 | // Only load tasks when they are needed
20 | require('jit-grunt')(grunt, {
21 | ngtemplates: 'grunt-angular-templates'
22 | });
23 |
24 | var config = {
25 | pkg: grunt.file.readJSON('package.json'),
26 | env: process.env
27 | };
28 |
29 | grunt.util._.extend(config, loadConfig('./grunt-tasks/options/'));
30 | grunt.initConfig(config);
31 | };
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # jQuery Tags Input Plugin
2 |
3 | Do you use tags to organize content on your site?
4 | This plugin will turn your boring tag list into a
5 | magical input that turns each tag into a style-able
6 | object with its own delete link. The plugin handles
7 | all the data - your form just sees a comma-delimited
8 | list of tags!
9 |
10 | [Get it from Github](https://github.com/xoxco/jQuery-Tags-Input)
11 |
12 | [View Demo](http://xoxco.com/projects/code/tagsinput/)
13 |
14 | [Test it yourself using this jsFiddle Demo](http://jsfiddle.net/7aDak/)
15 |
16 | Created by [XOXCO](http://xoxco.com)
17 |
18 |
19 | ## Instructions
20 |
21 | First, add the Javascript and CSS files to your
tag:
22 |
23 |
24 |
25 |
26 | Create a real input in your form that will contain a comma-separated list of
27 | tags. You can put any default or existing tags in the value attribute, and
28 | they'll be handled properly.
29 |
30 |
31 |
32 | Then, simply call the tagsInput function on any field that should be treated as
33 | a list of tags.
34 |
35 | $('#tags').tagsInput();
36 |
37 | If you want to use jQuery.autocomplete, you can pass in a parameter with the
38 | autocomplete url.
39 |
40 | $('#tags').tagsInput({
41 | autocomplete_url:'http://myserver.com/api/autocomplete'
42 | });
43 |
44 | If you're using the bassistance jQuery.autocomplete, which takes extra
45 | parameters, you can also send in options to the autocomplete plugin, as
46 | described here.
47 |
48 | $('#tags').tagsInput({
49 | autocomplete_url:'http://myserver.com/api/autocomplete',
50 | autocomplete:{selectFirst:true,width:'100px',autoFill:true}
51 | });
52 |
53 | You can add and remove tags by calling the addTag() and removeTag() functions.
54 |
55 | $('#tags').addTag('foo');
56 | $('#tags').removeTag('bar');
57 |
58 | You can import a list of tags using the importTags() function...
59 |
60 | $('#tags').importTags('foo,bar,baz');
61 |
62 | You can also use importTags() to reset the tag list...
63 |
64 | $('#tags').importTags('');
65 |
66 | And you can check if a tag exists using tagExist()...
67 |
68 | if ($('#tags').tagExist('foo')) { ... }
69 |
70 | If additional functionality is required when a tag is added or removed, you may
71 | specify callback functions via the onAddTag and onRemoveTag parameters. Both
72 | functions should accept a single tag as the parameter.
73 |
74 | If you do not want to provide a way to add tags, or you would prefer to provide
75 | an alternate interface for adding tags to the box, you may pass an false into
76 | the optional 'interactive' parameter. The tags will still be rendered as per
77 | usual, and the addTag and removeTag functions will operate as expected.
78 |
79 | If you want a function to be called every time a tag is updated/deleted, set it
80 | as the 'onChange' option.
81 |
82 | By default, if the cursor is immediately after a tag, hitting backspace will
83 | delete that tag. If you want to override this, set the 'removeWithBackspace'
84 | option to false.
85 |
86 | ## Options
87 |
88 | $(selector).tagsInput({
89 | 'autocomplete_url': url_to_autocomplete_api,
90 | 'autocomplete': { option: value, option: value},
91 | 'height':'100px',
92 | 'width':'300px',
93 | 'interactive':true,
94 | 'defaultText':'add a tag',
95 | 'onAddTag':callback_function,
96 | 'onRemoveTag':callback_function,
97 | 'onChange' : callback_function,
98 | 'delimiter': [',',';'], // Or a string with a single delimiter. Ex: ';'
99 | 'removeWithBackspace' : true,
100 | 'minChars' : 0,
101 | 'maxChars' : 0, // if not provided there is no limit
102 | 'placeholderColor' : '#666666'
103 | });
104 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jquery.tagsinput",
3 | "main": ["src/jquery.tagsinput.js", "src/jquery.tagsinput.css"],
4 | "ignore": [
5 | "**/.*",
6 | "*.html",
7 | "*.md",
8 | "*.json",
9 | "*.min.js",
10 | "test"
11 | ],
12 | "dependencies": {
13 | "jquery": "1.x"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/dist/jquery.tagsinput.min.css:
--------------------------------------------------------------------------------
1 | div.tagsinput{border:1px solid #CCC;background:#FFF;padding:5px;width:300px;height:100px;overflow-y:auto}div.tagsinput span.tag{border:1px solid #a5d24a;-moz-border-radius:2px;-webkit-border-radius:2px;display:block;float:left;padding:5px;text-decoration:none;background:#cde69c;color:#638421;margin-right:5px;margin-bottom:5px;font-family:helvetica;font-size:13px}div.tagsinput span.tag a{font-weight:700;color:#82ad2b;text-decoration:none;font-size:11px}div.tagsinput input{width:80px;margin:0 5px 5px 0;font-family:helvetica;font-size:13px;border:1px solid transparent;padding:5px;background:0 0;color:#000;outline:0}div.tagsinput div{display:block;float:left}.tags_clear{clear:both;width:100%;height:0}.not_valid{background:#FBD8DB!important;color:#90111A!important}
--------------------------------------------------------------------------------
/dist/jquery.tagsinput.min.js:
--------------------------------------------------------------------------------
1 | !function(a){var b=new Array,c=new Array;a.fn.doAutosize=function(b){var c=a(this).data("minwidth"),d=a(this).data("maxwidth"),e="",f=a(this),g=a("#"+a(this).data("tester_id"));if(e!==(e=f.val())){var h=e.replace(/&/g,"&").replace(/\s/g," ").replace(//g,">");g.html(h);var i=g.width(),j=i+b.comfortZone>=c?i+b.comfortZone:c,k=f.width(),l=k>j&&j>=c||j>c&&d>j;l&&f.width(j)}},a.fn.resetAutosize=function(b){var c=a(this).data("minwidth")||b.minInputWidth||a(this).width(),d=a(this).data("maxwidth")||b.maxInputWidth||a(this).closest(".tagsinput").width()-b.inputPadding,e=a(this),f=a("").css({position:"absolute",top:-9999,left:-9999,width:"auto",fontSize:e.css("fontSize"),fontFamily:e.css("fontFamily"),fontWeight:e.css("fontWeight"),letterSpacing:e.css("letterSpacing"),whiteSpace:"nowrap"}),g=a(this).attr("id")+"_autosize_tester";!a("#"+g).length>0&&(f.attr("id",g),f.appendTo("body")),e.data("minwidth",c),e.data("maxwidth",d),e.data("tester_id",g),e.css("width",c)},a.fn.addTag=function(d,e){return e=jQuery.extend({focus:!1,callback:!0},e),this.each(function(){var f=a(this).attr("id"),g=a(this).val().split(b[f]);if(""==g[0]&&(g=new Array),d=jQuery.trim(d),e.unique){var h=a(this).tagExist(d);1==h&&a("#"+f+"_tag").addClass("not_valid")}else var h=!1;if(""!=d&&1!=h){if(a("").addClass("tag").append(a("").text(d).append(" "),a("",{href:"#",title:"Removing tag",text:"x"}).click(function(){return a("#"+f).removeTag(escape(d))})).insertBefore("#"+f+"_addTag"),g.push(d),a("#"+f+"_tag").val(""),e.focus?a("#"+f+"_tag").focus():a("#"+f+"_tag").blur(),a.fn.tagsInput.updateTagsField(this,g),e.callback&&c[f]&&c[f].onAddTag){var i=c[f].onAddTag;i.call(this,d)}if(c[f]&&c[f].onChange){var j=g.length,i=c[f].onChange;i.call(this,a(this),g[j-1])}}}),!1},a.fn.removeTag=function(d){return d=unescape(d),this.each(function(){var e=a(this).attr("id"),f=a(this).val().split(b[e]);for(a("#"+e+"_tagsinput .tag").remove(),str="",i=0;i=0},a.fn.importTags=function(b){var c=a(this).attr("id");a("#"+c+"_tagsinput .tag").remove(),a.fn.tagsInput.importTags(this,b)},a.fn.tagsInput=function(e){var f=jQuery.extend({interactive:!0,defaultText:"add a tag",minChars:0,width:"300px",height:"100px",autocomplete:{selectFirst:!1},hide:!0,delimiter:",",unique:!0,removeWithBackspace:!0,placeholderColor:"#666666",autosize:!0,comfortZone:20,inputPadding:12},e),g=0;return this.each(function(){if("undefined"==typeof a(this).attr("data-tagsinput-init")){a(this).attr("data-tagsinput-init",!0),f.hide&&a(this).hide();var e=a(this).attr("id");(!e||b[a(this).attr("id")])&&(e=a(this).attr("id","tags"+(new Date).getTime()+g++).attr("id"));var h=jQuery.extend({pid:e,real_input:"#"+e,holder:"#"+e+"_tagsinput",input_wrapper:"#"+e+"_addTag",fake_input:"#"+e+"_tag"},f);b[e]=h.delimiter,(f.onAddTag||f.onRemoveTag||f.onChange)&&(c[e]=new Array,c[e].onAddTag=f.onAddTag,c[e].onRemoveTag=f.onRemoveTag,c[e].onChange=f.onChange);var i='