懒羊羊
2023-11-14 8286c62256f23bc2367a6729c0f46f84215e380b
提交 | 用户 | 时间
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, '&amp;').replace(/\s/g, ' ').replace(/</g, '&lt;').replace(/>/g, '&gt;');
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">&times;</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('&nbsp;&nbsp;'),
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 }));