select2-rails 3.5.9 → 3.5.11

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.
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: {