PageSourceSearch

https://www.cmu.ca/js/jquery.tagsinput.js

js cmu.ca collected 2026-09-24 10:27:20 UTC 12,345 bytes, 390 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.