jQuery Tags Input Plugin 改
jquery.tagsinput.js
根据jQuery Tags Input Plugin 1.3.3添加如下功能
·新增getTags()方法
·新增4个options[maxCount:0,lowerCase:false,upperCase:false,regex:'']
maxCount:默认值0,不限制tag数量,设定需要限定tag最大个数值
lowerCase:默认值false,若为true,tag转小写
upperCase:默认值false,若为true,tag转大写
regex:默认值空,可设置自定义验证 /^[\u4E00-\u9FA5\w\d\-+#.]+$/ ,英文数字汉字(除全角符号)可用符号(_-#.)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 jQuery Tags Input Plugin 1.3.3 3 Copyright (c) 2011 XOXCO, Inc 4 5 Documentation for this plugin lives here: 6 http://xoxco.com/clickable/jquery-tags-input 7 8 Licensed under the MIT license: 9 http://www.opensource.org/licenses/mit-license.php 10 11 ben@xoxco.com 12 ----------------------------------------1.3.3 Kai 0.1------------------------------------------- 13 jQuery Tags Input Plugin 1.3.3 Kai 0.1 14 what's new 15 add 1 function[getTags()] 16 add 4 options default[maxCount:0,lowerCase:false,upperCase:false,regex:''] 17 fix some error display addClass('not_valid') 18 2012-11-08 jsd.xug@sjtu.edu.cn 19 ------------------------------------------------------------------------------------------------ 20 */ 21 22 (function($) { 23 var kaiOptions=new Array(); 24 var delimiter = new Array(); 25 var tags_callbacks = new Array(); 26 $.fn.doAutosize = function(o){ 27 var minWidth = $(this).data('minwidth'), 28 maxWidth = $(this).data('maxwidth'), 29 val = '', 30 input = $(this), 31 testSubject = $('#'+$(this).data('tester_id')); 32 33 if (val === (val = input.val())) {return;} 34 35 // Enter new content into testSubject 36 var escaped = val.replace(/&/g, '&').replace(/\s/g,' ').replace(/</g, '<').replace(/>/g, '>'); 37 testSubject.html(escaped); 38 // Calculate new width + whether to change 39 var testerWidth = testSubject.width(), 40 newWidth = (testerWidth + o.comfortZone) >= minWidth ? testerWidth + o.comfortZone : minWidth, 41 currentWidth = input.width(), 42 isValidWidthChange = (newWidth < currentWidth && newWidth >= minWidth) 43 || (newWidth > minWidth && newWidth < maxWidth); 44 45 // Animate width 46 if (isValidWidthChange) { 47 input.width(newWidth); 48 } 49 50 51 }; 52 $.fn.resetAutosize = function(options){ 53 // alert(JSON.stringify(options)); 54 var minWidth = $(this).data('minwidth') || options.minInputWidth || $(this).width(), 55 maxWidth = $(this).data('maxwidth') || options.maxInputWidth || ($(this).closest('.tagsinput').width() - options.inputPadding), 56 val = '', 57 input = $(this), 58 testSubject = $('<tester/>').css({ 59 position: 'absolute', 60 top: -9999, 61 left: -9999, 62 width: 'auto', 63 fontSize: input.css('fontSize'), 64 fontFamily: input.css('fontFamily'), 65 fontWeight: input.css('fontWeight'), 66 letterSpacing: input.css('letterSpacing'), 67 whiteSpace: 'nowrap' 68 }), 69 testerId = $(this).attr('id')+'_autosize_tester'; 70 if(! $('#'+testerId).length > 0){ 71 testSubject.attr('id', testerId); 72 testSubject.appendTo('body'); 73 } 74 75 input.data('minwidth', minWidth); 76 input.data('maxwidth', maxWidth); 77 input.data('tester_id', testerId); 78 input.css('width', minWidth); 79 }; 80 81 $.fn.getTags = function() { 82 var id = $(this).attr('id'); 83 var tagslist = $(this).val().split(delimiter[id]); 84 return tagslist; 85 }; 86 87 $.fn.addTag = function(value,options) { 88 options = jQuery.extend({focus:false,callback:true},options); 89 this.each(function() { 90 var id = $(this).attr('id'); 91 92 var tagslist = $(this).val().split(delimiter[id]); 93 if (tagslist[0] == '') { 94 tagslist = new Array(); 95 } 96 97 var maxCount=kaiOptions[id]['maxCount']; 98 if(maxCount>0 && tagslist.length>maxCount-1){ 99 $('#'+id+'_tag').addClass('not_valid'); 100 return; 101 } 102 103 var lowerCase=kaiOptions[id]['lowerCase']; 104 var upperCase=kaiOptions[id]['upperCase']; 105 106 if(lowerCase && upperCase){ 107 value = jQuery.trim(value); 108 } 109 else{ 110 if(lowerCase){ 111 value = jQuery.trim(value.toLowerCase()); 112 } 113 if(upperCase){ 114 value = jQuery.trim(value.toUpperCase()); 115 } 116 } 117 118 var _reg=kaiOptions[id]['regex']; 119 if(jQuery.trim(_reg).length>0){ 120 if(!_reg.exec(value)){ 121 $('#'+id+'_tag').addClass('not_valid'); 122 return; 123 } 124 } 125 126 if (options.unique) { 127 var skipTag = $(this).tagExist(value); 128 if(skipTag == true) { 129 //Marks fake input as not_valid to let styling it 130 $('#'+id+'_tag').addClass('not_valid'); 131 } 132 } else { 133 var skipTag = false; 134 } 135 136 if (value !='' && skipTag != true) { 137 $('<span>').addClass('tag').append( 138 $('<span>').text(value).append(' '), 139 $('<a>', { 140 href : '#', 141 title : 'Removing tag', 142 text : 'x' 143 }).click(function () { 144 return $('#' + id).removeTag(escape(value)); 145 }) 146 ).insertBefore('#' + id + '_addTag'); 147 148 tagslist.push(value); 149 150 $('#'+id+'_tag').val(''); 151 if (options.focus) { 152 $('#'+id+'_tag').focus(); 153 } else { 154 $('#'+id+'_tag').blur(); 155 } 156 157 $.fn.tagsInput.updateTagsField(this,tagslist); 158 159 if (options.callback && tags_callbacks[id] && tags_callbacks[id]['onAddTag']) { 160 var f = tags_callbacks[id]['onAddTag']; 161 f.call(this, value); 162 } 163 if(tags_callbacks[id] && tags_callbacks[id]['onChange']) 164 { 165 var i = tagslist.length; 166 var f = tags_callbacks[id]['onChange']; 167 f.call(this, $(this), tagslist[i-1]); 168 } 169 } 170 171 }); 172 173 return false; 174 }; 175 176 $.fn.removeTag = function(value) { 177 value = unescape(value); 178 this.each(function() { 179 var id = $(this).attr('id'); 180 181 var old = $(this).val().split(delimiter[id]); 182 183 $('#'+id+'_tagsinput .tag').remove(); 184 str = ''; 185 for (i=0; i< old.length; i++) { 186 if (old[i]!=value) { 187 str = str + delimiter[id] +old[i]; 188 } 189 } 190 191 $.fn.tagsInput.importTags(this,str); 192 193 if (tags_callbacks[id] && tags_callbacks[id]['onRemoveTag']) { 194 var f = tags_callbacks[id]['onRemoveTag']; 195 f.call(this, value); 196 } 197 }); 198 199 return false; 200 }; 201 202 $.fn.tagExist = function(val) { 203 var id = $(this).attr('id'); 204 var tagslist = $(this).val().split(delimiter[id]); 205 return (jQuery.inArray(val, tagslist) >= 0); //true when tag exists, false when not 206 }; 207 208 // clear all existing tags and import new ones from a string 209 $.fn.importTags = function(str) { 210 var id = $(this).attr('id'); 211 $('#' + id + '_tagsinput .tag').remove(); 212 $.fn.tagsInput.importTags(this, str); 213 }; 214 215 $.fn.tagsInput = function(options) { 216 var settings = jQuery.extend({ 217 interactive:true, 218 defaultText:'add a tag', 219 minChars:0, 220 width:'300px', 221 height:'100px', 222 autocomplete: {selectFirst: false }, 223 'hide':true, 224 'delimiter':',', 225 'unique':true, 226 removeWithBackspace:true, 227 placeholderColor:'#666666', 228 autosize: true, 229 comfortZone: 20, 230 inputPadding: 6*2, 231 maxCount:0, 232 lowerCase:false, 233 upperCase:false, 234 regex:'' 235 },options); 236 237 this.each(function() { 238 if (settings.hide) { 239 $(this).hide(); 240 } 241 var id = $(this).attr('id'); 242 if (!id || delimiter[$(this).attr('id')]) { 243 id = $(this).attr('id', 'tags' + new Date().getTime()).attr('id'); 244 } 245 246 var data = jQuery.extend({ 247 pid:id, 248 real_input: '#'+id, 249 holder: '#'+id+'_tagsinput', 250 input_wrapper: '#'+id+'_addTag', 251 fake_input: '#'+id+'_tag' 252 },settings); 253 254 kaiOptions[id]=new Array(); 255 kaiOptions[id]['maxCount']=settings.maxCount; 256 kaiOptions[id]['lowerCase']=settings.lowerCase; 257 kaiOptions[id]['upperCase']=settings.upperCase; 258 kaiOptions[id]['regex']=settings.regex; 259 delimiter[id] = data.delimiter; 260 261 if (settings.onAddTag || settings.onRemoveTag || settings.onChange) { 262 tags_callbacks[id] = new Array(); 263 tags_callbacks[id]['onAddTag'] = settings.onAddTag; 264 tags_callbacks[id]['onRemoveTag'] = settings.onRemoveTag; 265 tags_callbacks[id]['onChange'] = settings.onChange; 266 } 267 268 var markup = '<div id="'+id+'_tagsinput" class="tagsinput"><div id="'+id+'_addTag">'; 269 270 if (settings.interactive) { 271 markup = markup + '<input id="'+id+'_tag" value="" data-default="'+settings.defaultText+'" />'; 272 } 273 274 markup = markup + '</div><div class="tags_clear"></div></div>'; 275 276 $(markup).insertAfter(this); 277 278 $(data.holder).css('width',settings.width); 279 $(data.holder).css('min-height',settings.height); 280 $(data.holder).css('height','100%'); 281 282 if ($(data.real_input).val()!='') { 283 $.fn.tagsInput.importTags($(data.real_input),$(data.real_input).val()); 284 } 285 if (settings.interactive) { 286 $(data.fake_input).val($(data.fake_input).attr('data-default')); 287 $(data.fake_input).css('color',settings.placeholderColor); 288 $(data.fake_input).resetAutosize(settings); 289 290 $(data.holder).bind('click',data,function(event) { 291 $(event.data.fake_input).focus(); 292 }); 293 294 $(data.fake_input).bind('focus',data,function(event) { 295 if ($(event.data.fake_input).val()==$(event.data.fake_input).attr('data-default')) { 296 $(event.data.fake_input).val(''); 297 } 298 $(event.data.fake_input).css('color','#000000'); 299 }); 300 301 if (settings.autocomplete_url != undefined) { 302 autocomplete_options = {source: settings.autocomplete_url}; 303 for (attrname in settings.autocomplete) { 304 autocomplete_options[attrname] = settings.autocomplete[attrname]; 305 } 306 307 308 if (jQuery.Autocompleter !== undefined) { 309 $(data.fake_input).autocomplete(settings.autocomplete_url, settings.autocomplete); 310 $(data.fake_input).bind('result',data,function(event,data,formatted) { 311 if (data) { 312 //$('#'+id).addTag(data[0] + "",{focus:true,unique:(settings.unique)}); 313 $('#'+id).addTag(data + "",{focus:true,unique:(settings.unique)}); 314 } 315 }); 316 } else if (jQuery.ui.autocomplete !== undefined) { 317 $(data.fake_input).autocomplete(autocomplete_options); 318 $(data.fake_input).bind('autocompleteselect',data,function(event,ui) { 319 $(event.data.real_input).addTag(ui.item.value,{focus:true,unique:(settings.unique)}); 320 return false; 321 }); 322 } 323 324 325 } else { 326 // if a user tabs out of the field, create a new tag 327 // this is only available if autocomplete is not used. 328 $(data.fake_input).bind('blur',data,function(event) { 329 var d = $(this).attr('data-default'); 330 if ($(event.data.fake_input).val()!='' && $(event.data.fake_input).val()!=d) { 331 if( (event.data.minChars <= $(event.data.fake_input).val().length) && (!event.data.maxChars || (event.data.maxChars >= $(event.data.fake_input).val().length)) ) 332 $(event.data.real_input).addTag($(event.data.fake_input).val(),{focus:true,unique:(settings.unique)}); 333 } else { 334 $(event.data.fake_input).val($(event.data.fake_input).attr('data-default')); 335 $(event.data.fake_input).css('color',settings.placeholderColor); 336 } 337 return false; 338 }); 339 340 } 341 // if user types a comma, create a new tag 342 $(data.fake_input).bind('keypress',data,function(event) { 343 if (event.which==event.data.delimiter.charCodeAt(0) || event.which==13 ) { 344 event.preventDefault(); 345 if( (event.data.minChars <= $(event.data.fake_input).val().length) && (!event.data.maxChars || (event.data.maxChars >= $(event.data.fake_input).val().length)) ) 346 $(event.data.real_input).addTag($(event.data.fake_input).val(),{focus:true,unique:(settings.unique)}); 347 $(event.data.fake_input).resetAutosize(settings); 348 return false; 349 } else if (event.data.autosize) { 350 $(event.data.fake_input).doAutosize(settings); 351 352 } 353 }); 354 //Delete last tag on backspace 355 data.removeWithBackspace && $(data.fake_input).bind('keydown', function(event) 356 { 357 if(event.keyCode == 8 && $(this).val() == '') 358 { 359 event.preventDefault(); 360 var last_tag = $(this).closest('.tagsinput').find('.tag:last').text(); 361 var id = $(this).attr('id').replace(/_tag$/, ''); 362 last_tag = last_tag.replace(/[\s]+x$/, ''); 363 $('#' + id).removeTag(escape(last_tag)); 364 $(this).trigger('focus'); 365 } 366 }); 367 $(data.fake_input).blur(); 368 369 //Removes the not_valid class when user changes the value of the fake input 370 if(data.unique) { 371 $(data.fake_input).keydown(function(event){ 372 if(event.keyCode == 8 || String.fromCharCode(event.which).match(/\w+|[áéíóúÁÉÍÓÚñÑ,/]+/)) { 373 $(this).removeClass('not_valid'); 374 } 375 }); 376 } 377 } // if settings.interactive 378 }); 379 380 return this; 381 382 }; 383 384 $.fn.tagsInput.updateTagsField = function(obj,tagslist) { 385 var id = $(obj).attr('id'); 386 $(obj).val(tagslist.join(delimiter[id])); 387 }; 388 389 $.fn.tagsInput.importTags = function(obj,val) { 390 $(obj).val(''); 391 var id = $(obj).attr('id'); 392 var tags = val.split(delimiter[id]); 393 for (i=0; i<tags.length; i++) { 394 $(obj).addTag(tags[i],{focus:false,callback:false}); 395 } 396 if(tags_callbacks[id] && tags_callbacks[id]['onChange']) 397 { 398 var f = tags_callbacks[id]['onChange']; 399 f.call(obj, obj, tags[i]); 400 } 401 }; 402 403 })(jQuery);
初始化参数
1 $(selector).tagsInput({ 2 'autocomplete_url': url_to_autocomplete_api, 3 'autocomplete': { option: value, option: value}, 4 'height':'100px', 5 'width':'300px', 6 'interactive':true, 7 'defaultText':'add a tag', 8 'onAddTag':callback_function, 9 'onRemoveTag':callback_function, 10 'onChange' : callback_function, 11 'removeWithBackspace' : true, 12 'minChars' : 0, 13 'maxChars' : 0, //if not provided there is no limit 14 'placeholderColor' : '#666666', 15 'maxCount':20, //tags max count 16 'lowerCase':false, 17 'upperCase':false, 18 'regex':/^[\u4E00-\u9FA5\w\d\-+#.]+$/ 19 });
获取tags结果集
1 $('#tags_1').getTags();
不通过getTags获取结果集方法
1 function getTags(){ 2 var $tagWord =$("#tags_1").siblings(".tagsinput").children(".tag"); 3 var tags = []; 4 for (var i = $tagWord.length; i--; ) { 5 tags.push($($tagWord[i]).text().substring(0, $($tagWord[i]).text().length - 1).trim()); 6 } 7 var uqTags = $.unique(tags); 8 return ugTags; 9 }
example.html部分代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <script type="text/javascript"> 2 3 function onAddTag(tag) { 4 alert("Added a tag: " + tag); 5 } 6 function onRemoveTag(tag) { 7 alert("Removed a tag: " + tag); 8 } 9 10 function onChangeTag(input,tag) { 11 alert("Changed a tag: " + tag); 12 } 13 14 $(function() { 15 16 $('#tags_1').tagsInput({'width':'300px','height':'100px','minChars':0,'maxChars':10,'maxCount':5,'lowerCase':true}); 17 $('#tags_2').tagsInput({ 18 'width':'300px','height':'100px','maxCount':7,'upperCase':true, 19 onChange: function(elem, elem_tags) 20 { 21 var languages = ['php','ruby','javascript']; 22 $('.tag', elem_tags).each(function() 23 { 24 if($(this).text().search(new RegExp('\\b(' + languages.join('|') + ')\\b')) >= 0) 25 $(this).css('background-color', 'yellow'); 26 }); 27 } 28 }); 29 $('#tags_3').tagsInput({ 30 'width':'300px','height':'100px','maxCount':10, 31 //autocomplete_url:'test/fake_plaintext_endpoint.html' //jquery.autocomplete (not jquery ui) 32 autocomplete_url:'test/fake_json_endpoint.html' // jquery ui autocomplete requires a json endpoint 33 }); 34 $('#result1').click(function(){alert($('#tags_1').getTags())}); 35 $('#result2').click(function(){alert($('#tags_2').getTags())}); 36 $('#result3').click(function(){alert($('#tags_3').getTags())}); 37 38 // Uncomment this line to see the callback functions in action 39 // $('input.tags').tagsInput({onAddTag:onAddTag,onRemoveTag:onRemoveTag,onChange: onChangeTag}); 40 41 // Uncomment this line to see an input with no interface for adding new tags. 42 // $('input.tags').tagsInput({interactive:false}); 43 }); 44 45 </script> 46 <div> 47 <p><label>Defaults:</label> 48 <input id="tags_1" type="text" class="tags" value="foo,bar,baz,roffle" /></p> 49 <span id="result1">result</span> 50 <p><label>Technologies: (Programming languages in yellow)</label> 51 <input id="tags_2" type="text" class="tags" value="php,ios,javascript,ruby,android,kindle" /></p> 52 <span id="result2">result</span> 53 <p><label>Autocomplete:</label> 54 <input id='tags_3' type='text' class='tags'></p> 55 <span id="result2">result</span> 56 </div>