rails_tokeninput 0.0.2 → 1.6.0

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.
data/README.md CHANGED
@@ -39,3 +39,5 @@ In your assets/stylesheets/application.css, you can add the stylesheets you want
39
39
  .
40
40
  *= require token-input-facebook
41
41
  ..etc.
42
+
43
+ ## As of 3-15-2012, the version numbers for this gem reflects the version number of the plugin.
@@ -1,3 +1,3 @@
1
1
  module RailsTokeninput
2
- VERSION = "0.0.2"
2
+ VERSION = "1.6.0"
3
3
  end
@@ -11,46 +11,47 @@
11
11
  (function ($) {
12
12
  // Default settings
13
13
  var DEFAULT_SETTINGS = {
14
- // Search settings
14
+ // Search settings
15
15
  method: "GET",
16
- contentType: "json",
17
16
  queryParam: "q",
18
17
  searchDelay: 300,
19
18
  minChars: 1,
20
19
  propertyToSearch: "name",
21
20
  jsonContainer: null,
21
+ contentType: "json",
22
22
 
23
- // Display settings
23
+ // Prepopulation settings
24
+ prePopulate: null,
25
+ processPrePopulate: false,
26
+
27
+ // Display settings
24
28
  hintText: "Type in a search term",
25
29
  noResultsText: "No results",
26
30
  searchingText: "Searching...",
27
31
  deleteText: "×",
28
32
  animateDropdown: true,
33
+ theme: null,
34
+ zindex: 999,
35
+ resultsFormatter: function(item){ return "<li>" + item[this.propertyToSearch]+ "</li>" },
36
+ tokenFormatter: function(item) { return "<li><p>" + item[this.propertyToSearch] + "</p></li>" },
29
37
 
30
- // Tokenization settings
38
+ // Tokenization settings
31
39
  tokenLimit: null,
32
40
  tokenDelimiter: ",",
33
41
  preventDuplicates: false,
34
-
35
- // Output settings
36
42
  tokenValue: "id",
37
43
 
38
- // Prepopulation settings
39
- prePopulate: null,
40
- processPrePopulate: false,
41
-
42
- // Manipulation settings
43
- idPrefix: "token-input-",
44
-
45
- // Formatters
46
- resultsFormatter: function(item){ return "<li>" + item[this.propertyToSearch]+ "</li>" },
47
- tokenFormatter: function(item) { return "<li><p>" + item[this.propertyToSearch] + "</p></li>" },
48
-
49
- // Callbacks
44
+ // Callbacks
50
45
  onResult: null,
51
46
  onAdd: null,
52
47
  onDelete: null,
53
- onReady: null
48
+ onReady: null,
49
+
50
+ // Other settings
51
+ idPrefix: "token-input-",
52
+
53
+ // Keep track if the input is currently in disabled mode
54
+ disabled: false
54
55
  };
55
56
 
56
57
  // Default classes to use when theming
@@ -64,7 +65,8 @@ var DEFAULT_CLASSES = {
64
65
  dropdownItem: "token-input-dropdown-item",
65
66
  dropdownItem2: "token-input-dropdown-item2",
66
67
  selectedDropdownItem: "token-input-selected-dropdown-item",
67
- inputToken: "token-input-input-token"
68
+ inputToken: "token-input-input-token",
69
+ disabled: "token-input-disabled"
68
70
  };
69
71
 
70
72
  // Input box position "enum"
@@ -115,8 +117,12 @@ var methods = {
115
117
  return this;
116
118
  },
117
119
  get: function() {
118
- return this.data("tokenInputObject").getTokens();
119
- }
120
+ return this.data("tokenInputObject").getTokens();
121
+ },
122
+ toggleDisabled: function(disable) {
123
+ this.data("tokenInputObject").toggleDisabled(disable);
124
+ return this;
125
+ }
120
126
  }
121
127
 
122
128
  // Expose the .tokenInput function to jQuery as a plugin
@@ -144,7 +150,7 @@ $.TokenList = function (input, url_or_data, settings) {
144
150
  var url = computeURL();
145
151
 
146
152
  // Make a smart guess about cross-domain if it wasn't explicitly specified
147
- if(settings.crossDomain === undefined) {
153
+ if(settings.crossDomain === undefined && typeof url === "string") {
148
154
  if(url.indexOf("://") === -1) {
149
155
  settings.crossDomain = false;
150
156
  } else {
@@ -191,6 +197,9 @@ $.TokenList = function (input, url_or_data, settings) {
191
197
  })
192
198
  .attr("id", settings.idPrefix + input.id)
193
199
  .focus(function () {
200
+ if (settings.disabled) {
201
+ return false;
202
+ } else
194
203
  if (settings.tokenLimit === null || settings.tokenLimit !== token_count) {
195
204
  show_dropdown_hint();
196
205
  }
@@ -239,8 +248,8 @@ $.TokenList = function (input, url_or_data, settings) {
239
248
  if(dropdown_item.length) {
240
249
  select_dropdown_item(dropdown_item);
241
250
  }
242
- return false;
243
251
  }
252
+ return false;
244
253
  break;
245
254
 
246
255
  case KEY.BACKSPACE:
@@ -292,7 +301,7 @@ $.TokenList = function (input, url_or_data, settings) {
292
301
  .hide()
293
302
  .val("")
294
303
  .focus(function () {
295
- input_box.focus();
304
+ focus_with_timeout(input_box);
296
305
  })
297
306
  .blur(function () {
298
307
  input_box.blur();
@@ -317,7 +326,7 @@ $.TokenList = function (input, url_or_data, settings) {
317
326
  }
318
327
 
319
328
  // Focus input box
320
- input_box.focus();
329
+ focus_with_timeout(input_box);
321
330
  }
322
331
  })
323
332
  .mouseover(function (event) {
@@ -374,6 +383,11 @@ $.TokenList = function (input, url_or_data, settings) {
374
383
  });
375
384
  }
376
385
 
386
+ // Check if widget should initialize as disabled
387
+ if (settings.disabled) {
388
+ toggleDisabled(true);
389
+ }
390
+
377
391
  // Initialization is done
378
392
  if($.isFunction(settings.onReady)) {
379
393
  settings.onReady.call();
@@ -412,15 +426,36 @@ $.TokenList = function (input, url_or_data, settings) {
412
426
  }
413
427
  });
414
428
  }
415
-
429
+
416
430
  this.getTokens = function() {
417
- return saved_tokens;
418
- }
431
+ return saved_tokens;
432
+ }
433
+
434
+ this.toggleDisabled = function(disable) {
435
+ toggleDisabled(disable);
436
+ }
419
437
 
420
438
  //
421
439
  // Private functions
422
440
  //
423
441
 
442
+ // Toggles the widget between enabled and disabled state, or according
443
+ // to the [disable] parameter.
444
+ function toggleDisabled(disable) {
445
+ if (typeof disable === 'boolean') {
446
+ settings.disabled = disable
447
+ } else {
448
+ settings.disabled = !settings.disabled;
449
+ }
450
+ input_box.prop('disabled', settings.disabled);
451
+ token_list.toggleClass(settings.classes.disabled, settings.disabled);
452
+ // if there is any token selected we deselect it
453
+ if(selected_token) {
454
+ deselect_token($(selected_token), POSITION.END);
455
+ }
456
+ hidden_input.prop('disabled', settings.disabled);
457
+ }
458
+
424
459
  function checkTokenLimit() {
425
460
  if(settings.tokenLimit !== null && token_count >= settings.tokenLimit) {
426
461
  input_box.hide();
@@ -457,14 +492,15 @@ $.TokenList = function (input, url_or_data, settings) {
457
492
  .addClass(settings.classes.tokenDelete)
458
493
  .appendTo(this_token)
459
494
  .click(function () {
460
- delete_token($(this).parent());
461
- hidden_input.change();
462
- return false;
495
+ if (!settings.disabled) {
496
+ delete_token($(this).parent());
497
+ hidden_input.change();
498
+ return false;
499
+ }
463
500
  });
464
501
 
465
502
  // Store data on the token
466
- var token_data = {"id": item.id};
467
- token_data[settings.propertyToSearch] = item[settings.propertyToSearch];
503
+ var token_data = item;
468
504
  $.data(this_token.get(0), "tokeninput", item);
469
505
 
470
506
  // Save this token for duplicate checking
@@ -504,7 +540,7 @@ $.TokenList = function (input, url_or_data, settings) {
504
540
  if(found_existing_token) {
505
541
  select_token(found_existing_token);
506
542
  input_token.insertAfter(found_existing_token);
507
- input_box.focus();
543
+ focus_with_timeout(input_box);
508
544
  return;
509
545
  }
510
546
  }
@@ -529,14 +565,16 @@ $.TokenList = function (input, url_or_data, settings) {
529
565
 
530
566
  // Select a token in the token list
531
567
  function select_token (token) {
532
- token.addClass(settings.classes.selectedToken);
533
- selected_token = token.get(0);
568
+ if (!settings.disabled) {
569
+ token.addClass(settings.classes.selectedToken);
570
+ selected_token = token.get(0);
534
571
 
535
- // Hide input box
536
- input_box.val("");
572
+ // Hide input box
573
+ input_box.val("");
537
574
 
538
- // Hide dropdown if it is visible (eg if we clicked to select token)
539
- hide_dropdown();
575
+ // Hide dropdown if it is visible (eg if we clicked to select token)
576
+ hide_dropdown();
577
+ }
540
578
  }
541
579
 
542
580
  // Deselect a token in the token list
@@ -556,7 +594,7 @@ $.TokenList = function (input, url_or_data, settings) {
556
594
  }
557
595
 
558
596
  // Show the input box and give it focus again
559
- input_box.focus();
597
+ focus_with_timeout(input_box);
560
598
  }
561
599
 
562
600
  // Toggle selection of a token in the token list
@@ -588,7 +626,7 @@ $.TokenList = function (input, url_or_data, settings) {
588
626
  selected_token = null;
589
627
 
590
628
  // Show the input box and give it focus again
591
- input_box.focus();
629
+ focus_with_timeout(input_box);
592
630
 
593
631
  // Remove this token from the saved list
594
632
  saved_tokens = saved_tokens.slice(0,index).concat(saved_tokens.slice(index+1));
@@ -602,8 +640,8 @@ $.TokenList = function (input, url_or_data, settings) {
602
640
  if(settings.tokenLimit !== null) {
603
641
  input_box
604
642
  .show()
605
- .val("")
606
- .focus();
643
+ .val("");
644
+ focus_with_timeout(input_box);
607
645
  }
608
646
 
609
647
  // Execute the onDelete callback if defined
@@ -615,6 +653,9 @@ $.TokenList = function (input, url_or_data, settings) {
615
653
  // Update the hidden input box value
616
654
  function update_hidden_input(saved_tokens, hidden_input) {
617
655
  var token_values = $.map(saved_tokens, function (el) {
656
+ if(typeof settings.tokenValue == 'function')
657
+ return settings.tokenValue.call(this, el);
658
+
618
659
  return el[settings.tokenValue];
619
660
  });
620
661
  hidden_input.val(token_values.join(settings.tokenDelimiter));
@@ -633,7 +674,8 @@ $.TokenList = function (input, url_or_data, settings) {
633
674
  position: "absolute",
634
675
  top: $(token_list).offset().top + $(token_list).outerHeight(),
635
676
  left: $(token_list).offset().left,
636
- zindex: 999
677
+ width: $(token_list).outerWidth(),
678
+ 'z-index': settings.zindex
637
679
  })
638
680
  .show();
639
681
  }
@@ -656,7 +698,7 @@ $.TokenList = function (input, url_or_data, settings) {
656
698
  function highlight_term(value, term) {
657
699
  return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<b>$1</b>");
658
700
  }
659
-
701
+
660
702
  function find_value_and_highlight_term(template, value, term) {
661
703
  return template.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + value + ")(?![^<>]*>)(?![^&;]+;)", "g"), highlight_term(value, term));
662
704
  }
@@ -679,11 +721,11 @@ $.TokenList = function (input, url_or_data, settings) {
679
721
 
680
722
  $.each(results, function(index, value) {
681
723
  var this_li = settings.resultsFormatter(value);
682
-
683
- this_li = find_value_and_highlight_term(this_li ,value[settings.propertyToSearch], query);
684
-
724
+
725
+ this_li = find_value_and_highlight_term(this_li ,value[settings.propertyToSearch], query);
726
+
685
727
  this_li = $(this_li).appendTo(dropdown_ul);
686
-
728
+
687
729
  if(index % 2) {
688
730
  this_li.addClass(settings.classes.dropdownItem);
689
731
  } else {
@@ -733,7 +775,7 @@ $.TokenList = function (input, url_or_data, settings) {
733
775
  // Do a search and show the "searching" dropdown if the input is longer
734
776
  // than settings.minChars
735
777
  function do_search() {
736
- var query = input_box.val().toLowerCase();
778
+ var query = input_box.val();
737
779
 
738
780
  if(query && query.length) {
739
781
  if(selected_token) {
@@ -795,7 +837,7 @@ $.TokenList = function (input, url_or_data, settings) {
795
837
  cache.add(cache_key, settings.jsonContainer ? results[settings.jsonContainer] : results);
796
838
 
797
839
  // only populate the dropdown if the results are associated with the active search query
798
- if(input_box.val().toLowerCase() === query) {
840
+ if(input_box.val() === query) {
799
841
  populate_dropdown(query, settings.jsonContainer ? results[settings.jsonContainer] : results);
800
842
  }
801
843
  };
@@ -821,10 +863,20 @@ $.TokenList = function (input, url_or_data, settings) {
821
863
  function computeURL() {
822
864
  var url = settings.url;
823
865
  if(typeof settings.url == 'function') {
824
- url = settings.url.call();
866
+ url = settings.url.call(settings);
825
867
  }
826
868
  return url;
827
869
  }
870
+
871
+ // Bring browser focus to the specified object.
872
+ // Use of setTimeout is to get around an IE bug.
873
+ // (See, e.g., http://stackoverflow.com/questions/2600186/focus-doesnt-work-in-ie)
874
+ //
875
+ // obj: a jQuery object to focus()
876
+ function focus_with_timeout(obj) {
877
+ setTimeout(function() { obj.focus(); }, 50);
878
+ }
879
+
828
880
  };
829
881
 
830
882
  // Really basic cache for the results
@@ -7,7 +7,7 @@ ul.token-input-list-facebook {
7
7
  border: 1px solid #8496ba;
8
8
  cursor: text;
9
9
  font-size: 12px;
10
- font-family: Verdana;
10
+ font-family: Verdana, sans-serif;
11
11
  min-height: 1px;
12
12
  z-index: 999;
13
13
  margin: 0;
@@ -80,7 +80,7 @@ div.token-input-dropdown-facebook {
80
80
  border-bottom: 1px solid #ccc;
81
81
  cursor: default;
82
82
  font-size: 11px;
83
- font-family: Verdana;
83
+ font-family: Verdana, sans-serif;
84
84
  z-index: 1;
85
85
  }
86
86
 
@@ -26,7 +26,7 @@ ul.token-input-list-mac {
26
26
  height: 1%;
27
27
  cursor: text;
28
28
  font-size: 12px;
29
- font-family: Verdana;
29
+ font-family: Verdana, sans-serif;
30
30
  min-height: 1px;
31
31
  z-index: 999;
32
32
  margin: 0;
@@ -58,7 +58,7 @@ li.token-input-token-mac span {
58
58
  /* TOKENS */
59
59
 
60
60
  li.token-input-token-mac {
61
- font-family: "Lucida Grande", Arial, serif;
61
+ font-family: "Lucida Grande", Arial, sans-serif;
62
62
  font-size: 9pt;
63
63
  line-height: 12pt;
64
64
  overflow: hidden;
@@ -122,7 +122,7 @@ div.token-input-dropdown-mac {
122
122
  overflow: hidden;
123
123
  cursor: default;
124
124
  font-size: 10pt;
125
- font-family: "Lucida Grande", Arial, serif;
125
+ font-family: "Lucida Grande", Arial, sans-serif;
126
126
  padding: 5px;
127
127
  border-radius: 0 0 10px 10px;
128
128
  -moz-border-radius: 0 0 10px 10px;
@@ -142,7 +142,7 @@ div.token-input-dropdown-mac p {
142
142
  }
143
143
 
144
144
  div.token-input-dropdown-mac h3.token-input-dropdown-category-mac {
145
- font-family: "Lucida Grande", Arial, serif;
145
+ font-family: "Lucida Grande", Arial, sans-serif;
146
146
  font-size: 10pt;
147
147
  font-weight: bold;
148
148
  border: none;
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_tokeninput
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 1.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-29 00:00:00.000000000Z
12
+ date: 2012-03-15 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties
16
- requirement: &70215912227620 !ruby/object:Gem::Requirement
16
+ requirement: &70095240341120 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.1.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70215912227620
24
+ version_requirements: *70095240341120
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bundler
27
- requirement: &70215912227100 !ruby/object:Gem::Requirement
27
+ requirement: &70095240340580 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.0.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70215912227100
35
+ version_requirements: *70095240340580
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rails
38
- requirement: &70215912226620 !ruby/object:Gem::Requirement
38
+ requirement: &70095240340120 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '3.1'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70215912226620
46
+ version_requirements: *70095240340120
47
47
  description: Gem installation of jquery tokeninput scripts and stylesheets
48
48
  email:
49
49
  - han@logicallsat.com