To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
root / plugins / redmine_tags / assets / javascripts / tag-it.js @ 1261:4f5d10466283
History | View | Annotate | Download (21.1 KB)
| 1 | 1132:9b2f28ecd125 | luis | /*
|
|---|---|---|---|
| 2 | * jQuery UI Tag-it!
|
||
| 3 | *
|
||
| 4 | * @version v2.0 (06/2011)
|
||
| 5 | *
|
||
| 6 | * Copyright 2011, Levy Carneiro Jr.
|
||
| 7 | * Released under the MIT license.
|
||
| 8 | * http://aehlke.github.com/tag-it/LICENSE
|
||
| 9 | *
|
||
| 10 | * Homepage:
|
||
| 11 | * http://aehlke.github.com/tag-it/
|
||
| 12 | *
|
||
| 13 | * Authors:
|
||
| 14 | * Levy Carneiro Jr.
|
||
| 15 | * Martin Rehfeld
|
||
| 16 | * Tobias Schmidt
|
||
| 17 | * Skylar Challand
|
||
| 18 | * Alex Ehlke
|
||
| 19 | *
|
||
| 20 | * Maintainer:
|
||
| 21 | * Alex Ehlke - Twitter: @aehlke
|
||
| 22 | *
|
||
| 23 | * Dependencies:
|
||
| 24 | * jQuery v1.4+
|
||
| 25 | * jQuery UI v1.8+
|
||
| 26 | */
|
||
| 27 | (function($) { |
||
| 28 | |||
| 29 | $.widget('ui.tagit', { |
||
| 30 | options: {
|
||
| 31 | 1261:4f5d10466283 | luis | allowDuplicates : false, |
| 32 | caseSensitive : true, |
||
| 33 | 1132:9b2f28ecd125 | luis | fieldName : 'tags', |
| 34 | 1261:4f5d10466283 | luis | placeholderText : null, // Sets `placeholder` attr on input field. |
| 35 | readOnly : false, // Disables editing. |
||
| 36 | removeConfirmation: false, // Require confirmation to remove tags. |
||
| 37 | tagLimit : null, // Max number of tags allowed (null for unlimited). |
||
| 38 | |||
| 39 | // Used for autocomplete, unless you override `autocomplete.source`.
|
||
| 40 | 1132:9b2f28ecd125 | luis | availableTags : [],
|
| 41 | |||
| 42 | 1261:4f5d10466283 | luis | // Use to override or add any options to the autocomplete widget.
|
| 43 | //
|
||
| 44 | // By default, autocomplete.source will map to availableTags,
|
||
| 45 | // unless overridden.
|
||
| 46 | autocomplete: {},
|
||
| 47 | |||
| 48 | // Shows autocomplete before the user even types anything.
|
||
| 49 | showAutocompleteOnFocus: false, |
||
| 50 | |||
| 51 | // When enabled, quotes are unneccesary for inputting multi-word tags.
|
||
| 52 | 1132:9b2f28ecd125 | luis | allowSpaces: false, |
| 53 | |||
| 54 | // The below options are for using a single field instead of several
|
||
| 55 | // for our form values.
|
||
| 56 | //
|
||
| 57 | // When enabled, will use a single hidden field for the form,
|
||
| 58 | // rather than one per tag. It will delimit tags in the field
|
||
| 59 | // with singleFieldDelimiter.
|
||
| 60 | //
|
||
| 61 | // The easiest way to use singleField is to just instantiate tag-it
|
||
| 62 | // on an INPUT element, in which case singleField is automatically
|
||
| 63 | 1261:4f5d10466283 | luis | // set to true, and singleFieldNode is set to that element. This
|
| 64 | 1132:9b2f28ecd125 | luis | // way, you don't need to fiddle with these options.
|
| 65 | singleField: false, |
||
| 66 | |||
| 67 | 1261:4f5d10466283 | luis | // This is just used when preloading data from the field, and for
|
| 68 | // populating the field with delimited tags as the user adds them.
|
||
| 69 | 1132:9b2f28ecd125 | luis | singleFieldDelimiter: ',', |
| 70 | |||
| 71 | // Set this to an input DOM node to use an existing form field.
|
||
| 72 | // Any text in it will be erased on init. But it will be
|
||
| 73 | // populated with the text of tags as they are created,
|
||
| 74 | // delimited by singleFieldDelimiter.
|
||
| 75 | //
|
||
| 76 | // If this is not set, we create an input node for it,
|
||
| 77 | 1261:4f5d10466283 | luis | // with the name given in settings.fieldName.
|
| 78 | 1132:9b2f28ecd125 | luis | singleFieldNode: null, |
| 79 | |||
| 80 | 1261:4f5d10466283 | luis | // Whether to animate tag removals or not.
|
| 81 | animate: true, |
||
| 82 | |||
| 83 | 1132:9b2f28ecd125 | luis | // Optionally set a tabindex attribute on the input that gets
|
| 84 | // created for tag-it.
|
||
| 85 | tabIndex: null, |
||
| 86 | |||
| 87 | 1261:4f5d10466283 | luis | // Event callbacks.
|
| 88 | beforeTagAdded : null, |
||
| 89 | afterTagAdded : null, |
||
| 90 | 1132:9b2f28ecd125 | luis | |
| 91 | 1261:4f5d10466283 | luis | beforeTagRemoved : null, |
| 92 | afterTagRemoved : null, |
||
| 93 | |||
| 94 | onTagClicked : null, |
||
| 95 | onTagLimitExceeded : null, |
||
| 96 | |||
| 97 | |||
| 98 | // DEPRECATED:
|
||
| 99 | //
|
||
| 100 | // /!\ These event callbacks are deprecated and WILL BE REMOVED at some
|
||
| 101 | // point in the future. They're here for backwards-compatibility.
|
||
| 102 | // Use the above before/after event callbacks instead.
|
||
| 103 | 1132:9b2f28ecd125 | luis | onTagAdded : null, |
| 104 | onTagRemoved: null, |
||
| 105 | 1261:4f5d10466283 | luis | // `autocomplete.source` is the replacement for tagSource.
|
| 106 | tagSource: null |
||
| 107 | // Do not use the above deprecated options.
|
||
| 108 | 1132:9b2f28ecd125 | luis | }, |
| 109 | |||
| 110 | _create: function() { |
||
| 111 | // for handling static scoping inside callbacks
|
||
| 112 | var that = this; |
||
| 113 | |||
| 114 | // There are 2 kinds of DOM nodes this widget can be instantiated on:
|
||
| 115 | // 1. UL, OL, or some element containing either of these.
|
||
| 116 | // 2. INPUT, in which case 'singleField' is overridden to true,
|
||
| 117 | // a UL is created and the INPUT is hidden.
|
||
| 118 | if (this.element.is('input')) { |
||
| 119 | this.tagList = $('<ul></ul>').insertAfter(this.element); |
||
| 120 | this.options.singleField = true; |
||
| 121 | this.options.singleFieldNode = this.element; |
||
| 122 | this.element.css('display', 'none'); |
||
| 123 | } else {
|
||
| 124 | this.tagList = this.element.find('ul, ol').andSelf().last(); |
||
| 125 | } |
||
| 126 | |||
| 127 | 1261:4f5d10466283 | luis | this.tagInput = $('<input type="text" />').addClass('ui-widget-content'); |
| 128 | |||
| 129 | if (this.options.readOnly) this.tagInput.attr('disabled', 'disabled'); |
||
| 130 | |||
| 131 | 1132:9b2f28ecd125 | luis | if (this.options.tabIndex) { |
| 132 | 1261:4f5d10466283 | luis | this.tagInput.attr('tabindex', this.options.tabIndex); |
| 133 | 1132:9b2f28ecd125 | luis | } |
| 134 | |||
| 135 | 1261:4f5d10466283 | luis | if (this.options.placeholderText) { |
| 136 | this.tagInput.attr('placeholder', this.options.placeholderText); |
||
| 137 | } |
||
| 138 | |||
| 139 | if (!this.options.autocomplete.source) { |
||
| 140 | this.options.autocomplete.source = function(search, showChoices) { |
||
| 141 | var filter = search.term.toLowerCase();
|
||
| 142 | var choices = $.grep(this.options.availableTags, function(element) { |
||
| 143 | // Only match autocomplete options that begin with the search term.
|
||
| 144 | // (Case insensitive.)
|
||
| 145 | return (element.toLowerCase().indexOf(filter) === 0); |
||
| 146 | }); |
||
| 147 | showChoices(this._subtractArray(choices, this.assignedTags())); |
||
| 148 | }; |
||
| 149 | } |
||
| 150 | |||
| 151 | if (this.options.showAutocompleteOnFocus) { |
||
| 152 | this.tagInput.focus(function(event, ui) { |
||
| 153 | that._showAutocomplete(); |
||
| 154 | 1132:9b2f28ecd125 | luis | }); |
| 155 | |||
| 156 | 1261:4f5d10466283 | luis | if (typeof this.options.autocomplete.minLength === 'undefined') { |
| 157 | this.options.autocomplete.minLength = 0; |
||
| 158 | } |
||
| 159 | } |
||
| 160 | |||
| 161 | // Bind autocomplete.source callback functions to this context.
|
||
| 162 | if ($.isFunction(this.options.autocomplete.source)) { |
||
| 163 | this.options.autocomplete.source = $.proxy(this.options.autocomplete.source, this); |
||
| 164 | } |
||
| 165 | |||
| 166 | // DEPRECATED.
|
||
| 167 | 1132:9b2f28ecd125 | luis | if ($.isFunction(this.options.tagSource)) { |
| 168 | this.options.tagSource = $.proxy(this.options.tagSource, this); |
||
| 169 | } |
||
| 170 | |||
| 171 | this.tagList
|
||
| 172 | .addClass('tagit')
|
||
| 173 | .addClass('ui-widget ui-widget-content ui-corner-all')
|
||
| 174 | // Create the input field.
|
||
| 175 | 1261:4f5d10466283 | luis | .append($('<li class="tagit-new"></li>').append(this.tagInput)) |
| 176 | 1132:9b2f28ecd125 | luis | .click(function(e) {
|
| 177 | var target = $(e.target); |
||
| 178 | if (target.hasClass('tagit-label')) { |
||
| 179 | 1261:4f5d10466283 | luis | var tag = target.closest('.tagit-choice'); |
| 180 | if (!tag.hasClass('removed')) { |
||
| 181 | that._trigger('onTagClicked', e, {tag: tag, tagLabel: that.tagLabel(tag)}); |
||
| 182 | } |
||
| 183 | 1132:9b2f28ecd125 | luis | } else {
|
| 184 | // Sets the focus() to the input field, if the user
|
||
| 185 | // clicks anywhere inside the UL. This is needed
|
||
| 186 | // because the input field needs to be of a small size.
|
||
| 187 | 1261:4f5d10466283 | luis | that.tagInput.focus(); |
| 188 | 1132:9b2f28ecd125 | luis | } |
| 189 | }); |
||
| 190 | |||
| 191 | // Single field support.
|
||
| 192 | 1261:4f5d10466283 | luis | var addedExistingFromSingleFieldNode = false; |
| 193 | 1132:9b2f28ecd125 | luis | if (this.options.singleField) { |
| 194 | if (this.options.singleFieldNode) { |
||
| 195 | // Add existing tags from the input field.
|
||
| 196 | var node = $(this.options.singleFieldNode); |
||
| 197 | var tags = node.val().split(this.options.singleFieldDelimiter); |
||
| 198 | node.val('');
|
||
| 199 | $.each(tags, function(index, tag) { |
||
| 200 | 1261:4f5d10466283 | luis | that.createTag(tag, null, true); |
| 201 | addedExistingFromSingleFieldNode = true;
|
||
| 202 | 1132:9b2f28ecd125 | luis | }); |
| 203 | } else {
|
||
| 204 | // Create our single field input after our list.
|
||
| 205 | 1261:4f5d10466283 | luis | this.options.singleFieldNode = $('<input type="hidden" style="display:none;" value="" name="' + this.options.fieldName + '" />'); |
| 206 | this.tagList.after(this.options.singleFieldNode); |
||
| 207 | 1132:9b2f28ecd125 | luis | } |
| 208 | } |
||
| 209 | |||
| 210 | 1261:4f5d10466283 | luis | // Add existing tags from the list, if any.
|
| 211 | if (!addedExistingFromSingleFieldNode) {
|
||
| 212 | this.tagList.children('li').each(function() { |
||
| 213 | if (!$(this).hasClass('tagit-new')) { |
||
| 214 | that.createTag($(this).text(), $(this).attr('class'), true); |
||
| 215 | $(this).remove(); |
||
| 216 | } |
||
| 217 | }); |
||
| 218 | } |
||
| 219 | |||
| 220 | 1132:9b2f28ecd125 | luis | // Events.
|
| 221 | 1261:4f5d10466283 | luis | this.tagInput
|
| 222 | 1132:9b2f28ecd125 | luis | .keydown(function(event) {
|
| 223 | // Backspace is not detected within a keypress, so it must use keydown.
|
||
| 224 | 1261:4f5d10466283 | luis | if (event.which == $.ui.keyCode.BACKSPACE && that.tagInput.val() === '') { |
| 225 | 1132:9b2f28ecd125 | luis | var tag = that._lastTag();
|
| 226 | if (!that.options.removeConfirmation || tag.hasClass('remove')) { |
||
| 227 | // When backspace is pressed, the last tag is deleted.
|
||
| 228 | that.removeTag(tag); |
||
| 229 | } else if (that.options.removeConfirmation) { |
||
| 230 | tag.addClass('remove ui-state-highlight');
|
||
| 231 | } |
||
| 232 | } else if (that.options.removeConfirmation) { |
||
| 233 | that._lastTag().removeClass('remove ui-state-highlight');
|
||
| 234 | } |
||
| 235 | |||
| 236 | // Comma/Space/Enter are all valid delimiters for new tags,
|
||
| 237 | // except when there is an open quote or if setting allowSpaces = true.
|
||
| 238 | 1261:4f5d10466283 | luis | // Tab will also create a tag, unless the tag input is empty,
|
| 239 | // in which case it isn't caught.
|
||
| 240 | 1132:9b2f28ecd125 | luis | if (
|
| 241 | 1261:4f5d10466283 | luis | event.which === $.ui.keyCode.COMMA ||
|
| 242 | event.which === $.ui.keyCode.ENTER ||
|
||
| 243 | 1132:9b2f28ecd125 | luis | ( |
| 244 | event.which == $.ui.keyCode.TAB &&
|
||
| 245 | 1261:4f5d10466283 | luis | that.tagInput.val() !== ''
|
| 246 | 1132:9b2f28ecd125 | luis | ) || |
| 247 | ( |
||
| 248 | event.which == $.ui.keyCode.SPACE &&
|
||
| 249 | that.options.allowSpaces !== true &&
|
||
| 250 | ( |
||
| 251 | 1261:4f5d10466283 | luis | $.trim(that.tagInput.val()).replace( /^s*/, '' ).charAt(0) != '"' || |
| 252 | 1132:9b2f28ecd125 | luis | ( |
| 253 | 1261:4f5d10466283 | luis | $.trim(that.tagInput.val()).charAt(0) == '"' && |
| 254 | $.trim(that.tagInput.val()).charAt($.trim(that.tagInput.val()).length - 1) == '"' && |
||
| 255 | $.trim(that.tagInput.val()).length - 1 !== 0 |
||
| 256 | 1132:9b2f28ecd125 | luis | ) |
| 257 | ) |
||
| 258 | ) |
||
| 259 | ) {
|
||
| 260 | 1261:4f5d10466283 | luis | // Enter submits the form if there's no text in the input.
|
| 261 | if (!(event.which === $.ui.keyCode.ENTER && that.tagInput.val() === '')) { |
||
| 262 | event.preventDefault(); |
||
| 263 | } |
||
| 264 | |||
| 265 | 1132:9b2f28ecd125 | luis | that.createTag(that._cleanedInput()); |
| 266 | |||
| 267 | // The autocomplete doesn't close automatically when TAB is pressed.
|
||
| 268 | // So let's ensure that it closes.
|
||
| 269 | 1261:4f5d10466283 | luis | that.tagInput.autocomplete('close');
|
| 270 | 1132:9b2f28ecd125 | luis | } |
| 271 | }).blur(function(e){
|
||
| 272 | 1261:4f5d10466283 | luis | // Create a tag when the element loses focus.
|
| 273 | // If autocomplete is enabled and suggestion was clicked, don't add it.
|
||
| 274 | if (!that.tagInput.data('autocomplete-open')) { |
||
| 275 | that.createTag(that._cleanedInput()); |
||
| 276 | } |
||
| 277 | 1132:9b2f28ecd125 | luis | }); |
| 278 | |||
| 279 | // Autocomplete.
|
||
| 280 | 1261:4f5d10466283 | luis | if (this.options.availableTags || this.options.tagSource || this.options.autocomplete.source) { |
| 281 | var autocompleteOptions = {
|
||
| 282 | 1132:9b2f28ecd125 | luis | select: function(event, ui) { |
| 283 | that.createTag(ui.item.value); |
||
| 284 | // Preventing the tag input to be updated with the chosen value.
|
||
| 285 | return false; |
||
| 286 | } |
||
| 287 | 1261:4f5d10466283 | luis | }; |
| 288 | $.extend(autocompleteOptions, this.options.autocomplete); |
||
| 289 | |||
| 290 | // tagSource is deprecated, but takes precedence here since autocomplete.source is set by default,
|
||
| 291 | // while tagSource is left null by default.
|
||
| 292 | autocompleteOptions.source = this.options.tagSource || autocompleteOptions.source;
|
||
| 293 | |||
| 294 | this.tagInput.autocomplete(autocompleteOptions).bind('autocompleteopen', function(event, ui) { |
||
| 295 | that.tagInput.data('autocomplete-open', true); |
||
| 296 | }).bind('autocompleteclose', function(event, ui) { |
||
| 297 | that.tagInput.data('autocomplete-open', false) |
||
| 298 | 1132:9b2f28ecd125 | luis | }); |
| 299 | } |
||
| 300 | }, |
||
| 301 | |||
| 302 | _cleanedInput: function() { |
||
| 303 | // Returns the contents of the tag input, cleaned and ready to be passed to createTag
|
||
| 304 | 1261:4f5d10466283 | luis | return $.trim(this.tagInput.val().replace(/^"(.*)"$/, '$1')); |
| 305 | 1132:9b2f28ecd125 | luis | }, |
| 306 | |||
| 307 | _lastTag: function() { |
||
| 308 | 1261:4f5d10466283 | luis | return this.tagList.find('.tagit-choice:last:not(.removed)'); |
| 309 | }, |
||
| 310 | |||
| 311 | _tags: function() { |
||
| 312 | return this.tagList.find('.tagit-choice:not(.removed)'); |
||
| 313 | 1132:9b2f28ecd125 | luis | }, |
| 314 | |||
| 315 | assignedTags: function() { |
||
| 316 | // Returns an array of tag string values
|
||
| 317 | var that = this; |
||
| 318 | var tags = [];
|
||
| 319 | if (this.options.singleField) { |
||
| 320 | tags = $(this.options.singleFieldNode).val().split(this.options.singleFieldDelimiter); |
||
| 321 | if (tags[0] === '') { |
||
| 322 | tags = []; |
||
| 323 | } |
||
| 324 | } else {
|
||
| 325 | 1261:4f5d10466283 | luis | this._tags().each(function() { |
| 326 | 1132:9b2f28ecd125 | luis | tags.push(that.tagLabel(this));
|
| 327 | }); |
||
| 328 | } |
||
| 329 | return tags;
|
||
| 330 | }, |
||
| 331 | |||
| 332 | _updateSingleTagsField: function(tags) { |
||
| 333 | // Takes a list of tag string values, updates this.options.singleFieldNode.val to the tags delimited by this.options.singleFieldDelimiter
|
||
| 334 | 1261:4f5d10466283 | luis | $(this.options.singleFieldNode).val(tags.join(this.options.singleFieldDelimiter)).trigger('change'); |
| 335 | 1132:9b2f28ecd125 | luis | }, |
| 336 | |||
| 337 | _subtractArray: function(a1, a2) { |
||
| 338 | var result = [];
|
||
| 339 | for (var i = 0; i < a1.length; i++) { |
||
| 340 | if ($.inArray(a1[i], a2) == -1) { |
||
| 341 | result.push(a1[i]); |
||
| 342 | } |
||
| 343 | } |
||
| 344 | return result;
|
||
| 345 | }, |
||
| 346 | |||
| 347 | tagLabel: function(tag) { |
||
| 348 | // Returns the tag's string label.
|
||
| 349 | if (this.options.singleField) { |
||
| 350 | 1261:4f5d10466283 | luis | return $(tag).find('.tagit-label:first').text(); |
| 351 | 1132:9b2f28ecd125 | luis | } else {
|
| 352 | 1261:4f5d10466283 | luis | return $(tag).find('input:first').val(); |
| 353 | 1132:9b2f28ecd125 | luis | } |
| 354 | }, |
||
| 355 | |||
| 356 | 1261:4f5d10466283 | luis | _showAutocomplete: function() { |
| 357 | this.tagInput.autocomplete('search', ''); |
||
| 358 | }, |
||
| 359 | |||
| 360 | _findTagByLabel: function(name) { |
||
| 361 | 1132:9b2f28ecd125 | luis | var that = this; |
| 362 | 1261:4f5d10466283 | luis | var tag = null; |
| 363 | this._tags().each(function(i) { |
||
| 364 | if (that._formatStr(name) == that._formatStr(that.tagLabel(this))) { |
||
| 365 | tag = $(this); |
||
| 366 | 1132:9b2f28ecd125 | luis | return false; |
| 367 | } |
||
| 368 | }); |
||
| 369 | 1261:4f5d10466283 | luis | return tag;
|
| 370 | }, |
||
| 371 | |||
| 372 | _isNew: function(name) { |
||
| 373 | return !this._findTagByLabel(name); |
||
| 374 | 1132:9b2f28ecd125 | luis | }, |
| 375 | |||
| 376 | _formatStr: function(str) { |
||
| 377 | if (this.options.caseSensitive) { |
||
| 378 | return str;
|
||
| 379 | } |
||
| 380 | return $.trim(str.toLowerCase()); |
||
| 381 | }, |
||
| 382 | |||
| 383 | 1261:4f5d10466283 | luis | _effectExists: function(name) { |
| 384 | return Boolean($.effects && ($.effects[name] || ($.effects.effect && $.effects.effect[name]))); |
||
| 385 | }, |
||
| 386 | |||
| 387 | createTag: function(value, additionalClass, duringInitialization) { |
||
| 388 | 1132:9b2f28ecd125 | luis | var that = this; |
| 389 | 1261:4f5d10466283 | luis | |
| 390 | 1132:9b2f28ecd125 | luis | value = $.trim(value);
|
| 391 | |||
| 392 | 1261:4f5d10466283 | luis | if(this.options.preprocessTag) { |
| 393 | value = this.options.preprocessTag(value);
|
||
| 394 | } |
||
| 395 | |||
| 396 | if (value === '') { |
||
| 397 | return false; |
||
| 398 | } |
||
| 399 | |||
| 400 | if (!this.options.allowDuplicates && !this._isNew(value)) { |
||
| 401 | var existingTag = this._findTagByLabel(value); |
||
| 402 | if (this._trigger('onTagExists', null, { |
||
| 403 | existingTag: existingTag,
|
||
| 404 | duringInitialization: duringInitialization
|
||
| 405 | }) !== false) {
|
||
| 406 | if (this._effectExists('highlight')) { |
||
| 407 | existingTag.effect('highlight');
|
||
| 408 | } |
||
| 409 | } |
||
| 410 | return false; |
||
| 411 | } |
||
| 412 | |||
| 413 | if (this.options.tagLimit && this._tags().length >= this.options.tagLimit) { |
||
| 414 | this._trigger('onTagLimitExceeded', null, {duringInitialization: duringInitialization}); |
||
| 415 | 1132:9b2f28ecd125 | luis | return false; |
| 416 | } |
||
| 417 | |||
| 418 | var label = $(this.options.onTagClicked ? '<a class="tagit-label"></a>' : '<span class="tagit-label"></span>').text(value); |
||
| 419 | |||
| 420 | // Create tag.
|
||
| 421 | var tag = $('<li></li>') |
||
| 422 | .addClass('tagit-choice ui-widget-content ui-state-default ui-corner-all')
|
||
| 423 | .addClass(additionalClass) |
||
| 424 | .append(label); |
||
| 425 | |||
| 426 | 1261:4f5d10466283 | luis | if (this.options.readOnly){ |
| 427 | tag.addClass('tagit-choice-read-only');
|
||
| 428 | } else {
|
||
| 429 | tag.addClass('tagit-choice-editable');
|
||
| 430 | // Button for removing the tag.
|
||
| 431 | var removeTagIcon = $('<span></span>') |
||
| 432 | .addClass('ui-icon ui-icon-close');
|
||
| 433 | var removeTag = $('<a><span class="text-icon">\xd7</span></a>') // \xd7 is an X |
||
| 434 | .addClass('tagit-close')
|
||
| 435 | .append(removeTagIcon) |
||
| 436 | .click(function(e) {
|
||
| 437 | // Removes a tag when the little 'x' is clicked.
|
||
| 438 | that.removeTag(tag); |
||
| 439 | }); |
||
| 440 | tag.append(removeTag); |
||
| 441 | } |
||
| 442 | 1132:9b2f28ecd125 | luis | |
| 443 | // Unless options.singleField is set, each tag has a hidden input field inline.
|
||
| 444 | 1261:4f5d10466283 | luis | if (!this.options.singleField) { |
| 445 | var escapedValue = label.html();
|
||
| 446 | tag.append('<input type="hidden" style="display:none;" value="' + escapedValue + '" name="' + this.options.fieldName + '" />'); |
||
| 447 | } |
||
| 448 | |||
| 449 | if (this._trigger('beforeTagAdded', null, { |
||
| 450 | tag: tag,
|
||
| 451 | tagLabel: this.tagLabel(tag), |
||
| 452 | duringInitialization: duringInitialization
|
||
| 453 | }) === false) {
|
||
| 454 | return;
|
||
| 455 | } |
||
| 456 | |||
| 457 | 1132:9b2f28ecd125 | luis | if (this.options.singleField) { |
| 458 | var tags = this.assignedTags(); |
||
| 459 | tags.push(value); |
||
| 460 | this._updateSingleTagsField(tags);
|
||
| 461 | } |
||
| 462 | |||
| 463 | 1261:4f5d10466283 | luis | // DEPRECATED.
|
| 464 | 1132:9b2f28ecd125 | luis | this._trigger('onTagAdded', null, tag); |
| 465 | |||
| 466 | 1261:4f5d10466283 | luis | this.tagInput.val(''); |
| 467 | 1132:9b2f28ecd125 | luis | |
| 468 | 1261:4f5d10466283 | luis | // Insert tag.
|
| 469 | this.tagInput.parent().before(tag);
|
||
| 470 | |||
| 471 | this._trigger('afterTagAdded', null, { |
||
| 472 | tag: tag,
|
||
| 473 | tagLabel: this.tagLabel(tag), |
||
| 474 | duringInitialization: duringInitialization
|
||
| 475 | }); |
||
| 476 | |||
| 477 | if (this.options.showAutocompleteOnFocus && !duringInitialization) { |
||
| 478 | setTimeout(function () { that._showAutocomplete(); }, 0); |
||
| 479 | } |
||
| 480 | 1132:9b2f28ecd125 | luis | }, |
| 481 | 1261:4f5d10466283 | luis | |
| 482 | 1132:9b2f28ecd125 | luis | removeTag: function(tag, animate) { |
| 483 | 1261:4f5d10466283 | luis | animate = typeof animate === 'undefined' ? this.options.animate : animate; |
| 484 | 1132:9b2f28ecd125 | luis | |
| 485 | tag = $(tag);
|
||
| 486 | |||
| 487 | 1261:4f5d10466283 | luis | // DEPRECATED.
|
| 488 | 1132:9b2f28ecd125 | luis | this._trigger('onTagRemoved', null, tag); |
| 489 | |||
| 490 | 1261:4f5d10466283 | luis | if (this._trigger('beforeTagRemoved', null, {tag: tag, tagLabel: this.tagLabel(tag)}) === false) { |
| 491 | return;
|
||
| 492 | } |
||
| 493 | |||
| 494 | 1132:9b2f28ecd125 | luis | if (this.options.singleField) { |
| 495 | var tags = this.assignedTags(); |
||
| 496 | var removedTagLabel = this.tagLabel(tag); |
||
| 497 | tags = $.grep(tags, function(el){ |
||
| 498 | return el != removedTagLabel;
|
||
| 499 | }); |
||
| 500 | this._updateSingleTagsField(tags);
|
||
| 501 | } |
||
| 502 | 1261:4f5d10466283 | luis | |
| 503 | 1132:9b2f28ecd125 | luis | if (animate) {
|
| 504 | 1261:4f5d10466283 | luis | tag.addClass('removed'); // Excludes this tag from _tags. |
| 505 | var hide_args = this._effectExists('blind') ? ['blind', {direction: 'horizontal'}, 'fast'] : ['fast']; |
||
| 506 | |||
| 507 | var thisTag = this; |
||
| 508 | hide_args.push(function() {
|
||
| 509 | 1132:9b2f28ecd125 | luis | tag.remove(); |
| 510 | 1261:4f5d10466283 | luis | thisTag._trigger('afterTagRemoved', null, {tag: tag, tagLabel: thisTag.tagLabel(tag)}); |
| 511 | }); |
||
| 512 | |||
| 513 | tag.fadeOut('fast').hide.apply(tag, hide_args).dequeue();
|
||
| 514 | 1132:9b2f28ecd125 | luis | } else {
|
| 515 | tag.remove(); |
||
| 516 | 1261:4f5d10466283 | luis | this._trigger('afterTagRemoved', null, {tag: tag, tagLabel: this.tagLabel(tag)}); |
| 517 | 1132:9b2f28ecd125 | luis | } |
| 518 | 1261:4f5d10466283 | luis | |
| 519 | }, |
||
| 520 | |||
| 521 | removeTagByLabel: function(tagLabel, animate) { |
||
| 522 | var toRemove = this._findTagByLabel(tagLabel); |
||
| 523 | if (!toRemove) {
|
||
| 524 | throw "No such tag exists with the name '" + tagLabel + "'"; |
||
| 525 | } |
||
| 526 | this.removeTag(toRemove, animate);
|
||
| 527 | 1132:9b2f28ecd125 | luis | }, |
| 528 | |||
| 529 | removeAll: function() { |
||
| 530 | // Removes all tags.
|
||
| 531 | var that = this; |
||
| 532 | 1261:4f5d10466283 | luis | this._tags().each(function(index, tag) { |
| 533 | 1132:9b2f28ecd125 | luis | that.removeTag(tag, false);
|
| 534 | }); |
||
| 535 | } |
||
| 536 | |||
| 537 | }); |
||
| 538 | 1261:4f5d10466283 | luis | })(jQuery); |