bootstrap_tokenfield_rails 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a99164ca4c75845c6e28ebbf78eeade419aedefe
|
4
|
+
data.tar.gz: b72c6367bc12f6d3bd9539888c076df50b28f02f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92a5cd5a835202b06661c05920d01fe4b2d6e7e315e379240abdfcba0e2bec2e705aa3544f7e86d209c8efcca0e05f54f6c6e4e40652d5412fe46a9f41121bba
|
7
|
+
data.tar.gz: af2ed1bfee6c48ce218239f58903e704f69e8849bbeee818b73f93786a67eaff786dab9c47965f64e2c851c7cdb6b3b96d6b6e0f28bc8fbced31d1c873fca147
|
@@ -25,7 +25,7 @@
|
|
25
25
|
};
|
26
26
|
} else {
|
27
27
|
// Browser globals
|
28
|
-
factory(jQuery);
|
28
|
+
factory(jQuery, window);
|
29
29
|
}
|
30
30
|
}(function ($, window) {
|
31
31
|
|
@@ -63,9 +63,9 @@
|
|
63
63
|
}
|
64
64
|
|
65
65
|
var specialCharacters = ['\\', '$', '[', '{', '^', '.', '|', '?', '*', '+', '(', ')']
|
66
|
-
$.each(this._delimiters, function (index,
|
67
|
-
var pos = $.inArray(
|
68
|
-
if (pos >= 0) _self._delimiters[index] = '\\' +
|
66
|
+
$.each(this._delimiters, function (index, character) {
|
67
|
+
var pos = $.inArray(character, specialCharacters)
|
68
|
+
if (pos >= 0) _self._delimiters[index] = '\\' + character;
|
69
69
|
});
|
70
70
|
|
71
71
|
// Store original input width
|
@@ -102,7 +102,7 @@
|
|
102
102
|
|
103
103
|
// Create a new input
|
104
104
|
var id = this.$element.prop('id') || new Date().getTime() + '' + Math.floor((1 + Math.random()) * 100)
|
105
|
-
this.$input = $('<input type="
|
105
|
+
this.$input = $('<input type="'+this.options.inputType+'" class="token-input" autocomplete="off" />')
|
106
106
|
.appendTo( this.$wrapper )
|
107
107
|
.prop( 'placeholder', this.$element.prop('placeholder') )
|
108
108
|
.prop( 'id', id + '-tokenfield' )
|
@@ -134,6 +134,11 @@
|
|
134
134
|
this.disable();
|
135
135
|
}
|
136
136
|
|
137
|
+
// Set tokenfield readonly, if original input is readonly
|
138
|
+
if (this.$element.prop('readonly')) {
|
139
|
+
this.readonly();
|
140
|
+
}
|
141
|
+
|
137
142
|
// Set up mirror for input auto-sizing
|
138
143
|
this.$mirror = $('<span style="position:absolute; top:-999px; left:0; white-space:pre;"/>');
|
139
144
|
this.$input.css('min-width', this.options.minWidth + 'px')
|
@@ -159,7 +164,7 @@
|
|
159
164
|
this.update()
|
160
165
|
|
161
166
|
// Create initial tokens, if any
|
162
|
-
this.setTokens(this.options.tokens, false,
|
167
|
+
this.setTokens(this.options.tokens, false, ! this.$element.val() && this.options.tokens )
|
163
168
|
|
164
169
|
// Start listening to events
|
165
170
|
this.listen()
|
@@ -167,23 +172,28 @@
|
|
167
172
|
// Initialize autocomplete, if necessary
|
168
173
|
if ( ! $.isEmptyObject( this.options.autocomplete ) ) {
|
169
174
|
var side = this.textDirection === 'rtl' ? 'right' : 'left'
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
175
|
+
, autocompleteOptions = $.extend({
|
176
|
+
minLength: this.options.showAutocompleteOnFocus ? 0 : null,
|
177
|
+
position: { my: side + " top", at: side + " bottom", of: this.$wrapper }
|
178
|
+
}, this.options.autocomplete )
|
179
|
+
|
174
180
|
this.$input.autocomplete( autocompleteOptions )
|
175
181
|
}
|
176
182
|
|
177
183
|
// Initialize typeahead, if necessary
|
178
184
|
if ( ! $.isEmptyObject( this.options.typeahead ) ) {
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
185
|
+
|
186
|
+
var typeaheadOptions = this.options.typeahead
|
187
|
+
, defaults = {
|
188
|
+
minLength: this.options.showAutocompleteOnFocus ? 0 : null
|
189
|
+
}
|
190
|
+
, args = $.isArray( typeaheadOptions ) ? typeaheadOptions : [typeaheadOptions, typeaheadOptions]
|
191
|
+
|
192
|
+
args[0] = $.extend( {}, defaults, args[0] )
|
193
|
+
|
194
|
+
this.$input.typeahead.apply( this.$input, args )
|
183
195
|
this.typeahead = true
|
184
196
|
}
|
185
|
-
|
186
|
-
this.$element.trigger('tokenfield:initialize')
|
187
197
|
}
|
188
198
|
|
189
199
|
Tokenfield.prototype = {
|
@@ -191,130 +201,119 @@
|
|
191
201
|
constructor: Tokenfield
|
192
202
|
|
193
203
|
, createToken: function (attrs, triggerChange) {
|
204
|
+
var _self = this
|
205
|
+
|
194
206
|
if (typeof attrs === 'string') {
|
195
207
|
attrs = { value: attrs, label: attrs }
|
208
|
+
} else {
|
209
|
+
// Copy objects to prevent contamination of data sources.
|
210
|
+
attrs = $.extend( {}, attrs )
|
196
211
|
}
|
197
212
|
|
198
|
-
|
213
|
+
if (typeof triggerChange === 'undefined') {
|
199
214
|
triggerChange = true
|
200
|
-
|
215
|
+
}
|
201
216
|
|
202
|
-
|
203
|
-
|
204
|
-
|
217
|
+
// Normalize label and value
|
218
|
+
attrs.value = $.trim(attrs.value.toString());
|
219
|
+
attrs.label = attrs.label && attrs.label.length ? $.trim(attrs.label) : attrs.value
|
205
220
|
|
206
|
-
if
|
221
|
+
// Bail out if has no value or label, or label is too short
|
222
|
+
if (!attrs.value.length || !attrs.label.length || attrs.label.length <= this.options.minLength) return
|
207
223
|
|
224
|
+
// Bail out if maximum number of tokens is reached
|
208
225
|
if (this.options.limit && this.getTokens().length >= this.options.limit) return
|
209
226
|
|
210
227
|
// Allow changing token data before creating it
|
211
|
-
var
|
212
|
-
|
213
|
-
value: value,
|
214
|
-
label: label
|
215
|
-
}
|
216
|
-
this.$element.trigger( prepareEvent )
|
217
|
-
|
218
|
-
if (!prepareEvent.token) return
|
219
|
-
|
220
|
-
value = prepareEvent.token.value
|
221
|
-
label = prepareEvent.token.label
|
222
|
-
|
223
|
-
// Check for duplicates
|
224
|
-
if (!this.options.allowDuplicates && $.grep(this.getTokens(), function (token) {
|
225
|
-
return token.value === value
|
226
|
-
}).length) {
|
227
|
-
// Allow listening to when duplicates get prevented
|
228
|
-
var preventDuplicateEvent = $.Event('tokenfield:preventduplicate')
|
229
|
-
preventDuplicateEvent.token = {
|
230
|
-
value: value,
|
231
|
-
label: label
|
232
|
-
}
|
233
|
-
this.$element.trigger( preventDuplicateEvent )
|
234
|
-
// Add duplicate warning class to existing token for 250ms
|
235
|
-
var duplicate = this.$wrapper.find( '.token[data-value="' + value + '"]' ).addClass('duplicate')
|
236
|
-
setTimeout(function() {
|
237
|
-
duplicate.removeClass('duplicate');
|
238
|
-
}, 250)
|
239
|
-
return false
|
240
|
-
}
|
228
|
+
var createEvent = $.Event('tokenfield:createtoken', { attrs: attrs })
|
229
|
+
this.$element.trigger(createEvent)
|
241
230
|
|
242
|
-
|
243
|
-
|
231
|
+
// Bail out if there if attributes are empty or event was defaultPrevented
|
232
|
+
if (!createEvent.attrs || createEvent.isDefaultPrevented()) return
|
233
|
+
|
234
|
+
var $token = $('<div class="token" />')
|
244
235
|
.append('<span class="token-label" />')
|
245
236
|
.append('<a href="#" class="close" tabindex="-1">×</a>')
|
237
|
+
.data('attrs', attrs)
|
246
238
|
|
247
239
|
// Insert token into HTML
|
248
240
|
if (this.$input.hasClass('tt-input')) {
|
249
|
-
|
241
|
+
// If the input has typeahead enabled, insert token before it's parent
|
242
|
+
this.$input.parent().before( $token )
|
250
243
|
} else {
|
251
|
-
this.$input.before( token )
|
244
|
+
this.$input.before( $token )
|
252
245
|
}
|
246
|
+
|
247
|
+
// Temporarily set input width to minimum
|
253
248
|
this.$input.css('width', this.options.minWidth + 'px')
|
254
249
|
|
255
|
-
var tokenLabel = token.find('.token-label')
|
256
|
-
, closeButton = token.find('.close')
|
250
|
+
var $tokenLabel = $token.find('.token-label')
|
251
|
+
, $closeButton = $token.find('.close')
|
257
252
|
|
258
253
|
// Determine maximum possible token label width
|
259
254
|
if (!this.maxTokenWidth) {
|
260
255
|
this.maxTokenWidth =
|
261
|
-
this.$wrapper.width() - closeButton.outerWidth() -
|
262
|
-
parseInt(closeButton.css('margin-left'), 10) -
|
263
|
-
parseInt(closeButton.css('margin-right'), 10) -
|
264
|
-
parseInt(token.css('border-left-width'), 10) -
|
265
|
-
parseInt(token.css('border-right-width'), 10) -
|
266
|
-
parseInt(token.css('padding-left'), 10) -
|
267
|
-
parseInt(token.css('padding-right'), 10)
|
268
|
-
parseInt(tokenLabel.css('border-left-width'), 10) -
|
269
|
-
parseInt(tokenLabel.css('border-right-width'), 10) -
|
270
|
-
parseInt(tokenLabel.css('padding-left'), 10) -
|
271
|
-
parseInt(tokenLabel.css('padding-right'), 10)
|
272
|
-
parseInt(tokenLabel.css('margin-left'), 10) -
|
273
|
-
parseInt(tokenLabel.css('margin-right'), 10)
|
274
|
-
}
|
275
|
-
|
276
|
-
tokenLabel
|
277
|
-
.text(label)
|
256
|
+
this.$wrapper.width() - $closeButton.outerWidth() -
|
257
|
+
parseInt($closeButton.css('margin-left'), 10) -
|
258
|
+
parseInt($closeButton.css('margin-right'), 10) -
|
259
|
+
parseInt($token.css('border-left-width'), 10) -
|
260
|
+
parseInt($token.css('border-right-width'), 10) -
|
261
|
+
parseInt($token.css('padding-left'), 10) -
|
262
|
+
parseInt($token.css('padding-right'), 10)
|
263
|
+
parseInt($tokenLabel.css('border-left-width'), 10) -
|
264
|
+
parseInt($tokenLabel.css('border-right-width'), 10) -
|
265
|
+
parseInt($tokenLabel.css('padding-left'), 10) -
|
266
|
+
parseInt($tokenLabel.css('padding-right'), 10)
|
267
|
+
parseInt($tokenLabel.css('margin-left'), 10) -
|
268
|
+
parseInt($tokenLabel.css('margin-right'), 10)
|
269
|
+
}
|
270
|
+
|
271
|
+
$tokenLabel
|
272
|
+
.text(attrs.label)
|
278
273
|
.css('max-width', this.maxTokenWidth)
|
279
274
|
|
280
|
-
// Listen to events
|
281
|
-
token
|
275
|
+
// Listen to events on token
|
276
|
+
$token
|
282
277
|
.on('mousedown', function (e) {
|
283
|
-
if (_self.
|
278
|
+
if (_self._disabled || _self._readonly) return false
|
284
279
|
_self.preventDeactivation = true
|
285
280
|
})
|
286
281
|
.on('click', function (e) {
|
287
|
-
if (_self.
|
282
|
+
if (_self._disabled || _self._readonly) return false
|
288
283
|
_self.preventDeactivation = false
|
289
284
|
|
290
285
|
if (e.ctrlKey || e.metaKey) {
|
291
286
|
e.preventDefault()
|
292
|
-
return _self.toggle( token )
|
287
|
+
return _self.toggle( $token )
|
293
288
|
}
|
294
289
|
|
295
|
-
_self.activate( token, e.shiftKey, e.shiftKey )
|
290
|
+
_self.activate( $token, e.shiftKey, e.shiftKey )
|
296
291
|
})
|
297
292
|
.on('dblclick', function (e) {
|
298
|
-
if (_self.
|
299
|
-
_self.edit( token )
|
293
|
+
if (_self._disabled || _self._readonly || !_self.options.allowEditing ) return false
|
294
|
+
_self.edit( $token )
|
300
295
|
})
|
301
296
|
|
302
|
-
closeButton
|
297
|
+
$closeButton
|
303
298
|
.on('click', $.proxy(this.remove, this))
|
304
299
|
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
300
|
+
// Trigger createdtoken event on the original field
|
301
|
+
// indicating that the token is now in the DOM
|
302
|
+
this.$element.trigger($.Event('tokenfield:createdtoken', {
|
303
|
+
attrs: attrs,
|
304
|
+
relatedTarget: $token.get(0)
|
305
|
+
}))
|
309
306
|
|
310
|
-
|
311
|
-
changeEvent.initiator = 'tokenfield'
|
307
|
+
// Trigger change event on the original field
|
312
308
|
if (triggerChange) {
|
313
|
-
this.$element.val( this.getTokensList() ).trigger(
|
309
|
+
this.$element.val( this.getTokensList() ).trigger( $.Event('change', { initiator: 'tokenfield' }) )
|
314
310
|
}
|
311
|
+
|
312
|
+
// Update tokenfield dimensions
|
315
313
|
this.update()
|
316
314
|
|
317
|
-
|
315
|
+
// Return original element
|
316
|
+
return this.$element.get(0)
|
318
317
|
}
|
319
318
|
|
320
319
|
, setTokens: function (tokens, add, triggerChange) {
|
@@ -336,20 +335,17 @@
|
|
336
335
|
}
|
337
336
|
|
338
337
|
var _self = this
|
339
|
-
$.each(tokens, function (i,
|
340
|
-
_self.createToken(
|
338
|
+
$.each(tokens, function (i, attrs) {
|
339
|
+
_self.createToken(attrs, triggerChange)
|
341
340
|
})
|
342
341
|
|
343
342
|
return this.$element.get(0)
|
344
343
|
}
|
345
344
|
|
346
|
-
, getTokenData: function(token) {
|
347
|
-
var data = token.map(function() {
|
345
|
+
, getTokenData: function($token) {
|
346
|
+
var data = $token.map(function() {
|
348
347
|
var $token = $(this);
|
349
|
-
return
|
350
|
-
value: $token.attr('data-value'),
|
351
|
-
label: $token.find('.token-label').text()
|
352
|
-
}
|
348
|
+
return $token.data('attrs')
|
353
349
|
}).get();
|
354
350
|
|
355
351
|
if (data.length == 1) {
|
@@ -431,7 +427,7 @@
|
|
431
427
|
}
|
432
428
|
return false
|
433
429
|
})
|
434
|
-
.on('typeahead:selected', function (e, datum, dataset) {
|
430
|
+
.on('typeahead:selected typeahead:autocompleted', function (e, datum, dataset) {
|
435
431
|
// Create token
|
436
432
|
if (_self.createToken( datum )) {
|
437
433
|
_self.$input.typeahead('val', '')
|
@@ -440,13 +436,6 @@
|
|
440
436
|
}
|
441
437
|
}
|
442
438
|
})
|
443
|
-
.on('typeahead:autocompleted', function (e, datum, dataset) {
|
444
|
-
_self.createToken( _self.$input.val() )
|
445
|
-
_self.$input.typeahead('val', '')
|
446
|
-
if (_self.$input.data( 'edit' )) {
|
447
|
-
_self.unedit(true)
|
448
|
-
}
|
449
|
-
})
|
450
439
|
|
451
440
|
// Listen to window resize
|
452
441
|
$(window).on('resize', $.proxy(this.update, this ))
|
@@ -491,11 +480,11 @@
|
|
491
480
|
case 13: // enter
|
492
481
|
|
493
482
|
// We will handle creating tokens from autocomplete in autocomplete events
|
494
|
-
if (this.$input.data('ui-autocomplete') && this.$input.data('ui-autocomplete').menu.element.find("li:has(a.ui-state-focus)").length) break
|
483
|
+
if (this.$input.data('ui-autocomplete') && this.$input.data('ui-autocomplete').menu.element.find("li:has(a.ui-state-focus), li.ui-state-focus").length) break
|
495
484
|
|
496
485
|
// We will handle creating tokens from typeahead in typeahead events
|
497
486
|
if (this.$input.hasClass('tt-input') && this.$wrapper.find('.tt-cursor').length ) break
|
498
|
-
if (this.$input.hasClass('tt-input') && this.$wrapper.find('.tt-hint').val().length) break
|
487
|
+
if (this.$input.hasClass('tt-input') && this.$wrapper.find('.tt-hint').val() && this.$wrapper.find('.tt-hint').val().length) break
|
499
488
|
|
500
489
|
// Create token
|
501
490
|
if (this.$input.is(document.activeElement) && this.$input.val().length || this.$input.data('edit')) {
|
@@ -515,13 +504,13 @@
|
|
515
504
|
if (_self.$input.val().length > 0) return
|
516
505
|
|
517
506
|
direction += 'All'
|
518
|
-
var token = _self.$input.hasClass('tt-input') ? _self.$input.parent()[direction]('.token:first') : _self.$input[direction]('.token:first')
|
519
|
-
if (
|
507
|
+
var $token = _self.$input.hasClass('tt-input') ? _self.$input.parent()[direction]('.token:first') : _self.$input[direction]('.token:first')
|
508
|
+
if (!$token.length) return
|
520
509
|
|
521
510
|
_self.preventInputFocus = true
|
522
511
|
_self.preventDeactivation = true
|
523
512
|
|
524
|
-
_self.activate( token )
|
513
|
+
_self.activate( $token )
|
525
514
|
e.preventDefault()
|
526
515
|
|
527
516
|
} else {
|
@@ -536,16 +525,16 @@
|
|
536
525
|
if (_self.$input.is(document.activeElement)) {
|
537
526
|
if (_self.$input.val().length > 0) return
|
538
527
|
|
539
|
-
var token = _self.$input.hasClass('tt-input') ? _self.$input.parent()[direction + 'All']('.token:first') : _self.$input[direction + 'All']('.token:first')
|
540
|
-
if (
|
528
|
+
var $token = _self.$input.hasClass('tt-input') ? _self.$input.parent()[direction + 'All']('.token:first') : _self.$input[direction + 'All']('.token:first')
|
529
|
+
if (!$token.length) return
|
541
530
|
|
542
|
-
_self.activate( token )
|
531
|
+
_self.activate( $token )
|
543
532
|
}
|
544
533
|
|
545
534
|
var opposite = direction === 'prev' ? 'next' : 'prev'
|
546
535
|
, position = direction === 'prev' ? 'first' : 'last'
|
547
536
|
|
548
|
-
_self
|
537
|
+
_self.$firstActiveToken[opposite + 'All']('.token').each(function() {
|
549
538
|
_self.deactivate( $(this) )
|
550
539
|
})
|
551
540
|
|
@@ -557,11 +546,9 @@
|
|
557
546
|
}
|
558
547
|
|
559
548
|
, keypress: function(e) {
|
560
|
-
this.lastKeyPressCode = e.keyCode
|
561
|
-
this.lastKeyPressCharCode = e.charCode
|
562
549
|
|
563
550
|
// Comma
|
564
|
-
if ($.inArray( e.
|
551
|
+
if ($.inArray( e.which, this._triggerKeys) !== -1 && this.$input.is(document.activeElement)) {
|
565
552
|
if (this.$input.val()) {
|
566
553
|
this.createTokensFromInput(e)
|
567
554
|
}
|
@@ -580,11 +567,11 @@
|
|
580
567
|
if (this.$input.val().length || this.lastInputValue.length && this.lastKeyDown === 8) break
|
581
568
|
|
582
569
|
this.preventDeactivation = true
|
583
|
-
var
|
570
|
+
var $prevToken = this.$input.hasClass('tt-input') ? this.$input.parent().prevAll('.token:first') : this.$input.prevAll('.token:first')
|
584
571
|
|
585
|
-
if (
|
572
|
+
if (!$prevToken.length) break
|
586
573
|
|
587
|
-
this.activate(
|
574
|
+
this.activate( $prevToken )
|
588
575
|
} else {
|
589
576
|
this.remove(e)
|
590
577
|
}
|
@@ -603,7 +590,7 @@
|
|
603
590
|
|
604
591
|
if (this.$input.is(document.activeElement)) {
|
605
592
|
this.$wrapper.find('.active').removeClass('active')
|
606
|
-
this
|
593
|
+
this.$firstActiveToken = null
|
607
594
|
|
608
595
|
if (this.options.showAutocompleteOnFocus) {
|
609
596
|
this.search()
|
@@ -618,7 +605,7 @@
|
|
618
605
|
|
619
606
|
if (!this.preventDeactivation && !this.$element.is(document.activeElement)) {
|
620
607
|
this.$wrapper.find('.active').removeClass('active')
|
621
|
-
this
|
608
|
+
this.$firstActiveToken = null
|
622
609
|
}
|
623
610
|
|
624
611
|
if (!this.preventCreateTokens && (this.$input.data('edit') && !this.$input.is(document.activeElement) || this.options.createTokensOnBlur )) {
|
@@ -633,9 +620,11 @@
|
|
633
620
|
var _self = this
|
634
621
|
|
635
622
|
// Add tokens to existing ones
|
636
|
-
|
637
|
-
|
638
|
-
|
623
|
+
if (_self.options.allowPasting) {
|
624
|
+
setTimeout(function () {
|
625
|
+
_self.createTokensFromInput(e)
|
626
|
+
}, 1)
|
627
|
+
}
|
639
628
|
}
|
640
629
|
|
641
630
|
, change: function (e) {
|
@@ -671,52 +660,50 @@
|
|
671
660
|
|
672
661
|
, next: function (add) {
|
673
662
|
if (add) {
|
674
|
-
var
|
675
|
-
, deactivate =
|
663
|
+
var $firstActiveToken = this.$wrapper.find('.active:first')
|
664
|
+
, deactivate = $firstActiveToken && this.$firstActiveToken ? $firstActiveToken.index() < this.$firstActiveToken.index() : false
|
676
665
|
|
677
|
-
if (deactivate) return this.deactivate(
|
666
|
+
if (deactivate) return this.deactivate( $firstActiveToken )
|
678
667
|
}
|
679
668
|
|
680
|
-
var
|
681
|
-
,
|
669
|
+
var $lastActiveToken = this.$wrapper.find('.active:last')
|
670
|
+
, $nextToken = $lastActiveToken.nextAll('.token:first')
|
682
671
|
|
683
|
-
if (
|
672
|
+
if (!$nextToken.length) {
|
684
673
|
this.$input.focus()
|
685
674
|
return
|
686
675
|
}
|
687
676
|
|
688
|
-
this.activate(
|
677
|
+
this.activate($nextToken, add)
|
689
678
|
}
|
690
679
|
|
691
680
|
, prev: function (add) {
|
692
681
|
|
693
682
|
if (add) {
|
694
|
-
var
|
695
|
-
, deactivate =
|
683
|
+
var $lastActiveToken = this.$wrapper.find('.active:last')
|
684
|
+
, deactivate = $lastActiveToken && this.$firstActiveToken ? $lastActiveToken.index() > this.$firstActiveToken.index() : false
|
696
685
|
|
697
|
-
if (deactivate) return this.deactivate(
|
686
|
+
if (deactivate) return this.deactivate( $lastActiveToken )
|
698
687
|
}
|
699
688
|
|
700
|
-
var
|
701
|
-
,
|
689
|
+
var $firstActiveToken = this.$wrapper.find('.active:first')
|
690
|
+
, $prevToken = $firstActiveToken.prevAll('.token:first')
|
702
691
|
|
703
|
-
if (
|
704
|
-
|
692
|
+
if (!$prevToken.length) {
|
693
|
+
$prevToken = this.$wrapper.find('.token:first')
|
705
694
|
}
|
706
695
|
|
707
|
-
if (
|
696
|
+
if (!$prevToken.length && !add) {
|
708
697
|
this.$input.focus()
|
709
698
|
return
|
710
699
|
}
|
711
700
|
|
712
|
-
this.activate(
|
701
|
+
this.activate( $prevToken, add )
|
713
702
|
}
|
714
703
|
|
715
|
-
, activate: function (token, add, multi, remember) {
|
716
|
-
|
717
|
-
if (!token) return
|
704
|
+
, activate: function ($token, add, multi, remember) {
|
718
705
|
|
719
|
-
if (
|
706
|
+
if (!$token) return
|
720
707
|
|
721
708
|
if (typeof remember === 'undefined') var remember = true
|
722
709
|
|
@@ -727,17 +714,17 @@
|
|
727
714
|
if (!add) {
|
728
715
|
this.$wrapper.find('.active').removeClass('active')
|
729
716
|
if (remember) {
|
730
|
-
this
|
717
|
+
this.$firstActiveToken = $token
|
731
718
|
} else {
|
732
|
-
delete this
|
719
|
+
delete this.$firstActiveToken
|
733
720
|
}
|
734
721
|
}
|
735
722
|
|
736
|
-
if (multi && this
|
723
|
+
if (multi && this.$firstActiveToken) {
|
737
724
|
// Determine first active token and the current tokens indicies
|
738
725
|
// Account for the 1 hidden textarea by subtracting 1 from both
|
739
|
-
var i = this
|
740
|
-
, a = token.index() - 2
|
726
|
+
var i = this.$firstActiveToken.index() - 2
|
727
|
+
, a = $token.index() - 2
|
741
728
|
, _self = this
|
742
729
|
|
743
730
|
this.$wrapper.find('.token').slice( Math.min(i, a) + 1, Math.max(i, a) ).each( function() {
|
@@ -745,7 +732,7 @@
|
|
745
732
|
})
|
746
733
|
}
|
747
734
|
|
748
|
-
token.addClass('active')
|
735
|
+
$token.addClass('active')
|
749
736
|
this.$copyHelper.val( this.getTokensList( null, null, true ) ).select()
|
750
737
|
}
|
751
738
|
|
@@ -757,55 +744,51 @@
|
|
757
744
|
})
|
758
745
|
}
|
759
746
|
|
760
|
-
, deactivate: function(token) {
|
761
|
-
if (
|
747
|
+
, deactivate: function($token) {
|
748
|
+
if (!$token) return
|
762
749
|
|
763
|
-
token.removeClass('active')
|
750
|
+
$token.removeClass('active')
|
764
751
|
this.$copyHelper.val( this.getTokensList( null, null, true ) ).select()
|
765
752
|
}
|
766
753
|
|
767
|
-
, toggle: function(token) {
|
768
|
-
if (
|
754
|
+
, toggle: function($token) {
|
755
|
+
if (!$token) return
|
769
756
|
|
770
|
-
token.toggleClass('active')
|
757
|
+
$token.toggleClass('active')
|
771
758
|
this.$copyHelper.val( this.getTokensList( null, null, true ) ).select()
|
772
759
|
}
|
773
760
|
|
774
|
-
, edit: function (token) {
|
775
|
-
if (
|
761
|
+
, edit: function ($token) {
|
762
|
+
if (!$token) return
|
776
763
|
|
777
|
-
var
|
778
|
-
, label = token.find('.token-label').text()
|
764
|
+
var attrs = $token.data('attrs')
|
779
765
|
|
780
766
|
// Allow changing input value before editing
|
781
|
-
var
|
782
|
-
editEvent
|
783
|
-
value: value,
|
784
|
-
label: label
|
785
|
-
}
|
786
|
-
editEvent.relatedTarget = token.get(0)
|
767
|
+
var options = { attrs: attrs, relatedTarget: $token.get(0) }
|
768
|
+
var editEvent = $.Event('tokenfield:edittoken', options)
|
787
769
|
this.$element.trigger( editEvent )
|
788
770
|
|
789
|
-
if
|
790
|
-
|
791
|
-
value = editEvent.token.value
|
792
|
-
label = editEvent.token.label
|
771
|
+
// Edit event can be cancelled if default is prevented
|
772
|
+
if (editEvent.isDefaultPrevented()) return
|
793
773
|
|
794
|
-
token.find('.token-label').text(value)
|
795
|
-
var tokenWidth = token.outerWidth()
|
774
|
+
$token.find('.token-label').text(attrs.value)
|
775
|
+
var tokenWidth = $token.outerWidth()
|
796
776
|
|
797
777
|
var $_input = this.$input.hasClass('tt-input') ? this.$input.parent() : this.$input
|
798
778
|
|
799
|
-
token.replaceWith( $_input )
|
779
|
+
$token.replaceWith( $_input )
|
800
780
|
|
801
781
|
this.preventCreateTokens = true
|
802
782
|
|
803
|
-
this.$input.val( value )
|
783
|
+
this.$input.val( attrs.value )
|
804
784
|
.select()
|
805
785
|
.data( 'edit', true )
|
806
786
|
.width( tokenWidth )
|
807
787
|
|
808
788
|
this.update();
|
789
|
+
|
790
|
+
// Indicate that token is now being edited, and is replaced with an input field in the DOM
|
791
|
+
this.$element.trigger($.Event('tokenfield:editedtoken', options ))
|
809
792
|
}
|
810
793
|
|
811
794
|
, unedit: function (focus) {
|
@@ -829,31 +812,35 @@
|
|
829
812
|
}
|
830
813
|
|
831
814
|
, remove: function (e, direction) {
|
832
|
-
if (this.$input.is(document.activeElement) || this.
|
815
|
+
if (this.$input.is(document.activeElement) || this._disabled || this._readonly) return
|
833
816
|
|
834
|
-
var token = (e.type === 'click') ? $(e.target).closest('.token') : this.$wrapper.find('.token.active')
|
817
|
+
var $token = (e.type === 'click') ? $(e.target).closest('.token') : this.$wrapper.find('.token.active')
|
835
818
|
|
836
819
|
if (e.type !== 'click') {
|
837
820
|
if (!direction) var direction = 'prev'
|
838
821
|
this[direction]()
|
839
822
|
|
840
|
-
// Was
|
841
|
-
if (direction === 'prev') var firstToken = token.first().prevAll('.token:first').length === 0
|
823
|
+
// Was it the first token?
|
824
|
+
if (direction === 'prev') var firstToken = $token.first().prevAll('.token:first').length === 0
|
842
825
|
}
|
843
826
|
|
844
|
-
// Prepare events
|
827
|
+
// Prepare events and their options
|
828
|
+
var options = { attrs: this.getTokenData( $token ), relatedTarget: $token.get(0) }
|
829
|
+
, removeEvent = $.Event('tokenfield:removetoken', options)
|
830
|
+
|
831
|
+
this.$element.trigger(removeEvent);
|
845
832
|
|
846
|
-
|
847
|
-
removeEvent.
|
833
|
+
// Remove event can be intercepted and cancelled
|
834
|
+
if (removeEvent.isDefaultPrevented()) return
|
848
835
|
|
849
|
-
var
|
850
|
-
|
836
|
+
var removedEvent = $.Event('tokenfield:removedtoken', options)
|
837
|
+
, changeEvent = $.Event('change', { initiator: 'tokenfield' })
|
851
838
|
|
852
839
|
// Remove token from DOM
|
853
|
-
token.remove()
|
840
|
+
$token.remove()
|
854
841
|
|
855
842
|
// Trigger events
|
856
|
-
this.$element.val( this.getTokensList() ).trigger(
|
843
|
+
this.$element.val( this.getTokensList() ).trigger( removedEvent ).trigger( changeEvent )
|
857
844
|
|
858
845
|
// Focus, when necessary:
|
859
846
|
// When there are no more tokens, or if this was the first token
|
@@ -864,15 +851,19 @@
|
|
864
851
|
this.$input.css('width', this.options.minWidth + 'px')
|
865
852
|
this.update()
|
866
853
|
|
854
|
+
// Cancel original event handlers
|
867
855
|
e.preventDefault()
|
868
856
|
e.stopPropagation()
|
869
857
|
}
|
870
858
|
|
859
|
+
/**
|
860
|
+
* Update tokenfield dimensions
|
861
|
+
*/
|
871
862
|
, update: function (e) {
|
872
863
|
var value = this.$input.val()
|
873
|
-
,
|
874
|
-
,
|
875
|
-
, inputPadding =
|
864
|
+
, inputPaddingLeft = parseInt(this.$input.css('padding-left'), 10)
|
865
|
+
, inputPaddingRight = parseInt(this.$input.css('padding-right'), 10)
|
866
|
+
, inputPadding = inputPaddingLeft + inputPaddingRight
|
876
867
|
|
877
868
|
if (this.$input.data('edit')) {
|
878
869
|
|
@@ -891,16 +882,19 @@
|
|
891
882
|
this.$input.width( mirrorWidth )
|
892
883
|
}
|
893
884
|
else {
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
885
|
+
var w = (this.textDirection === 'rtl')
|
886
|
+
? this.$input.offset().left + this.$input.outerWidth() - this.$wrapper.offset().left - parseInt(this.$wrapper.css('padding-left'), 10) - inputPadding - 1
|
887
|
+
: this.$wrapper.offset().left + this.$wrapper.width() + parseInt(this.$wrapper.css('padding-left'), 10) - this.$input.offset().left - inputPadding;
|
888
|
+
//
|
889
|
+
// some usecases pre-render widget before attaching to DOM,
|
890
|
+
// dimensions returned by jquery will be NaN -> we default to 100%
|
891
|
+
// so placeholder won't be cut off.
|
892
|
+
isNaN(w) ? this.$input.width('100%') : this.$input.width(w);
|
899
893
|
}
|
900
894
|
}
|
901
895
|
|
902
896
|
, focusInput: function (e) {
|
903
|
-
if ($(e.target).closest('.token').length || $(e.target).closest('.token-input').length) return
|
897
|
+
if ( $(e.target).closest('.token').length || $(e.target).closest('.token-input').length || $(e.target).closest('.tt-dropdown-menu').length ) return
|
904
898
|
// Focus only after the current call stack has cleared,
|
905
899
|
// otherwise has no effect.
|
906
900
|
// Reason: mousedown is too early - input will lose focus
|
@@ -919,19 +913,28 @@
|
|
919
913
|
}
|
920
914
|
|
921
915
|
, disable: function () {
|
922
|
-
this.disabled
|
923
|
-
this.$input.prop('disabled', true);
|
924
|
-
this.$element.prop('disabled', true);
|
925
|
-
this.$wrapper.addClass('disabled');
|
916
|
+
this.setProperty('disabled', true);
|
926
917
|
}
|
927
918
|
|
928
919
|
, enable: function () {
|
929
|
-
this.disabled
|
930
|
-
|
931
|
-
|
932
|
-
|
920
|
+
this.setProperty('disabled', false);
|
921
|
+
}
|
922
|
+
|
923
|
+
, readonly: function () {
|
924
|
+
this.setProperty('readonly', true);
|
933
925
|
}
|
934
926
|
|
927
|
+
, writeable: function () {
|
928
|
+
this.setProperty('readonly', false);
|
929
|
+
}
|
930
|
+
|
931
|
+
, setProperty: function(property, value) {
|
932
|
+
this['_' + property] = value;
|
933
|
+
this.$input.prop(property, value);
|
934
|
+
this.$element.prop(property, value);
|
935
|
+
this.$wrapper[ value ? 'addClass' : 'removeClass' ](property);
|
936
|
+
}
|
937
|
+
|
935
938
|
, destroy: function() {
|
936
939
|
// Set field value
|
937
940
|
this.$element.val( this.getTokensList() );
|
@@ -939,7 +942,7 @@
|
|
939
942
|
this.$element.css( this.$element.data('original-styles') );
|
940
943
|
this.$element.prop( 'tabindex', this.$element.data('original-tabindex') );
|
941
944
|
|
942
|
-
// Re-route tokenfield
|
945
|
+
// Re-route tokenfield label to original input
|
943
946
|
var $label = $( 'label[for="' + this.$input.prop('id') + '"]' )
|
944
947
|
if ( $label.length ) {
|
945
948
|
$label.prop( 'for', this.$element.prop('id') )
|
@@ -949,15 +952,15 @@
|
|
949
952
|
this.$element.insertBefore( this.$wrapper );
|
950
953
|
|
951
954
|
// Remove tokenfield-related data
|
952
|
-
this.$element.removeData('original-styles')
|
953
|
-
|
954
|
-
|
955
|
+
this.$element.removeData('original-styles')
|
956
|
+
.removeData('original-tabindex')
|
957
|
+
.removeData('bs.tokenfield');
|
955
958
|
|
956
959
|
// Remove tokenfield from DOM
|
957
960
|
this.$wrapper.remove();
|
961
|
+
this.$mirror.remove();
|
958
962
|
|
959
963
|
var $_element = this.$element;
|
960
|
-
delete this;
|
961
964
|
|
962
965
|
return $_element;
|
963
966
|
}
|
@@ -985,7 +988,10 @@
|
|
985
988
|
args.shift()
|
986
989
|
value = data[option].apply(data, args)
|
987
990
|
} else {
|
988
|
-
if (!data && typeof option !== 'string' && !param)
|
991
|
+
if (!data && typeof option !== 'string' && !param) {
|
992
|
+
$this.data('bs.tokenfield', (data = new Tokenfield(this, options)))
|
993
|
+
$this.trigger('tokenfield:initialize')
|
994
|
+
}
|
989
995
|
}
|
990
996
|
})
|
991
997
|
|
@@ -995,15 +1001,16 @@
|
|
995
1001
|
$.fn.tokenfield.defaults = {
|
996
1002
|
minWidth: 60,
|
997
1003
|
minLength: 0,
|
998
|
-
allowDuplicates: false,
|
999
1004
|
allowEditing: true,
|
1005
|
+
allowPasting: true,
|
1000
1006
|
limit: 0,
|
1001
1007
|
autocomplete: {},
|
1002
1008
|
typeahead: {},
|
1003
1009
|
showAutocompleteOnFocus: false,
|
1004
1010
|
createTokensOnBlur: false,
|
1005
1011
|
delimiter: ',',
|
1006
|
-
beautify: true
|
1012
|
+
beautify: true,
|
1013
|
+
inputType: 'text'
|
1007
1014
|
}
|
1008
1015
|
|
1009
1016
|
$.fn.tokenfield.Constructor = Tokenfield
|
@@ -3,7 +3,7 @@
|
|
3
3
|
* https://github.com/sliptree/bootstrap-tokenfield
|
4
4
|
* Copyright 2013-2014 Sliptree and other contributors; Licensed MIT
|
5
5
|
*/
|
6
|
-
@-webkit-keyframes
|
6
|
+
@-webkit-keyframes blink {
|
7
7
|
0% {
|
8
8
|
border-color: #ededed;
|
9
9
|
}
|
@@ -11,7 +11,7 @@
|
|
11
11
|
border-color: #b94a48;
|
12
12
|
}
|
13
13
|
}
|
14
|
-
@-moz-keyframes
|
14
|
+
@-moz-keyframes blink {
|
15
15
|
0% {
|
16
16
|
border-color: #ededed;
|
17
17
|
}
|
@@ -19,7 +19,7 @@
|
|
19
19
|
border-color: #b94a48;
|
20
20
|
}
|
21
21
|
}
|
22
|
-
@keyframes
|
22
|
+
@keyframes blink {
|
23
23
|
0% {
|
24
24
|
border-color: #ededed;
|
25
25
|
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bootstrap_tokenfield_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Akash Devaraju
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -76,3 +76,4 @@ signing_key:
|
|
76
76
|
specification_version: 4
|
77
77
|
summary: A jQuery tagging / tokenizer input plugin for Twitter's Bootstrap
|
78
78
|
test_files: []
|
79
|
+
has_rdoc:
|