select2-rails 3.5.9 → 3.5.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +5 -13
  2. data/README.md +4 -4
  3. data/Rakefile +0 -1
  4. data/lib/select2-rails/engine.rb +5 -1
  5. data/lib/select2-rails/source_file.rb +13 -32
  6. data/lib/select2-rails/version.rb +1 -1
  7. data/select2-rails.gemspec +2 -2
  8. data/{app → vendor}/assets/images/select2-spinner.gif +0 -0
  9. data/{app → vendor}/assets/images/select2.png +0 -0
  10. data/{app → vendor}/assets/images/select2x2.png +0 -0
  11. data/{app → vendor}/assets/javascripts/select2.js +359 -111
  12. data/{app → vendor}/assets/javascripts/select2_locale_ar.js +6 -4
  13. data/{app → vendor}/assets/javascripts/select2_locale_az.js +4 -2
  14. data/{app → vendor}/assets/javascripts/select2_locale_bg.js +4 -2
  15. data/{app → vendor}/assets/javascripts/select2_locale_ca.js +4 -2
  16. data/{app → vendor}/assets/javascripts/select2_locale_cs.js +4 -2
  17. data/{app → vendor}/assets/javascripts/select2_locale_da.js +4 -2
  18. data/{app → vendor}/assets/javascripts/select2_locale_de.js +5 -3
  19. data/{app → vendor}/assets/javascripts/select2_locale_el.js +4 -2
  20. data/{app → vendor}/assets/javascripts/select2_locale_es.js +7 -3
  21. data/{app → vendor}/assets/javascripts/select2_locale_et.js +4 -2
  22. data/{app → vendor}/assets/javascripts/select2_locale_eu.js +4 -2
  23. data/{app → vendor}/assets/javascripts/select2_locale_fa.js +4 -2
  24. data/{app → vendor}/assets/javascripts/select2_locale_fi.js +4 -2
  25. data/{app → vendor}/assets/javascripts/select2_locale_fr.js +4 -2
  26. data/{app → vendor}/assets/javascripts/select2_locale_gl.js +4 -2
  27. data/{app → vendor}/assets/javascripts/select2_locale_he.js +4 -2
  28. data/{app → vendor}/assets/javascripts/select2_locale_hr.js +4 -2
  29. data/{app → vendor}/assets/javascripts/select2_locale_hu.js +4 -2
  30. data/{app → vendor}/assets/javascripts/select2_locale_id.js +9 -5
  31. data/{app → vendor}/assets/javascripts/select2_locale_is.js +4 -2
  32. data/{app → vendor}/assets/javascripts/select2_locale_it.js +4 -2
  33. data/{app → vendor}/assets/javascripts/select2_locale_ja.js +4 -2
  34. data/{app → vendor}/assets/javascripts/select2_locale_ka.js +4 -2
  35. data/{app → vendor}/assets/javascripts/select2_locale_ko.js +4 -2
  36. data/{app → vendor}/assets/javascripts/select2_locale_lt.js +4 -2
  37. data/{app → vendor}/assets/javascripts/select2_locale_lv.js +4 -2
  38. data/{app → vendor}/assets/javascripts/select2_locale_mk.js +4 -2
  39. data/{app → vendor}/assets/javascripts/select2_locale_ms.js +6 -2
  40. data/vendor/assets/javascripts/select2_locale_nb.js +22 -0
  41. data/{app → vendor}/assets/javascripts/select2_locale_nl.js +7 -5
  42. data/{app → vendor}/assets/javascripts/select2_locale_no.js +4 -2
  43. data/vendor/assets/javascripts/select2_locale_pl.js +54 -0
  44. data/{app → vendor}/assets/javascripts/select2_locale_pt-BR.js +6 -3
  45. data/{app → vendor}/assets/javascripts/select2_locale_pt-PT.js +4 -2
  46. data/{app → vendor}/assets/javascripts/select2_locale_ro.js +4 -2
  47. data/{app → vendor}/assets/javascripts/select2_locale_rs.js +4 -2
  48. data/{app → vendor}/assets/javascripts/select2_locale_ru.js +4 -2
  49. data/{app → vendor}/assets/javascripts/select2_locale_sk.js +13 -11
  50. data/{app → vendor}/assets/javascripts/select2_locale_sv.js +4 -2
  51. data/{app → vendor}/assets/javascripts/select2_locale_th.js +4 -2
  52. data/{app → vendor}/assets/javascripts/select2_locale_tr.js +5 -2
  53. data/vendor/assets/javascripts/select2_locale_ug-CN.js +16 -0
  54. data/{app → vendor}/assets/javascripts/select2_locale_uk.js +4 -2
  55. data/{app → vendor}/assets/javascripts/select2_locale_vi.js +8 -6
  56. data/{app → vendor}/assets/javascripts/select2_locale_zh-CN.js +4 -2
  57. data/{app → vendor}/assets/javascripts/select2_locale_zh-TW.js +4 -2
  58. data/{app → vendor}/assets/stylesheets/select2-bootstrap.css +0 -0
  59. data/{app/assets/stylesheets/select2.css.erb → vendor/assets/stylesheets/select2.scss} +29 -40
  60. metadata +73 -71
  61. data/app/assets/javascripts/select2_locale_pl.js +0 -23
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MmJhNDhmYTI5M2VkYWU4YWQwOTY2MDEzMmFiMDMyN2I0OWNkZTQyMA==
5
- data.tar.gz: !binary |-
6
- MDkzMzY0MWIwZDIyODM1M2I3ZWRlZWE0ZTdhYjJmYzY4NDE1MWEwNg==
2
+ SHA256:
3
+ metadata.gz: 30d5b3dbf2ae9e41f53ee07277e7c82c38c2027794774fd66324e62085909be7
4
+ data.tar.gz: 7e601365f397a46f842cdc107d31dddb1098749c8f3348d73e854552ffd72053
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- Y2UyZWE5YzQ4MTYyMDY5YTczZDNmZGNhOTc5Y2U4Mjg1MTM3YzdjM2QyMzNl
10
- NDRiYjU2YmE0NWNjYzE4NTY2MTdlNTIwZGQyZjUzZTNkODBkNjYzNDUwYmM5
11
- OTM3NjYxNGY1MDEwZTA1MTc0YWI0YWY1YzZlM2RhNzkwOGI3MWU=
12
- data.tar.gz: !binary |-
13
- NzM5OTVhZTU5YmI5MTQyZWNlNGFjYjhkZDM4MmMxOGQ4MmI5Y2VlMTJlMDg2
14
- MzdhNTNhZTk3MmUyZDVhYjY2ZGZmZjAxYzRmMjQwODEzNWQ1MDQzZWM3M2U5
15
- NWVlOTZkNWJkN2E5MmZlYjQ0Nzg1NjFiYzg5OWM0NTAwNjk1OTQ=
6
+ metadata.gz: f4ae4f7ae03c84e2d9c334f630ca2b0199344bd9e4b1646045ebd3b7dd3db3f23f6e8a751b871e17b516d79f31c28c9b1d3dfa893cbdf7f4378003911f9ffd7d
7
+ data.tar.gz: 4b399313ad2d0e5c2a38110e2a80731c322cc98f5614c8d7e0f6d56e65f57ae07de137c686f704a200b0e251b484dec886cf38fd553c9458454e768b28c01580
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  #Select2 for rails asset pipeline
2
2
 
3
- [Select2](https://github.com/ivaynberg/select2) is a jQuery based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results.
3
+ [Select2](https://github.com/select2/select2) is a jQuery based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results.
4
4
 
5
5
  The `select2-rails` gem integrates the `Select2` jQuery plugin with the Rails asset pipeline.
6
6
 
@@ -65,9 +65,9 @@ The last number of the version is the patch version specific to the gem. For exa
65
65
 
66
66
  If you want to contribute, please:
67
67
 
68
- * Fork the project.
69
- * Make your feature addition or bug fix.
70
- * Send me a pull request on Github.
68
+ * Fork the project.
69
+ * Make your feature addition or bug fix.
70
+ * Send me a pull request on Github.
71
71
 
72
72
  ## License
73
73
 
data/Rakefile CHANGED
@@ -7,5 +7,4 @@ task "update-select2" do
7
7
  files = SourceFile.new
8
8
  files.fetch
9
9
  files.convert
10
- files.cleanup
11
10
  end
@@ -1,6 +1,10 @@
1
1
  module Select2
2
2
  module Rails
3
3
  class Engine < ::Rails::Engine
4
+ initializer :images do |app|
5
+ app.config.assets.precompile +=
6
+ %w(select2.png select2-spinner.gif select2x2.png)
7
+ end
4
8
  end
5
9
  end
6
- end
10
+ end
@@ -9,12 +9,12 @@ class SourceFile < Thor
9
9
  def fetch
10
10
  filtered_tags = fetch_tags
11
11
  tag = select("Which tag do you want to fetch?", filtered_tags)
12
- self.destination_root = "app/assets"
13
- remote = "https://github.com/ivaynberg/select2"
12
+ self.destination_root = "vendor/assets"
13
+ remote = "https://github.com/select2/select2"
14
14
  get "#{remote}/raw/#{tag}/select2.png", "images/select2.png"
15
15
  get "#{remote}/raw/#{tag}/select2x2.png", "images/select2x2.png"
16
16
  get "#{remote}/raw/#{tag}/select2-spinner.gif", "images/select2-spinner.gif"
17
- get "#{remote}/raw/#{tag}/select2.css", "stylesheets/select2.css"
17
+ get "#{remote}/raw/#{tag}/select2.css", "stylesheets/select2.scss"
18
18
  get "#{remote}/raw/#{tag}/select2-bootstrap.css", "stylesheets/select2-bootstrap.css"
19
19
  get "#{remote}/raw/#{tag}/select2.js", "javascripts/select2.js"
20
20
  languages.each do |lang|
@@ -22,35 +22,30 @@ class SourceFile < Thor
22
22
  end
23
23
  end
24
24
 
25
- desc "convert css to css.erb file", "make css preprocess with erb"
25
+ desc "convert css to use rails paths", "make css use rails paths"
26
26
  def convert
27
- self.destination_root = "app/assets"
27
+ self.destination_root = "vendor/assets"
28
28
  inside destination_root do
29
- run("cp stylesheets/select2.css stylesheets/select2.css.erb")
30
- build_image_dependencies
31
- gsub_file 'stylesheets/select2.css.erb', %r/url\(([^\)]*)\)/, 'url(<%= asset_path(\1) %>)'
29
+ gsub_file 'stylesheets/select2.scss', %r/url\(([^\)]*)\)/, 'image-url(\1)'
32
30
  end
33
31
  end
34
32
 
35
- desc "clean up useless files", "clean up useless files"
36
- def cleanup
37
- self.destination_root = "app/assets"
38
- remove_file "stylesheets/select2.css"
39
- end
40
-
41
33
  private
42
34
 
43
35
  def fetch_tags
44
36
  http = HTTPClient.new
45
- response = JSON.parse(http.get("https://api.github.com/repos/ivaynberg/select2/tags").body)
37
+ #http.ssl_config.ssl_version = :SSLv23
38
+ response = JSON.parse(http.get("https://api.github.com/repos/select2/select2/tags").body)
46
39
  response.map{|tag| tag["name"]}.sort
47
40
  end
41
+
48
42
  def languages
49
- [ "ar", "bg", "ca", "cs", "da", "de", "el", "es", "et", "eu", "fa", "fi", "fr", "gl", "he", "hr",
50
- "hu", "id", "is", "it", "ja", "ka", "ko", "lt", "lv", "mk", "ms", "nl", "no", "pl", "pt-BR",
51
- "pt-PT", "ro", "rs", "ru", "sk", "sv", "th", "tr", "uk", "vi", "zh-CN", "zh-TW"
43
+ [ "ar", "az", "bg", "ca", "cs", "da", "de", "el", "es", "et", "eu", "fa", "fi", "fr", "gl", "he", "hr",
44
+ "hu", "id", "is", "it", "ja", "ka", "ko", "lt", "lv", "mk", "ms", "nb", "nl", "pl", "pt-BR",
45
+ "pt-PT", "ro", "rs", "ru", "sk", "sv", "th", "tr", "ug-CN", "uk", "vi", "zh-CN", "zh-TW"
52
46
  ].sort
53
47
  end
48
+
54
49
  def select msg, elements
55
50
  elements.each_with_index do |element, index|
56
51
  say(block_given? ? yield(element, index + 1) : ("#{index + 1}. #{element.to_s}"))
@@ -59,18 +54,4 @@ class SourceFile < Thor
59
54
  elements[result - 1]
60
55
  end
61
56
 
62
- def build_image_dependencies
63
- f = File.open("stylesheets/select2.css.erb", "r+")
64
- lines = f.readlines
65
- f.close
66
- lines = ["//= depend_on_asset \"select2.png\"\n"] +
67
- ["//= depend_on_asset \"select2-spinner.gif\"\n"] +
68
- ["//= depend_on_asset \"select2x2.png\"\n"] +
69
- lines
70
-
71
- output = File.new("stylesheets/select2.css.erb", "w")
72
- lines.each { |line| output.write line }
73
- output.close
74
- end
75
-
76
57
  end
@@ -1,5 +1,5 @@
1
1
  module Select2
2
2
  module Rails
3
- VERSION = "3.5.9"
3
+ VERSION = "3.5.11"
4
4
  end
5
5
  end
@@ -15,8 +15,8 @@ Gem::Specification.new do |s|
15
15
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
16
  s.require_paths = ["lib"]
17
17
 
18
- s.add_dependency "thor", "~> 0.14"
19
- s.add_development_dependency "bundler", "~> 1.0"
18
+ s.add_development_dependency "thor", "~> 0.14"
19
+ s.add_development_dependency "bundler", "~> 2.0"
20
20
  s.add_development_dependency "rails", ">= 3.0"
21
21
  s.add_development_dependency "httpclient", "~> 2.2"
22
22
  end
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  Copyright 2012 Igor Vaynberg
3
3
 
4
- Version: 3.5.0 Timestamp: Mon Jun 16 19:29:44 EDT 2014
4
+ Version: 3.5.4 Timestamp: Sun Aug 30 13:30:32 EDT 2015
5
5
 
6
6
  This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU
7
7
  General Public License version 2 (the "GPL License"). You may choose either license to govern your
@@ -46,7 +46,7 @@ the specific language governing permissions and limitations under the Apache Lic
46
46
  return;
47
47
  }
48
48
 
49
- var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, nextUid, sizer,
49
+ var AbstractSelect2, SingleSelect2, MultiSelect2, nextUid, sizer,
50
50
  lastMousePosition={x:0,y:0}, $document, scrollBarDimensions,
51
51
 
52
52
  KEY = {
@@ -132,7 +132,7 @@ the specific language governing permissions and limitations under the Apache Lic
132
132
 
133
133
  function measureScrollbar () {
134
134
  var $template = $( MEASURE_SCROLLBAR_TEMPLATE );
135
- $template.appendTo('body');
135
+ $template.appendTo(document.body);
136
136
 
137
137
  var dim = {
138
138
  width: $template.width() - $template[0].clientWidth,
@@ -160,16 +160,16 @@ the specific language governing permissions and limitations under the Apache Lic
160
160
  }
161
161
 
162
162
  /**
163
- * Splits the string into an array of values, trimming each value. An empty array is returned for nulls or empty
163
+ * Splits the string into an array of values, transforming each value. An empty array is returned for nulls or empty
164
164
  * strings
165
165
  * @param string
166
166
  * @param separator
167
167
  */
168
- function splitVal(string, separator) {
168
+ function splitVal(string, separator, transform) {
169
169
  var val, i, l;
170
170
  if (string === null || string.length < 1) return [];
171
171
  val = string.split(separator);
172
- for (i = 0, l = val.length; i < l; i = i + 1) val[i] = $.trim(val[i]);
172
+ for (i = 0, l = val.length; i < l; i = i + 1) val[i] = transform(val[i]);
173
173
  return val;
174
174
  }
175
175
 
@@ -311,7 +311,7 @@ the specific language governing permissions and limitations under the Apache Lic
311
311
  whiteSpace: "nowrap"
312
312
  });
313
313
  sizer.attr("class","select2-sizer");
314
- $("body").append(sizer);
314
+ $(document.body).append(sizer);
315
315
  }
316
316
  sizer.text(e.val());
317
317
  return sizer.width();
@@ -443,6 +443,16 @@ the specific language governing permissions and limitations under the Apache Lic
443
443
  // TODO - replace query.page with query so users have access to term, page, etc.
444
444
  // added query as third paramter to keep backwards compatibility
445
445
  var results = options.results(data, query.page, query);
446
+ query.callback(results);
447
+ },
448
+ error: function(jqXHR, textStatus, errorThrown){
449
+ var results = {
450
+ hasError: true,
451
+ jqXHR: jqXHR,
452
+ textStatus: textStatus,
453
+ errorThrown: errorThrown
454
+ };
455
+
446
456
  query.callback(results);
447
457
  }
448
458
  });
@@ -689,12 +699,15 @@ the specific language governing permissions and limitations under the Apache Lic
689
699
 
690
700
  this.container = this.createContainer();
691
701
 
692
- this.liveRegion = $("<span>", {
693
- role: "status",
694
- "aria-live": "polite"
695
- })
696
- .addClass("select2-hidden-accessible")
697
- .appendTo(document.body);
702
+ this.liveRegion = $('.select2-hidden-accessible');
703
+ if (this.liveRegion.length == 0) {
704
+ this.liveRegion = $("<span>", {
705
+ role: "status",
706
+ "aria-live": "polite"
707
+ })
708
+ .addClass("select2-hidden-accessible")
709
+ .appendTo(document.body);
710
+ }
698
711
 
699
712
  this.containerId="s2id_"+(opts.element.attr("id") || "autogen"+nextUid());
700
713
  this.containerEventName= this.containerId
@@ -704,7 +717,7 @@ the specific language governing permissions and limitations under the Apache Lic
704
717
 
705
718
  this.container.attr("title", opts.element.attr("title"));
706
719
 
707
- this.body = $("body");
720
+ this.body = $(document.body);
708
721
 
709
722
  syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);
710
723
 
@@ -801,7 +814,7 @@ the specific language governing permissions and limitations under the Apache Lic
801
814
  // focusin can cause focus wars between modals and select2 since the dropdown is outside the modal.
802
815
  this.dropdown.on("click mouseup mousedown touchstart touchend focusin", function (e) { e.stopPropagation(); });
803
816
 
804
- this.nextSearchTerm = undefined;
817
+ this.lastSearchTerm = undefined;
805
818
 
806
819
  if ($.isFunction(this.opts.initSelection)) {
807
820
  // initialize selection based on the current value of the source element
@@ -836,13 +849,15 @@ the specific language governing permissions and limitations under the Apache Lic
836
849
 
837
850
  // abstract
838
851
  destroy: function () {
839
- var element=this.opts.element, select2 = element.data("select2");
852
+ var element=this.opts.element, select2 = element.data("select2"), self = this;
840
853
 
841
854
  this.close();
842
855
 
843
- if (element.length && element[0].detachEvent) {
856
+ if (element.length && element[0].detachEvent && self._sync) {
844
857
  element.each(function () {
845
- this.detachEvent("onpropertychange", this._sync);
858
+ if (self._sync) {
859
+ this.detachEvent("onpropertychange", self._sync);
860
+ }
846
861
  });
847
862
  }
848
863
  if (this.propertyObserver) {
@@ -855,17 +870,21 @@ the specific language governing permissions and limitations under the Apache Lic
855
870
  select2.container.remove();
856
871
  select2.liveRegion.remove();
857
872
  select2.dropdown.remove();
858
- element
859
- .removeClass("select2-offscreen")
860
- .removeData("select2")
861
- .off(".select2")
862
- .prop("autofocus", this.autofocus || false);
863
- if (this.elementTabIndex) {
864
- element.attr({tabindex: this.elementTabIndex});
873
+ element.removeData("select2")
874
+ .off(".select2");
875
+ if (!element.is("input[type='hidden']")) {
876
+ element
877
+ .show()
878
+ .prop("autofocus", this.autofocus || false);
879
+ if (this.elementTabIndex) {
880
+ element.attr({tabindex: this.elementTabIndex});
881
+ } else {
882
+ element.removeAttr("tabindex");
883
+ }
884
+ element.show();
865
885
  } else {
866
- element.removeAttr("tabindex");
886
+ element.css("display", "");
867
887
  }
868
- element.show();
869
888
  }
870
889
 
871
890
  cleanupJQueryElements.call(this,
@@ -917,6 +936,155 @@ the specific language governing permissions and limitations under the Apache Lic
917
936
  });
918
937
  }
919
938
 
939
+ opts.debug = opts.debug || $.fn.select2.defaults.debug;
940
+
941
+ // Warnings for options renamed/removed in Select2 4.0.0
942
+ // Only when it's enabled through debug mode
943
+ if (opts.debug && console && console.warn) {
944
+ // id was removed
945
+ if (opts.id != null) {
946
+ console.warn(
947
+ 'Select2: The `id` option has been removed in Select2 4.0.0, ' +
948
+ 'consider renaming your `id` property or mapping the property before your data makes it to Select2. ' +
949
+ 'You can read more at https://select2.github.io/announcements-4.0.html#changed-id'
950
+ );
951
+ }
952
+
953
+ // text was removed
954
+ if (opts.text != null) {
955
+ console.warn(
956
+ 'Select2: The `text` option has been removed in Select2 4.0.0, ' +
957
+ 'consider renaming your `text` property or mapping the property before your data makes it to Select2. ' +
958
+ 'You can read more at https://select2.github.io/announcements-4.0.html#changed-id'
959
+ );
960
+ }
961
+
962
+ // sortResults was renamed to results
963
+ if (opts.sortResults != null) {
964
+ console.warn(
965
+ 'Select2: the `sortResults` option has been renamed to `sorter` in Select2 4.0.0. '
966
+ );
967
+ }
968
+
969
+ // selectOnBlur was renamed to selectOnClose
970
+ if (opts.selectOnBlur != null) {
971
+ console.warn(
972
+ 'Select2: The `selectOnBlur` option has been renamed to `selectOnClose` in Select2 4.0.0.'
973
+ );
974
+ }
975
+
976
+ // ajax.results was renamed to ajax.processResults
977
+ if (opts.ajax != null && opts.ajax.results != null) {
978
+ console.warn(
979
+ 'Select2: The `ajax.results` option has been renamed to `ajax.processResults` in Select2 4.0.0.'
980
+ );
981
+ }
982
+
983
+ // format* options were renamed to language.*
984
+ if (opts.formatNoResults != null) {
985
+ console.warn(
986
+ 'Select2: The `formatNoResults` option has been renamed to `language.noResults` in Select2 4.0.0.'
987
+ );
988
+ }
989
+ if (opts.formatSearching != null) {
990
+ console.warn(
991
+ 'Select2: The `formatSearching` option has been renamed to `language.searching` in Select2 4.0.0.'
992
+ );
993
+ }
994
+ if (opts.formatInputTooShort != null) {
995
+ console.warn(
996
+ 'Select2: The `formatInputTooShort` option has been renamed to `language.inputTooShort` in Select2 4.0.0.'
997
+ );
998
+ }
999
+ if (opts.formatInputTooLong != null) {
1000
+ console.warn(
1001
+ 'Select2: The `formatInputTooLong` option has been renamed to `language.inputTooLong` in Select2 4.0.0.'
1002
+ );
1003
+ }
1004
+ if (opts.formatLoading != null) {
1005
+ console.warn(
1006
+ 'Select2: The `formatLoading` option has been renamed to `language.loadingMore` in Select2 4.0.0.'
1007
+ );
1008
+ }
1009
+ if (opts.formatSelectionTooBig != null) {
1010
+ console.warn(
1011
+ 'Select2: The `formatSelectionTooBig` option has been renamed to `language.maximumSelected` in Select2 4.0.0.'
1012
+ );
1013
+ }
1014
+
1015
+ if (opts.element.data('select2Tags')) {
1016
+ console.warn(
1017
+ 'Select2: The `data-select2-tags` attribute has been renamed to `data-tags` in Select2 4.0.0.'
1018
+ );
1019
+ }
1020
+ }
1021
+
1022
+ // Aliasing options renamed in Select2 4.0.0
1023
+
1024
+ // data-select2-tags -> data-tags
1025
+ if (opts.element.data('tags') != null) {
1026
+ var elemTags = opts.element.data('tags');
1027
+
1028
+ // data-tags should actually be a boolean
1029
+ if (!$.isArray(elemTags)) {
1030
+ elemTags = [];
1031
+ }
1032
+
1033
+ opts.element.data('select2Tags', elemTags);
1034
+ }
1035
+
1036
+ // sortResults -> sorter
1037
+ if (opts.sorter != null) {
1038
+ opts.sortResults = opts.sorter;
1039
+ }
1040
+
1041
+ // selectOnBlur -> selectOnClose
1042
+ if (opts.selectOnClose != null) {
1043
+ opts.selectOnBlur = opts.selectOnClose;
1044
+ }
1045
+
1046
+ // ajax.results -> ajax.processResults
1047
+ if (opts.ajax != null) {
1048
+ if ($.isFunction(opts.ajax.processResults)) {
1049
+ opts.ajax.results = opts.ajax.processResults;
1050
+ }
1051
+ }
1052
+
1053
+ // Formatters/language options
1054
+ if (opts.language != null) {
1055
+ var lang = opts.language;
1056
+
1057
+ // formatNoMatches -> language.noMatches
1058
+ if ($.isFunction(lang.noMatches)) {
1059
+ opts.formatNoMatches = lang.noMatches;
1060
+ }
1061
+
1062
+ // formatSearching -> language.searching
1063
+ if ($.isFunction(lang.searching)) {
1064
+ opts.formatSearching = lang.searching;
1065
+ }
1066
+
1067
+ // formatInputTooShort -> language.inputTooShort
1068
+ if ($.isFunction(lang.inputTooShort)) {
1069
+ opts.formatInputTooShort = lang.inputTooShort;
1070
+ }
1071
+
1072
+ // formatInputTooLong -> language.inputTooLong
1073
+ if ($.isFunction(lang.inputTooLong)) {
1074
+ opts.formatInputTooLong = lang.inputTooLong;
1075
+ }
1076
+
1077
+ // formatLoading -> language.loadingMore
1078
+ if ($.isFunction(lang.loadingMore)) {
1079
+ opts.formatLoading = lang.loadingMore;
1080
+ }
1081
+
1082
+ // formatSelectionTooBig -> language.maximumSelected
1083
+ if ($.isFunction(lang.maximumSelected)) {
1084
+ opts.formatSelectionTooBig = lang.maximumSelected;
1085
+ }
1086
+ }
1087
+
920
1088
  opts = $.extend({}, {
921
1089
  populateResults: function(container, results, query) {
922
1090
  var populate, id=this.opts.id, liveRegion=this.liveRegion;
@@ -960,7 +1128,6 @@ the specific language governing permissions and limitations under the Apache Lic
960
1128
 
961
1129
 
962
1130
  if (compound) {
963
-
964
1131
  innerContainer=$("<ul></ul>");
965
1132
  innerContainer.addClass("select2-result-sub");
966
1133
  populate(result.children, innerContainer, depth+1);
@@ -1027,11 +1194,10 @@ the specific language governing permissions and limitations under the Apache Lic
1027
1194
 
1028
1195
  query.callback(data);
1029
1196
  });
1030
- // this is needed because inside val() we construct choices from options and there id is hardcoded
1197
+ // this is needed because inside val() we construct choices from options and their id is hardcoded
1031
1198
  opts.id=function(e) { return e.id; };
1032
1199
  } else {
1033
1200
  if (!("query" in opts)) {
1034
-
1035
1201
  if ("ajax" in opts) {
1036
1202
  ajaxUrl = opts.element.data("ajax-url");
1037
1203
  if (ajaxUrl && ajaxUrl.length > 0) {
@@ -1048,7 +1214,7 @@ the specific language governing permissions and limitations under the Apache Lic
1048
1214
  if (opts.initSelection === undefined) {
1049
1215
  opts.initSelection = function (element, callback) {
1050
1216
  var data = [];
1051
- $(splitVal(element.val(), opts.separator)).each(function () {
1217
+ $(splitVal(element.val(), opts.separator, opts.transformVal)).each(function () {
1052
1218
  var obj = { id: this, text: this },
1053
1219
  tags = opts.tags;
1054
1220
  if ($.isFunction(tags)) tags=tags();
@@ -1103,11 +1269,15 @@ the specific language governing permissions and limitations under the Apache Lic
1103
1269
  if (readonly === undefined) readonly = false;
1104
1270
  this.readonly(readonly);
1105
1271
 
1106
- syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);
1107
- this.container.addClass(evaluate(this.opts.containerCssClass, this.opts.element));
1272
+ if (this.container) {
1273
+ syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);
1274
+ this.container.addClass(evaluate(this.opts.containerCssClass, this.opts.element));
1275
+ }
1108
1276
 
1109
- syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass);
1110
- this.dropdown.addClass(evaluate(this.opts.dropdownCssClass, this.opts.element));
1277
+ if (this.dropdown) {
1278
+ syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass);
1279
+ this.dropdown.addClass(evaluate(this.opts.dropdownCssClass, this.opts.element));
1280
+ }
1111
1281
 
1112
1282
  });
1113
1283
 
@@ -1212,9 +1382,10 @@ the specific language governing permissions and limitations under the Apache Lic
1212
1382
  // abstract
1213
1383
  positionDropdown: function() {
1214
1384
  var $dropdown = this.dropdown,
1215
- offset = this.container.offset(),
1216
- height = this.container.outerHeight(false),
1217
- width = this.container.outerWidth(false),
1385
+ container = this.container,
1386
+ offset = container.offset(),
1387
+ height = container.outerHeight(false),
1388
+ width = container.outerWidth(false),
1218
1389
  dropHeight = $dropdown.outerHeight(false),
1219
1390
  $window = $(window),
1220
1391
  windowWidth = $window.width(),
@@ -1226,7 +1397,12 @@ the specific language governing permissions and limitations under the Apache Lic
1226
1397
  enoughRoomBelow = dropTop + dropHeight <= viewportBottom,
1227
1398
  enoughRoomAbove = (offset.top - dropHeight) >= $window.scrollTop(),
1228
1399
  dropWidth = $dropdown.outerWidth(false),
1229
- enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight,
1400
+ enoughRoomOnRight = function() {
1401
+ return dropLeft + dropWidth <= viewPortRight;
1402
+ },
1403
+ enoughRoomOnLeft = function() {
1404
+ return offset.left + viewPortRight + container.outerWidth(false) > dropWidth;
1405
+ },
1230
1406
  aboveNow = $dropdown.hasClass("select2-drop-above"),
1231
1407
  bodyOffset,
1232
1408
  above,
@@ -1261,7 +1437,6 @@ the specific language governing permissions and limitations under the Apache Lic
1261
1437
  dropTop = offset.top + height;
1262
1438
  dropLeft = offset.left;
1263
1439
  dropWidth = $dropdown.outerWidth(false);
1264
- enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight;
1265
1440
  $dropdown.show();
1266
1441
 
1267
1442
  // fix so the cursor does not move to the left within the search-textbox in IE
@@ -1276,7 +1451,6 @@ the specific language governing permissions and limitations under the Apache Lic
1276
1451
  dropWidth = $dropdown.outerWidth(false) + (resultsListNode.scrollHeight === resultsListNode.clientHeight ? 0 : scrollBarDimensions.width);
1277
1452
  dropWidth > width ? width = dropWidth : dropWidth = width;
1278
1453
  dropHeight = $dropdown.outerHeight(false);
1279
- enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight;
1280
1454
  }
1281
1455
  else {
1282
1456
  this.container.removeClass('select2-drop-auto-width');
@@ -1292,7 +1466,7 @@ the specific language governing permissions and limitations under the Apache Lic
1292
1466
  dropLeft -= bodyOffset.left;
1293
1467
  }
1294
1468
 
1295
- if (!enoughRoomOnRight) {
1469
+ if (!enoughRoomOnRight() && enoughRoomOnLeft()) {
1296
1470
  dropLeft = offset.left + this.container.outerWidth(false) - dropWidth;
1297
1471
  }
1298
1472
 
@@ -1302,10 +1476,11 @@ the specific language governing permissions and limitations under the Apache Lic
1302
1476
  };
1303
1477
 
1304
1478
  if (above) {
1305
- css.top = offset.top - dropHeight;
1306
- css.bottom = 'auto';
1307
1479
  this.container.addClass("select2-drop-above");
1308
1480
  $dropdown.addClass("select2-drop-above");
1481
+ dropHeight = $dropdown.outerHeight(false);
1482
+ css.top = offset.top - dropHeight;
1483
+ css.bottom = 'auto';
1309
1484
  }
1310
1485
  else {
1311
1486
  css.top = dropTop;
@@ -1381,7 +1556,7 @@ the specific language governing permissions and limitations under the Apache Lic
1381
1556
 
1382
1557
  // create the dropdown mask if doesn't already exist
1383
1558
  mask = $("#select2-drop-mask");
1384
- if (mask.length == 0) {
1559
+ if (mask.length === 0) {
1385
1560
  mask = $(document.createElement("div"));
1386
1561
  mask.attr("id","select2-drop-mask").attr("class","select2-drop-mask");
1387
1562
  mask.hide();
@@ -1458,6 +1633,9 @@ the specific language governing permissions and limitations under the Apache Lic
1458
1633
 
1459
1634
  this.clearSearch();
1460
1635
  this.search.removeClass("select2-active");
1636
+
1637
+ // Remove the aria active descendant for highlighted element
1638
+ this.search.removeAttr("aria-activedescendant");
1461
1639
  this.opts.element.trigger($.Event("select2-close"));
1462
1640
  },
1463
1641
 
@@ -1476,6 +1654,27 @@ the specific language governing permissions and limitations under the Apache Lic
1476
1654
 
1477
1655
  },
1478
1656
 
1657
+ /**
1658
+ * @return {Boolean} Whether or not search value was changed.
1659
+ * @private
1660
+ */
1661
+ prefillNextSearchTerm: function () {
1662
+ // initializes search's value with nextSearchTerm (if defined by user)
1663
+ // ignore nextSearchTerm if the dropdown is opened by the user pressing a letter
1664
+ if(this.search.val() !== "") {
1665
+ return false;
1666
+ }
1667
+
1668
+ var nextSearchTerm = this.opts.nextSearchTerm(this.data(), this.lastSearchTerm);
1669
+ if(nextSearchTerm !== undefined){
1670
+ this.search.val(nextSearchTerm);
1671
+ this.search.select();
1672
+ return true;
1673
+ }
1674
+
1675
+ return false;
1676
+ },
1677
+
1479
1678
  //abstract
1480
1679
  getMaximumSelectionSize: function() {
1481
1680
  return evaluate(this.opts.maximumSelectionSize, this.opts.element);
@@ -1515,7 +1714,7 @@ the specific language governing permissions and limitations under the Apache Lic
1515
1714
  }
1516
1715
  }
1517
1716
 
1518
- rb = results.offset().top + results.outerHeight(true);
1717
+ rb = results.offset().top + results.outerHeight(false);
1519
1718
  if (hb > rb) {
1520
1719
  results.scrollTop(results.scrollTop() + (hb - rb));
1521
1720
  }
@@ -1638,7 +1837,7 @@ the specific language governing permissions and limitations under the Apache Lic
1638
1837
  self.postprocessResults(data, false, false);
1639
1838
 
1640
1839
  if (data.more===true) {
1641
- more.detach().appendTo(results).text(evaluate(self.opts.formatLoadMore, self.opts.element, page+1));
1840
+ more.detach().appendTo(results).html(self.opts.escapeMarkup(evaluate(self.opts.formatLoadMore, self.opts.element, page+1)));
1642
1841
  window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10);
1643
1842
  } else {
1644
1843
  more.remove();
@@ -1691,7 +1890,7 @@ the specific language governing permissions and limitations under the Apache Lic
1691
1890
  self.liveRegion.text(results.text());
1692
1891
  }
1693
1892
  else {
1694
- self.liveRegion.text(self.opts.formatMatches(results.find('.select2-result-selectable').length));
1893
+ self.liveRegion.text(self.opts.formatMatches(results.find('.select2-result-selectable:not(".select2-selected")').length));
1695
1894
  }
1696
1895
  }
1697
1896
 
@@ -1766,6 +1965,12 @@ the specific language governing permissions and limitations under the Apache Lic
1766
1965
  return;
1767
1966
  }
1768
1967
 
1968
+ // handle ajax error
1969
+ if(data.hasError !== undefined && checkFormatter(opts.formatAjaxError, "formatAjaxError")) {
1970
+ render("<li class='select2-ajax-error'>" + evaluate(opts.formatAjaxError, opts.element, data.jqXHR, data.textStatus, data.errorThrown) + "</li>");
1971
+ return;
1972
+ }
1973
+
1769
1974
  // save context, if any
1770
1975
  this.context = (data.context===undefined) ? null : data.context;
1771
1976
  // create a default choice and prepend it to the list
@@ -1783,6 +1988,9 @@ the specific language governing permissions and limitations under the Apache Lic
1783
1988
 
1784
1989
  if (data.results.length === 0 && checkFormatter(opts.formatNoMatches, "formatNoMatches")) {
1785
1990
  render("<li class='select2-no-results'>" + evaluate(opts.formatNoMatches, opts.element, search.val()) + "</li>");
1991
+ if(this.showSearch){
1992
+ this.showSearch(search.val());
1993
+ }
1786
1994
  return;
1787
1995
  }
1788
1996
 
@@ -1887,7 +2095,7 @@ the specific language governing permissions and limitations under the Apache Lic
1887
2095
  } else if (this.opts.width === "copy" || this.opts.width === "resolve") {
1888
2096
  // check if there is inline style on the element that contains width
1889
2097
  style = this.opts.element.attr('style');
1890
- if (style !== undefined) {
2098
+ if (typeof(style) === "string") {
1891
2099
  attrs = style.split(';');
1892
2100
  for (i = 0, l = attrs.length; i < l; i = i + 1) {
1893
2101
  attr = attrs[i].replace(/\s/g, '');
@@ -1986,14 +2194,7 @@ the specific language governing permissions and limitations under the Apache Lic
1986
2194
  }
1987
2195
  }
1988
2196
 
1989
- // initializes search's value with nextSearchTerm (if defined by user)
1990
- // ignore nextSearchTerm if the dropdown is opened by the user pressing a letter
1991
- if(this.search.val() === "") {
1992
- if(this.nextSearchTerm != undefined){
1993
- this.search.val(this.nextSearchTerm);
1994
- this.search.select();
1995
- }
1996
- }
2197
+ this.prefillNextSearchTerm();
1997
2198
 
1998
2199
  this.focusser.prop("disabled", true).val("");
1999
2200
  this.updateResults(true);
@@ -2080,6 +2281,7 @@ the specific language governing permissions and limitations under the Apache Lic
2080
2281
  this.focusser.attr("id", "s2id_autogen"+idSuffix);
2081
2282
 
2082
2283
  elementLabel = $("label[for='" + this.opts.element.attr("id") + "']");
2284
+ this.opts.element.on('focus.select2', this.bind(function () { this.focus(); }));
2083
2285
 
2084
2286
  this.focusser.prev()
2085
2287
  .text(elementLabel.text())
@@ -2101,6 +2303,9 @@ the specific language governing permissions and limitations under the Apache Lic
2101
2303
  this.search.on("keydown", this.bind(function (e) {
2102
2304
  if (!this.isInterfaceEnabled()) return;
2103
2305
 
2306
+ // filter 229 keyCodes (input method editor is processing key input)
2307
+ if (229 == e.keyCode) return;
2308
+
2104
2309
  if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) {
2105
2310
  // prevent the page from scrolling
2106
2311
  killEvent(e);
@@ -2132,7 +2337,7 @@ the specific language governing permissions and limitations under the Apache Lic
2132
2337
  // without this the search field loses focus which is annoying
2133
2338
  if (document.activeElement === this.body.get(0)) {
2134
2339
  window.setTimeout(this.bind(function() {
2135
- if (this.opened()) {
2340
+ if (this.opened() && this.results && this.results.length > 1) {
2136
2341
  this.search.focus();
2137
2342
  }
2138
2343
  }), 0);
@@ -2181,11 +2386,17 @@ the specific language governing permissions and limitations under the Apache Lic
2181
2386
  }));
2182
2387
 
2183
2388
  selection.on("mousedown touchstart", "abbr", this.bind(function (e) {
2184
- if (!this.isInterfaceEnabled()) return;
2389
+ if (!this.isInterfaceEnabled()) {
2390
+ return;
2391
+ }
2392
+
2185
2393
  this.clear();
2186
2394
  killEventImmediately(e);
2187
2395
  this.close();
2188
- this.selection.focus();
2396
+
2397
+ if (this.selection) {
2398
+ this.selection.focus();
2399
+ }
2189
2400
  }));
2190
2401
 
2191
2402
  selection.on("mousedown touchstart", this.bind(function (e) {
@@ -2234,7 +2445,7 @@ the specific language governing permissions and limitations under the Apache Lic
2234
2445
  }));
2235
2446
 
2236
2447
  this.initContainerWidth();
2237
- this.opts.element.addClass("select2-offscreen");
2448
+ this.opts.element.hide();
2238
2449
  this.setPlaceholder();
2239
2450
 
2240
2451
  },
@@ -2278,7 +2489,7 @@ the specific language governing permissions and limitations under the Apache Lic
2278
2489
  self.updateSelection(selected);
2279
2490
  self.close();
2280
2491
  self.setPlaceholder();
2281
- self.nextSearchTerm = self.opts.nextSearchTerm(selected, self.search.val());
2492
+ self.lastSearchTerm = self.search.val();
2282
2493
  }
2283
2494
  });
2284
2495
  }
@@ -2415,7 +2626,7 @@ the specific language governing permissions and limitations under the Apache Lic
2415
2626
 
2416
2627
  this.opts.element.trigger({ type: "select2-selected", val: this.id(data), choice: data });
2417
2628
 
2418
- this.nextSearchTerm = this.opts.nextSearchTerm(data, this.search.val());
2629
+ this.lastSearchTerm = this.search.val();
2419
2630
  this.close();
2420
2631
 
2421
2632
  if ((!options || !options.noFocus) && this.opts.shouldFocusInput(this)) {
@@ -2469,9 +2680,23 @@ the specific language governing permissions and limitations under the Apache Lic
2469
2680
 
2470
2681
  if (arguments.length > 1) {
2471
2682
  triggerChange = arguments[1];
2683
+
2684
+ if (this.opts.debug && console && console.warn) {
2685
+ console.warn(
2686
+ 'Select2: The second option to `select2("val")` is not supported in Select2 4.0.0. ' +
2687
+ 'The `change` event will always be triggered in 4.0.0.'
2688
+ );
2689
+ }
2472
2690
  }
2473
2691
 
2474
2692
  if (this.select) {
2693
+ if (this.opts.debug && console && console.warn) {
2694
+ console.warn(
2695
+ 'Select2: Setting the value on a <select> using `select2("val")` is no longer supported in 4.0.0. ' +
2696
+ 'You can use the `.val(newValue).trigger("change")` method provided by jQuery instead.'
2697
+ );
2698
+ }
2699
+
2475
2700
  this.select
2476
2701
  .val(val)
2477
2702
  .find("option").filter(function() { return this.selected }).each2(function (i, elm) {
@@ -2520,6 +2745,13 @@ the specific language governing permissions and limitations under the Apache Lic
2520
2745
  if (data == undefined) data = null;
2521
2746
  return data;
2522
2747
  } else {
2748
+ if (this.opts.debug && console && console.warn) {
2749
+ console.warn(
2750
+ 'Select2: The `select2("data")` method can no longer set selected values in 4.0.0, ' +
2751
+ 'consider using the `.val()` method instead.'
2752
+ );
2753
+ }
2754
+
2523
2755
  if (arguments.length > 1) {
2524
2756
  triggerChange = arguments[1];
2525
2757
  }
@@ -2563,7 +2795,6 @@ the specific language governing permissions and limitations under the Apache Lic
2563
2795
  self=this;
2564
2796
 
2565
2797
  // TODO validate placeholder is a string if specified
2566
-
2567
2798
  if (opts.element.get(0).tagName.toLowerCase() === "select") {
2568
2799
  // install the selection initializer
2569
2800
  opts.initSelection = function (element, callback) {
@@ -2578,7 +2809,7 @@ the specific language governing permissions and limitations under the Apache Lic
2578
2809
  } else if ("data" in opts) {
2579
2810
  // install default initSelection when applied to hidden input and data is local
2580
2811
  opts.initSelection = opts.initSelection || function (element, callback) {
2581
- var ids = splitVal(element.val(), opts.separator);
2812
+ var ids = splitVal(element.val(), opts.separator, opts.transformVal);
2582
2813
  //search in data by array of ids, storing matching items in a list
2583
2814
  var matches = [];
2584
2815
  opts.query({
@@ -2655,8 +2886,7 @@ the specific language governing permissions and limitations under the Apache Lic
2655
2886
  this.selection = selection = this.container.find(selector);
2656
2887
 
2657
2888
  var _this = this;
2658
- this.selection.on("click", ".select2-search-choice:not(.select2-locked)", function (e) {
2659
- //killEvent(e);
2889
+ this.selection.on("click", ".select2-container:not(.select2-container-disabled) .select2-search-choice:not(.select2-locked)", function (e) {
2660
2890
  _this.search[0].focus();
2661
2891
  _this.selectChoice($(this));
2662
2892
  });
@@ -2667,6 +2897,7 @@ the specific language governing permissions and limitations under the Apache Lic
2667
2897
  this.search.prev()
2668
2898
  .text($("label[for='" + this.opts.element.attr("id") + "']").text())
2669
2899
  .attr('for', this.search.attr('id'));
2900
+ this.opts.element.on('focus.select2', this.bind(function () { this.focus(); }));
2670
2901
 
2671
2902
  this.search.on("input paste", this.bind(function() {
2672
2903
  if (this.search.attr('placeholder') && this.search.val().length == 0) return;
@@ -2818,7 +3049,7 @@ the specific language governing permissions and limitations under the Apache Lic
2818
3049
  }));
2819
3050
 
2820
3051
  this.initContainerWidth();
2821
- this.opts.element.addClass("select2-offscreen");
3052
+ this.opts.element.hide();
2822
3053
 
2823
3054
  // set the placeholder if necessary
2824
3055
  this.clearSearch();
@@ -2884,16 +3115,9 @@ the specific language governing permissions and limitations under the Apache Lic
2884
3115
 
2885
3116
  this.focusSearch();
2886
3117
 
2887
- // initializes search's value with nextSearchTerm (if defined by user)
2888
- // ignore nextSearchTerm if the dropdown is opened by the user pressing a letter
2889
- if(this.search.val() === "") {
2890
- if(this.nextSearchTerm != undefined){
2891
- this.search.val(this.nextSearchTerm);
2892
- this.search.select();
2893
- }
2894
- }
2895
-
3118
+ this.prefillNextSearchTerm();
2896
3119
  this.updateResults(true);
3120
+
2897
3121
  if (this.opts.shouldFocusInput(this)) {
2898
3122
  this.search.focus();
2899
3123
  }
@@ -2919,21 +3143,18 @@ the specific language governing permissions and limitations under the Apache Lic
2919
3143
 
2920
3144
  // multi
2921
3145
  updateSelection: function (data) {
2922
- var ids = [], filtered = [], self = this;
3146
+ var ids = {}, filtered = [], self = this;
2923
3147
 
2924
3148
  // filter out duplicates
2925
3149
  $(data).each(function () {
2926
- if (indexOf(self.id(this), ids) < 0) {
2927
- ids.push(self.id(this));
3150
+ if (!(self.id(this) in ids)) {
3151
+ ids[self.id(this)] = 0;
2928
3152
  filtered.push(this);
2929
3153
  }
2930
3154
  });
2931
- data = filtered;
2932
3155
 
2933
3156
  this.selection.find(".select2-search-choice").remove();
2934
- $(data).each(function () {
2935
- self.addSelectedChoice(this);
2936
- });
3157
+ this.addSelectedChoice(filtered);
2937
3158
  self.postprocessResults();
2938
3159
  },
2939
3160
 
@@ -2953,14 +3174,14 @@ the specific language governing permissions and limitations under the Apache Lic
2953
3174
  // multi
2954
3175
  onSelect: function (data, options) {
2955
3176
 
2956
- if (!this.triggerSelect(data)) { return; }
3177
+ if (!this.triggerSelect(data) || data.text === "") { return; }
2957
3178
 
2958
3179
  this.addSelectedChoice(data);
2959
3180
 
2960
3181
  this.opts.element.trigger({ type: "selected", val: this.id(data), choice: data });
2961
3182
 
2962
3183
  // keep track of the search's value before it gets cleared
2963
- this.nextSearchTerm = this.opts.nextSearchTerm(data, this.search.val());
3184
+ this.lastSearchTerm = this.search.val();
2964
3185
 
2965
3186
  this.clearSearch();
2966
3187
  this.updateResults();
@@ -2980,10 +3201,8 @@ the specific language governing permissions and limitations under the Apache Lic
2980
3201
  this.updateResults(true);
2981
3202
  } else {
2982
3203
  // initializes search's value with nextSearchTerm and update search result
2983
- if(this.nextSearchTerm != undefined){
2984
- this.search.val(this.nextSearchTerm);
3204
+ if (this.prefillNextSearchTerm()) {
2985
3205
  this.updateResults();
2986
- this.search.select();
2987
3206
  }
2988
3207
  }
2989
3208
  this.positionDropdown();
@@ -3009,6 +3228,14 @@ the specific language governing permissions and limitations under the Apache Lic
3009
3228
  },
3010
3229
 
3011
3230
  addSelectedChoice: function (data) {
3231
+ var val = this.getVal(), self = this;
3232
+ $(data).each(function () {
3233
+ val.push(self.createChoice(this));
3234
+ });
3235
+ this.setVal(val);
3236
+ },
3237
+
3238
+ createChoice: function (data) {
3012
3239
  var enableChoice = !data.locked,
3013
3240
  enabledItem = $(
3014
3241
  "<li class='select2-search-choice'>" +
@@ -3021,13 +3248,12 @@ the specific language governing permissions and limitations under the Apache Lic
3021
3248
  "</li>");
3022
3249
  var choice = enableChoice ? enabledItem : disabledItem,
3023
3250
  id = this.id(data),
3024
- val = this.getVal(),
3025
3251
  formatted,
3026
3252
  cssClass;
3027
3253
 
3028
3254
  formatted=this.opts.formatSelection(data, choice.find("div"), this.opts.escapeMarkup);
3029
3255
  if (formatted != undefined) {
3030
- choice.find("div").replaceWith("<div>"+formatted+"</div>");
3256
+ choice.find("div").replaceWith($("<div></div>").html(formatted));
3031
3257
  }
3032
3258
  cssClass=this.opts.formatSelectionCssClass(data, choice.find("div"));
3033
3259
  if (cssClass != undefined) {
@@ -3055,8 +3281,7 @@ the specific language governing permissions and limitations under the Apache Lic
3055
3281
  choice.data("select2-data", data);
3056
3282
  choice.insertBefore(this.searchContainer);
3057
3283
 
3058
- val.push(id);
3059
- this.setVal(val);
3284
+ return id;
3060
3285
  },
3061
3286
 
3062
3287
  // multi
@@ -3125,7 +3350,7 @@ the specific language governing permissions and limitations under the Apache Lic
3125
3350
  }
3126
3351
  });
3127
3352
 
3128
- if (this.highlight() == -1 && noHighlightUpdate !== false){
3353
+ if (this.highlight() == -1 && noHighlightUpdate !== false && this.opts.closeOnSelect === true){
3129
3354
  self.highlight(0);
3130
3355
  }
3131
3356
 
@@ -3182,20 +3407,22 @@ the specific language governing permissions and limitations under the Apache Lic
3182
3407
  return val === null ? [] : val;
3183
3408
  } else {
3184
3409
  val = this.opts.element.val();
3185
- return splitVal(val, this.opts.separator);
3410
+ return splitVal(val, this.opts.separator, this.opts.transformVal);
3186
3411
  }
3187
3412
  },
3188
3413
 
3189
3414
  // multi
3190
3415
  setVal: function (val) {
3191
- var unique;
3192
3416
  if (this.select) {
3193
3417
  this.select.val(val);
3194
3418
  } else {
3195
- unique = [];
3419
+ var unique = [], valMap = {};
3196
3420
  // filter out duplicates
3197
3421
  $(val).each(function () {
3198
- if (indexOf(this, unique) < 0) unique.push(this);
3422
+ if (!(this in valMap)) {
3423
+ unique.push(this);
3424
+ valMap[this] = 0;
3425
+ }
3199
3426
  });
3200
3427
  this.opts.element.val(unique.length === 0 ? "" : unique.join(this.opts.separator));
3201
3428
  }
@@ -3211,11 +3438,9 @@ the specific language governing permissions and limitations under the Apache Lic
3211
3438
  for (var j = 0; j < old.length; j++) {
3212
3439
  if (equal(this.opts.id(current[i]), this.opts.id(old[j]))) {
3213
3440
  current.splice(i, 1);
3214
- if(i>0){
3215
- i--;
3216
- }
3441
+ i--;
3217
3442
  old.splice(j, 1);
3218
- j--;
3443
+ break;
3219
3444
  }
3220
3445
  }
3221
3446
  }
@@ -3385,6 +3610,7 @@ the specific language governing permissions and limitations under the Apache Lic
3385
3610
 
3386
3611
  // plugin defaults, accessible to users
3387
3612
  $.fn.select2.defaults = {
3613
+ debug: false,
3388
3614
  width: "copy",
3389
3615
  loadMorePadding: 0,
3390
3616
  closeOnSelect: true,
@@ -3395,29 +3621,36 @@ the specific language governing permissions and limitations under the Apache Lic
3395
3621
  dropdownCssClass: "",
3396
3622
  formatResult: function(result, container, query, escapeMarkup) {
3397
3623
  var markup=[];
3398
- markMatch(result.text, query.term, markup, escapeMarkup);
3624
+ markMatch(this.text(result), query.term, markup, escapeMarkup);
3399
3625
  return markup.join("");
3400
3626
  },
3627
+ transformVal: function(val) {
3628
+ return $.trim(val);
3629
+ },
3401
3630
  formatSelection: function (data, container, escapeMarkup) {
3402
- return data ? escapeMarkup(data.text) : undefined;
3631
+ return data ? escapeMarkup(this.text(data)) : undefined;
3403
3632
  },
3404
3633
  sortResults: function (results, container, query) {
3405
3634
  return results;
3406
3635
  },
3407
3636
  formatResultCssClass: function(data) {return data.css;},
3408
3637
  formatSelectionCssClass: function(data, container) {return undefined;},
3409
- formatMatches: function (matches) { if (matches === 1) { return "One result is available, press enter to select it."; } return matches + " results are available, use up and down arrow keys to navigate."; },
3410
- formatNoMatches: function () { return "No matches found"; },
3411
- formatInputTooShort: function (input, min) { var n = min - input.length; return "Please enter " + n + " or more character" + (n == 1? "" : "s"); },
3412
- formatInputTooLong: function (input, max) { var n = input.length - max; return "Please delete " + n + " character" + (n == 1? "" : "s"); },
3413
- formatSelectionTooBig: function (limit) { return "You can only select " + limit + " item" + (limit == 1 ? "" : "s"); },
3414
- formatLoadMore: function (pageNumber) { return "Loading more results…"; },
3415
- formatSearching: function () { return "Searching…"; },
3416
3638
  minimumResultsForSearch: 0,
3417
3639
  minimumInputLength: 0,
3418
3640
  maximumInputLength: null,
3419
3641
  maximumSelectionSize: 0,
3420
3642
  id: function (e) { return e == undefined ? null : e.id; },
3643
+ text: function (e) {
3644
+ if (e && this.data && this.data.text) {
3645
+ if ($.isFunction(this.data.text)) {
3646
+ return this.data.text(e);
3647
+ } else {
3648
+ return e[this.data.text];
3649
+ }
3650
+ } else {
3651
+ return e.text;
3652
+ }
3653
+ },
3421
3654
  matcher: function(term, text) {
3422
3655
  return stripDiacritics(''+text).toUpperCase().indexOf(stripDiacritics(''+term).toUpperCase()) >= 0;
3423
3656
  },
@@ -3451,6 +3684,21 @@ the specific language governing permissions and limitations under the Apache Lic
3451
3684
  }
3452
3685
  };
3453
3686
 
3687
+ $.fn.select2.locales = [];
3688
+
3689
+ $.fn.select2.locales['en'] = {
3690
+ formatMatches: function (matches) { if (matches === 1) { return "One result is available, press enter to select it."; } return matches + " results are available, use up and down arrow keys to navigate."; },
3691
+ formatNoMatches: function () { return "No matches found"; },
3692
+ formatAjaxError: function (jqXHR, textStatus, errorThrown) { return "Loading failed"; },
3693
+ formatInputTooShort: function (input, min) { var n = min - input.length; return "Please enter " + n + " or more character" + (n == 1 ? "" : "s"); },
3694
+ formatInputTooLong: function (input, max) { var n = input.length - max; return "Please delete " + n + " character" + (n == 1 ? "" : "s"); },
3695
+ formatSelectionTooBig: function (limit) { return "You can only select " + limit + " item" + (limit == 1 ? "" : "s"); },
3696
+ formatLoadMore: function (pageNumber) { return "Loading more results…"; },
3697
+ formatSearching: function () { return "Searching…"; }
3698
+ };
3699
+
3700
+ $.extend($.fn.select2.defaults, $.fn.select2.locales['en']);
3701
+
3454
3702
  $.fn.select2.ajaxDefaults = {
3455
3703
  transport: $.ajax,
3456
3704
  params: {