rails_tokeninput 0.0.2 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
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