提交 | 用户 | 时间
|
8286c6
|
1 |
/* |
懒 |
2 |
jQuery Tags Input Plugin 1.3.3 |
|
3 |
Copyright (c) 2011 XOXCO, Inc |
|
4 |
Documentation for this plugin lives here: |
|
5 |
http://xoxco.com/clickable/jquery-tags-input |
|
6 |
Licensed under the MIT license: |
|
7 |
http://www.opensource.org/licenses/mit-license.php |
|
8 |
ben@xoxco.com |
|
9 |
*/ |
|
10 |
(function (factory) { |
|
11 |
if (typeof define === 'function' && define.amd) { |
|
12 |
// AMD. Register as an anonymous module. |
|
13 |
define(['jquery'], factory); |
|
14 |
} else if (typeof exports === 'object') { |
|
15 |
// Node/CommonJS style for Browserify |
|
16 |
module.exports = factory; |
|
17 |
} else if (window.layui && layui.define) { // layui加载 |
|
18 |
layui.define('jquery', function (exports) { |
|
19 |
var $ = layui.jquery; |
|
20 |
layui.link(layui.cache.base + 'tagsInput/tagsInput.css'); |
|
21 |
exports('tagsInput', factory($)); |
|
22 |
}); |
|
23 |
} else { |
|
24 |
// Browser globals |
|
25 |
factory(jQuery); |
|
26 |
} |
|
27 |
}(function ($) { |
|
28 |
var jQuery = $; |
|
29 |
var delimiter = new Array(); |
|
30 |
var tags_callbacks = new Array(); |
|
31 |
$.fn.doAutosize = function (o) { |
|
32 |
var minWidth = $(this).data('minwidth'), |
|
33 |
maxWidth = $(this).data('maxwidth'), |
|
34 |
val = '', |
|
35 |
input = $(this), |
|
36 |
testSubject = $('#' + $(this).data('tester_id')); |
|
37 |
|
|
38 |
if (val === (val = input.val())) { |
|
39 |
return; |
|
40 |
} |
|
41 |
|
|
42 |
// Enter new content into testSubject |
|
43 |
var escaped = val.replace(/&/g, '&').replace(/\s/g, ' ').replace(/</g, '<').replace(/>/g, '>'); |
|
44 |
testSubject.html(escaped); |
|
45 |
// Calculate new width + whether to change |
|
46 |
var testerWidth = testSubject.width(), |
|
47 |
newWidth = (testerWidth + o.comfortZone) >= minWidth ? testerWidth + o.comfortZone : minWidth, |
|
48 |
currentWidth = input.width(), |
|
49 |
isValidWidthChange = (newWidth < currentWidth && newWidth >= minWidth) |
|
50 |
|| (newWidth > minWidth && newWidth < maxWidth); |
|
51 |
|
|
52 |
// Animate width |
|
53 |
if (isValidWidthChange) { |
|
54 |
input.width(newWidth); |
|
55 |
} |
|
56 |
|
|
57 |
|
|
58 |
}; |
|
59 |
$.fn.resetAutosize = function (options) { |
|
60 |
var minWidth = $(this).data('minwidth') || options.minInputWidth || $(this).width(), |
|
61 |
maxWidth = $(this).data('maxwidth') || options.maxInputWidth || ($(this).closest('.tagsinput').width() - options.inputPadding), |
|
62 |
val = '', |
|
63 |
input = $(this), |
|
64 |
testSubject = $('<tester/>').css({ |
|
65 |
position: 'absolute', |
|
66 |
top: -9999, |
|
67 |
left: -9999, |
|
68 |
width: 'auto', |
|
69 |
fontSize: input.css('fontSize'), |
|
70 |
fontFamily: input.css('fontFamily'), |
|
71 |
fontWeight: input.css('fontWeight'), |
|
72 |
letterSpacing: input.css('letterSpacing'), |
|
73 |
whiteSpace: 'nowrap' |
|
74 |
}), |
|
75 |
testerId = $(this).attr('id') + '_autosize_tester'; |
|
76 |
if (!$('#' + testerId).length > 0) { |
|
77 |
testSubject.attr('id', testerId); |
|
78 |
testSubject.appendTo('body'); |
|
79 |
} |
|
80 |
|
|
81 |
// input.data('minwidth', minWidth); |
|
82 |
input.data('maxwidth', maxWidth); |
|
83 |
input.data('tester_id', testerId); |
|
84 |
// input.css('width', minWidth); |
|
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 |
value = jQuery.trim(value); |
|
98 |
|
|
99 |
if (options.unique) { |
|
100 |
var skipTag = $(this).tagExist(value); |
|
101 |
if (skipTag == true) { |
|
102 |
//Marks fake input as not_valid to let styling it |
|
103 |
$('#' + id + '_tag').addClass('not_valid'); |
|
104 |
} |
|
105 |
} else { |
|
106 |
var skipTag = false; |
|
107 |
} |
|
108 |
|
|
109 |
if (value != '' && skipTag != true) { |
|
110 |
var closeText = '<span class="default-close-text">×</span>'; |
|
111 |
if (layui) { |
|
112 |
closeText = '<i class="layui-icon layui-icon-close"></i>'; |
|
113 |
} |
|
114 |
$('<span>').addClass('tag').append( |
|
115 |
$('<span>').text(value).append(' '), |
|
116 |
$('<a>', { |
|
117 |
href: 'javascript:;', |
|
118 |
title: '移除', |
|
119 |
html: closeText |
|
120 |
}).click(function () { |
|
121 |
return $('#' + id).removeTag(escape(value)); |
|
122 |
}) |
|
123 |
).insertBefore('#' + id + '_addTag'); |
|
124 |
|
|
125 |
tagslist.push(value); |
|
126 |
|
|
127 |
$('#' + id + '_tag').val(''); |
|
128 |
$('#' + id + '_tag').parent().find('.tagsinput-tip-list').remove(); |
|
129 |
if (options.focus) { |
|
130 |
$('#' + id + '_tag').focus(); |
|
131 |
} else { |
|
132 |
$('#' + id + '_tag').blur(); |
|
133 |
} |
|
134 |
|
|
135 |
$.fn.tagsInput.updateTagsField(this, tagslist); |
|
136 |
|
|
137 |
if (options.callback && tags_callbacks[id] && tags_callbacks[id]['onAddTag']) { |
|
138 |
var f = tags_callbacks[id]['onAddTag']; |
|
139 |
f.call(this, value); |
|
140 |
} |
|
141 |
if (tags_callbacks[id] && tags_callbacks[id]['onChange']) { |
|
142 |
var i = tagslist.length; |
|
143 |
var f = tags_callbacks[id]['onChange']; |
|
144 |
f.call(this, $(this), tagslist[i - 1]); |
|
145 |
} |
|
146 |
} |
|
147 |
|
|
148 |
}); |
|
149 |
|
|
150 |
return false; |
|
151 |
}; |
|
152 |
|
|
153 |
$.fn.removeTag = function (value) { |
|
154 |
value = unescape(value); |
|
155 |
this.each(function () { |
|
156 |
var id = $(this).attr('id'); |
|
157 |
|
|
158 |
var old = $(this).val().split(delimiter[id]); |
|
159 |
|
|
160 |
$('#' + id + '_tagsinput .tag').remove(); |
|
161 |
str = ''; |
|
162 |
for (i = 0; i < old.length; i++) { |
|
163 |
if (old[i] != value) { |
|
164 |
str = str + delimiter[id] + old[i]; |
|
165 |
} |
|
166 |
} |
|
167 |
|
|
168 |
$.fn.tagsInput.importTags(this, str); |
|
169 |
|
|
170 |
if (tags_callbacks[id] && tags_callbacks[id]['onRemoveTag']) { |
|
171 |
var f = tags_callbacks[id]['onRemoveTag']; |
|
172 |
f.call(this, value); |
|
173 |
} |
|
174 |
}); |
|
175 |
|
|
176 |
return false; |
|
177 |
}; |
|
178 |
|
|
179 |
$.fn.tagExist = function (val) { |
|
180 |
var id = $(this).attr('id'); |
|
181 |
var tagslist = $(this).val().split(delimiter[id]); |
|
182 |
return (jQuery.inArray(val, tagslist) >= 0); //true when tag exists, false when not |
|
183 |
}; |
|
184 |
|
|
185 |
// clear all existing tags and import new ones from a string |
|
186 |
$.fn.importTags = function (str) { |
|
187 |
var id = $(this).attr('id'); |
|
188 |
$('#' + id + '_tagsinput .tag').remove(); |
|
189 |
$.fn.tagsInput.importTags(this, str); |
|
190 |
} |
|
191 |
|
|
192 |
$.fn.tagsInput = function (options) { |
|
193 |
if (options && options.skin == 'tagsinput-default' && options.focusWithClick == undefined) { |
|
194 |
options.focusWithClick = false; |
|
195 |
} |
|
196 |
var settings = jQuery.extend({ |
|
197 |
interactive: true, |
|
198 |
defaultText: '+请输入', |
|
199 |
minChars: 0, |
|
200 |
width: '', |
|
201 |
height: '', |
|
202 |
autocomplete: {type: 'get', data: {}}, |
|
203 |
hide: true, |
|
204 |
delimiter: ',', |
|
205 |
unique: true, |
|
206 |
removeWithBackspace: false, |
|
207 |
focusWithClick: true, |
|
208 |
placeholderColor: '#666666', |
|
209 |
autosize: true, |
|
210 |
comfortZone: 20, |
|
211 |
inputPadding: 6 * 2, |
|
212 |
skin: '' |
|
213 |
}, options); |
|
214 |
|
|
215 |
var uniqueIdCounter = 0; |
|
216 |
|
|
217 |
this.each(function () { |
|
218 |
// If we have already initialized the field, do not do it again |
|
219 |
if (typeof $(this).attr('data-tagsinput-init') !== 'undefined') { |
|
220 |
return; |
|
221 |
} |
|
222 |
|
|
223 |
// Mark the field as having been initialized |
|
224 |
$(this).attr('data-tagsinput-init', true); |
|
225 |
|
|
226 |
if (settings.hide) { |
|
227 |
$(this).hide(); |
|
228 |
$(this).addClass('ew-tagsinput-hide'); |
|
229 |
} |
|
230 |
var id = $(this).attr('id'); |
|
231 |
if (!id || delimiter[$(this).attr('id')]) { |
|
232 |
id = $(this).attr('id', 'tags' + new Date().getTime() + (uniqueIdCounter++)).attr('id'); |
|
233 |
} |
|
234 |
|
|
235 |
var data = jQuery.extend({ |
|
236 |
pid: id, |
|
237 |
real_input: '#' + id, |
|
238 |
holder: '#' + id + '_tagsinput', |
|
239 |
input_wrapper: '#' + id + '_addTag', |
|
240 |
fake_input: '#' + id + '_tag' |
|
241 |
}, settings); |
|
242 |
|
|
243 |
delimiter[id] = data.delimiter; |
|
244 |
|
|
245 |
if (settings.onAddTag || settings.onRemoveTag || settings.onChange) { |
|
246 |
tags_callbacks[id] = new Array(); |
|
247 |
tags_callbacks[id]['onAddTag'] = settings.onAddTag; |
|
248 |
tags_callbacks[id]['onRemoveTag'] = settings.onRemoveTag; |
|
249 |
tags_callbacks[id]['onChange'] = settings.onChange; |
|
250 |
} |
|
251 |
|
|
252 |
var markup = '<div id="' + id + '_tagsinput" class="tagsinput ' + settings.skin + '"><div id="' + id + '_addTag">'; |
|
253 |
|
|
254 |
if (settings.interactive) { |
|
255 |
markup = markup + '<input id="' + id + '_tag" value="" placeholder="' + settings.defaultText + '" autocomplete="off" />'; |
|
256 |
} |
|
257 |
|
|
258 |
markup = markup + '</div></div>'; |
|
259 |
|
|
260 |
$(markup).insertAfter(this); |
|
261 |
$(data.holder).css('width', settings.width); |
|
262 |
$(data.holder).css('min-height', settings.height); |
|
263 |
$(data.holder).css('height', settings.height); |
|
264 |
|
|
265 |
if ($(data.real_input).val() != '') { |
|
266 |
$.fn.tagsInput.importTags($(data.real_input), $(data.real_input).val()); |
|
267 |
} |
|
268 |
if (settings.interactive) { |
|
269 |
$(data.fake_input).resetAutosize(settings); |
|
270 |
|
|
271 |
if (settings.focusWithClick) { |
|
272 |
$(data.holder).bind('click', data, function (event) { |
|
273 |
$(event.data.fake_input).focus(); |
|
274 |
}); |
|
275 |
} |
|
276 |
|
|
277 |
if (settings.autocomplete_url != undefined) { |
|
278 |
$(data.fake_input).on('input', function () { |
|
279 |
var name = $(this).val(); |
|
280 |
if (!name) { |
|
281 |
$(data.fake_input).parent().find('.tagsinput-tip-list').remove(); |
|
282 |
return; |
|
283 |
} |
|
284 |
settings.autocomplete.data.name = name; |
|
285 |
$.ajax({ |
|
286 |
url: settings.autocomplete_url, |
|
287 |
type: settings.autocomplete.type, |
|
288 |
data: settings.autocomplete.data, |
|
289 |
dataType: 'json', |
|
290 |
success: function (res) { |
|
291 |
if (res.code == 200) { |
|
292 |
var $tipList = $(data.fake_input).parent().find('.tagsinput-tip-list'); |
|
293 |
if (res.data.length == 0) { |
|
294 |
$tipList.remove(); |
|
295 |
} |
|
296 |
var htmlStr = ''; |
|
297 |
for (var i = 0; i < res.data.length; i++) { |
|
298 |
var item = res.data[i]; |
|
299 |
htmlStr += '<li data-value="' + item + '">' + item + '</li>'; |
|
300 |
} |
|
301 |
if ($tipList.length <= 0) { |
|
302 |
$(data.fake_input).after('<ul class="tagsinput-tip-list"></ul>'); |
|
303 |
$tipList = $(data.fake_input).parent().find('.tagsinput-tip-list'); |
|
304 |
$tipList.on('click', '>li', function () { |
|
305 |
var value = $(this).data('value'); |
|
306 |
$('#' + id).addTag(value, {focus: true, unique: (settings.unique)}); |
|
307 |
$tipList.remove(); |
|
308 |
}); |
|
309 |
} |
|
310 |
$tipList.html(htmlStr); |
|
311 |
} else { |
|
312 |
console.error(res); |
|
313 |
} |
|
314 |
} |
|
315 |
}); |
|
316 |
}); |
|
317 |
|
|
318 |
} else { |
|
319 |
// if a user tabs out of the field, create a new tag |
|
320 |
// this is only available if autocomplete is not used. |
|
321 |
$(data.fake_input).bind('blur', data, function (event) { |
|
322 |
// var d = $(this).attr('data-default'); |
|
323 |
if ($(event.data.fake_input).val() != ''/* && $(event.data.fake_input).val() != d*/) { |
|
324 |
if ((event.data.minChars <= $(event.data.fake_input).val().length) && (!event.data.maxChars || (event.data.maxChars >= $(event.data.fake_input).val().length))) |
|
325 |
$(event.data.real_input).addTag($(event.data.fake_input).val(), { |
|
326 |
focus: false, |
|
327 |
unique: (settings.unique) |
|
328 |
}); |
|
329 |
} |
|
330 |
return false; |
|
331 |
}); |
|
332 |
|
|
333 |
} |
|
334 |
// if user types a default delimiter like comma,semicolon and then create a new tag |
|
335 |
$(data.fake_input).bind('keypress', data, function (event) { |
|
336 |
if (_checkDelimiter(event)) { |
|
337 |
event.preventDefault(); |
|
338 |
if ((event.data.minChars <= $(event.data.fake_input).val().length) && (!event.data.maxChars || (event.data.maxChars >= $(event.data.fake_input).val().length))) |
|
339 |
$(event.data.real_input).addTag($(event.data.fake_input).val(), { |
|
340 |
focus: true, |
|
341 |
unique: (settings.unique) |
|
342 |
}); |
|
343 |
$(event.data.fake_input).resetAutosize(settings); |
|
344 |
return false; |
|
345 |
} else if (event.data.autosize) { |
|
346 |
$(event.data.fake_input).doAutosize(settings); |
|
347 |
|
|
348 |
} |
|
349 |
}); |
|
350 |
//Delete last tag on backspace |
|
351 |
data.removeWithBackspace && $(data.fake_input).bind('keydown', function (event) { |
|
352 |
if (event.keyCode == 8 && $(this).val() == '') { |
|
353 |
event.preventDefault(); |
|
354 |
var last_tag = $(this).closest('.tagsinput').find('.tag:last').text(); |
|
355 |
var id = $(this).attr('id').replace(/_tag$/, ''); |
|
356 |
last_tag = last_tag.replace(/[\s]+x$/, ''); |
|
357 |
last_tag = last_tag.replace(/\s/g, ''); |
|
358 |
$('#' + id).removeTag(escape(last_tag)); |
|
359 |
$(this).trigger('focus'); |
|
360 |
} |
|
361 |
}); |
|
362 |
$(data.fake_input).blur(); |
|
363 |
|
|
364 |
//Removes the not_valid class when user changes the value of the fake input |
|
365 |
if (data.unique) { |
|
366 |
$(data.fake_input).keydown(function (event) { |
|
367 |
if (event.keyCode == 8 || String.fromCharCode(event.which).match(/\w+|[áéíóúÁÉÍÓÚñÑ,/]+/)) { |
|
368 |
$(this).removeClass('not_valid'); |
|
369 |
} |
|
370 |
}); |
|
371 |
} |
|
372 |
} // if settings.interactive |
|
373 |
}); |
|
374 |
|
|
375 |
return this; |
|
376 |
|
|
377 |
}; |
|
378 |
|
|
379 |
$.fn.tagsInput.updateTagsField = function (obj, tagslist) { |
|
380 |
var id = $(obj).attr('id'); |
|
381 |
$(obj).val(tagslist.join(delimiter[id])); |
|
382 |
}; |
|
383 |
|
|
384 |
$.fn.tagsInput.importTags = function (obj, val) { |
|
385 |
$(obj).val(''); |
|
386 |
var id = $(obj).attr('id'); |
|
387 |
var tags = val.split(delimiter[id]); |
|
388 |
for (i = 0; i < tags.length; i++) { |
|
389 |
$(obj).addTag(tags[i], {focus: false, callback: false}); |
|
390 |
} |
|
391 |
if (tags_callbacks[id] && tags_callbacks[id]['onChange']) { |
|
392 |
var f = tags_callbacks[id]['onChange']; |
|
393 |
f.call(obj, obj, tags[i]); |
|
394 |
} |
|
395 |
}; |
|
396 |
|
|
397 |
/** |
|
398 |
* check delimiter Array |
|
399 |
* @param event |
|
400 |
* @returns {boolean} |
|
401 |
* @private |
|
402 |
*/ |
|
403 |
var _checkDelimiter = function (event) { |
|
404 |
var found = false; |
|
405 |
if (event.which == 13) { |
|
406 |
return true; |
|
407 |
} |
|
408 |
|
|
409 |
if (typeof event.data.delimiter === 'string') { |
|
410 |
if (event.which == event.data.delimiter.charCodeAt(0)) { |
|
411 |
found = true; |
|
412 |
} |
|
413 |
} else { |
|
414 |
$.each(event.data.delimiter, function (index, delimiter) { |
|
415 |
if (event.which == delimiter.charCodeAt(0)) { |
|
416 |
found = true; |
|
417 |
} |
|
418 |
}); |
|
419 |
} |
|
420 |
|
|
421 |
return found; |
|
422 |
} |
|
423 |
})); |