Browse Source

Merge pull request #5614 from select2/develop

Release Select2 4.0.9
Kevin Brown 5 years ago
parent
commit
2148b6d3ae
100 changed files with 2142 additions and 550 deletions
  1. 29 0
      CHANGELOG.md
  2. 1 1
      component.json
  3. 2 1
      dist/css/select2.css
  4. 0 0
      dist/css/select2.min.css
  5. 1 1
      dist/js/i18n/af.js
  6. 1 1
      dist/js/i18n/ar.js
  7. 1 1
      dist/js/i18n/az.js
  8. 1 1
      dist/js/i18n/bg.js
  9. 1 1
      dist/js/i18n/bn.js
  10. 1 1
      dist/js/i18n/bs.js
  11. 1 1
      dist/js/i18n/ca.js
  12. 1 1
      dist/js/i18n/cs.js
  13. 1 1
      dist/js/i18n/da.js
  14. 1 1
      dist/js/i18n/de.js
  15. 1 1
      dist/js/i18n/dsb.js
  16. 1 1
      dist/js/i18n/el.js
  17. 1 1
      dist/js/i18n/en.js
  18. 1 1
      dist/js/i18n/es.js
  19. 1 1
      dist/js/i18n/et.js
  20. 1 1
      dist/js/i18n/eu.js
  21. 1 1
      dist/js/i18n/fa.js
  22. 1 1
      dist/js/i18n/fi.js
  23. 1 1
      dist/js/i18n/fr.js
  24. 1 1
      dist/js/i18n/gl.js
  25. 1 1
      dist/js/i18n/he.js
  26. 1 1
      dist/js/i18n/hi.js
  27. 1 1
      dist/js/i18n/hr.js
  28. 1 1
      dist/js/i18n/hsb.js
  29. 1 1
      dist/js/i18n/hu.js
  30. 1 1
      dist/js/i18n/hy.js
  31. 1 1
      dist/js/i18n/id.js
  32. 1 1
      dist/js/i18n/is.js
  33. 1 1
      dist/js/i18n/it.js
  34. 1 1
      dist/js/i18n/ja.js
  35. 1 1
      dist/js/i18n/ka.js
  36. 1 1
      dist/js/i18n/km.js
  37. 1 1
      dist/js/i18n/ko.js
  38. 1 1
      dist/js/i18n/lt.js
  39. 1 1
      dist/js/i18n/lv.js
  40. 1 1
      dist/js/i18n/mk.js
  41. 1 1
      dist/js/i18n/ms.js
  42. 1 1
      dist/js/i18n/nb.js
  43. 1 1
      dist/js/i18n/ne.js
  44. 1 1
      dist/js/i18n/nl.js
  45. 1 1
      dist/js/i18n/pl.js
  46. 1 1
      dist/js/i18n/ps.js
  47. 1 1
      dist/js/i18n/pt-BR.js
  48. 1 1
      dist/js/i18n/pt.js
  49. 1 1
      dist/js/i18n/ro.js
  50. 1 1
      dist/js/i18n/ru.js
  51. 1 1
      dist/js/i18n/sk.js
  52. 1 1
      dist/js/i18n/sl.js
  53. 1 1
      dist/js/i18n/sq.js
  54. 1 1
      dist/js/i18n/sr-Cyrl.js
  55. 1 1
      dist/js/i18n/sr.js
  56. 1 1
      dist/js/i18n/sv.js
  57. 1 1
      dist/js/i18n/th.js
  58. 1 1
      dist/js/i18n/tk.js
  59. 1 1
      dist/js/i18n/tr.js
  60. 1 1
      dist/js/i18n/uk.js
  61. 1 1
      dist/js/i18n/vi.js
  62. 1 1
      dist/js/i18n/zh-CN.js
  63. 1 1
      dist/js/i18n/zh-TW.js
  64. 229 99
      dist/js/select2.full.js
  65. 0 1
      dist/js/select2.full.min.js
  66. 229 99
      dist/js/select2.js
  67. 0 1
      dist/js/select2.min.js
  68. 2 2
      package.json
  69. 7 3
      src/js/select2/data/array.js
  70. 24 1
      src/js/select2/data/maximumSelectionLength.js
  71. 0 2
      src/js/select2/data/tags.js
  72. 114 54
      src/js/select2/defaults.js
  73. 25 16
      src/js/select2/dropdown/attachBody.js
  74. 1 1
      src/js/select2/dropdown/infiniteScroll.js
  75. 14 1
      src/js/select2/dropdown/search.js
  76. 4 6
      src/js/select2/i18n/de.js
  77. 4 8
      src/js/select2/options.js
  78. 3 3
      src/js/select2/results.js
  79. 3 4
      src/js/select2/selection/base.js
  80. 6 1
      src/js/select2/selection/multiple.js
  81. 17 3
      src/js/select2/selection/search.js
  82. 8 1
      src/js/select2/selection/single.js
  83. 2 0
      src/js/select2/utils.js
  84. 6 0
      src/scss/theme/default/_multiple.scss
  85. 0 51
      tests/a11y/search-tests.js
  86. 32 0
      tests/a11y/selection-tests.js
  87. 54 0
      tests/data/array-tests.js
  88. 15 0
      tests/data/inputData-tests.js
  89. 70 120
      tests/data/maximumSelectionLength-tests.js
  90. 185 0
      tests/dropdown/search-a11y-tests.js
  91. 262 2
      tests/options/translation-tests.js
  92. 25 0
      tests/results/a11y-tests.js
  93. 54 1
      tests/results/option-tests.js
  94. 70 0
      tests/selection/allowClear-tests.js
  95. 110 3
      tests/selection/multiple-tests.js
  96. 217 0
      tests/selection/search-a11y-tests.js
  97. 55 0
      tests/selection/search-placeholder-tests.js
  98. 87 1
      tests/selection/search-tests.js
  99. 112 4
      tests/selection/single-tests.js
  100. 5 1
      tests/unit-jq1.html

+ 29 - 0
CHANGELOG.md

@@ -1,5 +1,34 @@
 # Change Log
 
+## 4.0.9
+
+### New features / improvements
+
+* Mirror disabled state through aria-disabled on selection (#5579)
+* Select2 now clears the internal ID when it is destroyed (#5587)
+* Set the main ARIA 1.1 roles and properties for comboboxes (#5582)
+* The `language` option now has a clearly defined fallback chain (#5602)
+
+### Bug fixes
+
+* Do not propagate click when search box is not empty (#5580)
+* Fix `maximumSelectionLength` being ignored by `closeOnSelect` (#5581)
+* Fix generated options not receiving result IDs (#5586)
+* Remove selection title attribute if text is empty (#5589)
+* Reposition dropdown whenever items are selected (#5590)
+* Fix dropdown positioning when displayed above with messages (#5592)
+* Fix search box expanding width of container (#5595)
+* `allowClear` no longer shifts selections to a new line (#5603)
+
+### Translations
+
+* Fix error in German translations (#5604)
+
+### Miscellaneous
+
+* Updated development grunt version so it no longer shows as vulnerable (#5597)
+* Remove unused variables (#5554)
+
 ## 4.0.8
 
 ### New features / improvements

+ 1 - 1
component.json

@@ -2,7 +2,7 @@
   "name": "select2",
   "repo": "select/select2",
   "description": "Select2 is a jQuery based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results.",
-  "version": "4.0.8",
+  "version": "4.0.9",
   "demo": "https://select2.org/",
   "keywords": [
     "jquery"

+ 2 - 1
dist/css/select2.css

@@ -193,7 +193,8 @@
     float: right;
     font-weight: bold;
     margin-top: 5px;
-    margin-right: 10px; }
+    margin-right: 10px;
+    padding: 1px; }
   .select2-container--default .select2-selection--multiple .select2-selection__choice {
     background-color: #e4e4e4;
     border: 1px solid #aaa;

File diff suppressed because it is too large
+ 0 - 0
dist/css/select2.min.css


+ 1 - 1
dist/js/i18n/af.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/af",[],function(){return{errorLoading:function(){return"Die resultate kon nie gelaai word nie."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Verwyders asseblief "+n+" character";return 1!=n&&(r+="s"),r},inputTooShort:function(e){return"Voer asseblief "+(e.minimum-e.input.length)+" of meer karakters"},loadingMore:function(){return"Meer resultate word gelaai…"},maximumSelected:function(e){var n="Kies asseblief net "+e.maximum+" item";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"Geen resultate gevind"},searching:function(){return"Besig…"},removeAllItems:function(){return"Verwyder alle items"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/ar.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ar",[],function(){return{errorLoading:function(){return"لا يمكن تحميل النتائج"},inputTooLong:function(n){return"الرجاء حذف "+(n.input.length-n.maximum)+" عناصر"},inputTooShort:function(n){return"الرجاء إضافة "+(n.minimum-n.input.length)+" عناصر"},loadingMore:function(){return"جاري تحميل نتائج إضافية..."},maximumSelected:function(n){return"تستطيع إختيار "+n.maximum+" بنود فقط"},noResults:function(){return"لم يتم العثور على أي نتائج"},searching:function(){return"جاري البحث…"},removeAllItems:function(){return"قم بإزالة كل العناصر"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/az.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/az",[],function(){return{inputTooLong:function(n){return n.input.length-n.maximum+" simvol silin"},inputTooShort:function(n){return n.minimum-n.input.length+" simvol daxil edin"},loadingMore:function(){return"Daha çox nəticə yüklənir…"},maximumSelected:function(n){return"Sadəcə "+n.maximum+" element seçə bilərsiniz"},noResults:function(){return"Nəticə tapılmadı"},searching:function(){return"Axtarılır…"},removeAllItems:function(){return"Bütün elementləri sil"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/bg.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/bg",[],function(){return{inputTooLong:function(n){var e=n.input.length-n.maximum,u="Моля въведете с "+e+" по-малко символ";return e>1&&(u+="a"),u},inputTooShort:function(n){var e=n.minimum-n.input.length,u="Моля въведете още "+e+" символ";return e>1&&(u+="a"),u},loadingMore:function(){return"Зареждат се още…"},maximumSelected:function(n){var e="Можете да направите до "+n.maximum+" ";return n.maximum>1?e+="избора":e+="избор",e},noResults:function(){return"Няма намерени съвпадения"},searching:function(){return"Търсене…"},removeAllItems:function(){return"Премахнете всички елементи"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/bn.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/bn",[],function(){return{errorLoading:function(){return"ফলাফলগুলি লোড করা যায়নি।"},inputTooLong:function(n){var e=n.input.length-n.maximum,u="অনুগ্রহ করে "+e+" টি অক্ষর মুছে দিন।";return 1!=e&&(u="অনুগ্রহ করে "+e+" টি অক্ষর মুছে দিন।"),u},inputTooShort:function(n){return n.minimum-n.input.length+" টি অক্ষর অথবা অধিক অক্ষর লিখুন।"},loadingMore:function(){return"আরো ফলাফল লোড হচ্ছে ..."},maximumSelected:function(n){var e=n.maximum+" টি আইটেম নির্বাচন করতে পারবেন।";return 1!=n.maximum&&(e=n.maximum+" টি আইটেম নির্বাচন করতে পারবেন।"),e},noResults:function(){return"কোন ফলাফল পাওয়া যায়নি।"},searching:function(){return"অনুসন্ধান করা হচ্ছে ..."}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/bs.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/bs",[],function(){function e(e,n,r,t){return e%10==1&&e%100!=11?n:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?r:t}return{errorLoading:function(){return"Preuzimanje nije uspijelo."},inputTooLong:function(n){var r=n.input.length-n.maximum,t="Obrišite "+r+" simbol";return t+=e(r,"","a","a")},inputTooShort:function(n){var r=n.minimum-n.input.length,t="Ukucajte bar još "+r+" simbol";return t+=e(r,"","a","a")},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(n){var r="Možete izabrati samo "+n.maximum+" stavk";return r+=e(n.maximum,"u","e","i")},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Uklonite sve stavke"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/ca.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/ca",[],function(){return{errorLoading:function(){return"La càrrega ha fallat"},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Si us plau, elimina "+n+" car";return r+=1==n?"àcter":"àcters"},inputTooShort:function(e){var n=e.minimum-e.input.length,r="Si us plau, introdueix "+n+" car";return r+=1==n?"àcter":"àcters"},loadingMore:function(){return"Carregant més resultats…"},maximumSelected:function(e){var n="Només es pot seleccionar "+e.maximum+" element";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No s'han trobat resultats"},searching:function(){return"Cercant…"},removeAllItems:function(){return"Treu tots els elements"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/cs.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/cs",[],function(){function e(e,n){switch(e){case 2:return n?"dva":"dvě";case 3:return"tři";case 4:return"čtyři"}return""}return{errorLoading:function(){return"Výsledky nemohly být načteny."},inputTooLong:function(n){var t=n.input.length-n.maximum;return 1==t?"Prosím, zadejte o jeden znak méně.":t<=4?"Prosím, zadejte o "+e(t,!0)+" znaky méně.":"Prosím, zadejte o "+t+" znaků méně."},inputTooShort:function(n){var t=n.minimum-n.input.length;return 1==t?"Prosím, zadejte ještě jeden znak.":t<=4?"Prosím, zadejte ještě další "+e(t,!0)+" znaky.":"Prosím, zadejte ještě dalších "+t+" znaků."},loadingMore:function(){return"Načítají se další výsledky…"},maximumSelected:function(n){var t=n.maximum;return 1==t?"Můžete zvolit jen jednu položku.":t<=4?"Můžete zvolit maximálně "+e(t,!1)+" položky.":"Můžete zvolit maximálně "+t+" položek."},noResults:function(){return"Nenalezeny žádné položky."},searching:function(){return"Vyhledávání…"},removeAllItems:function(){return"Odstraňte všechny položky"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/da.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/da",[],function(){return{errorLoading:function(){return"Resultaterne kunne ikke indlæses."},inputTooLong:function(e){return"Angiv venligst "+(e.input.length-e.maximum)+" tegn mindre"},inputTooShort:function(e){return"Angiv venligst "+(e.minimum-e.input.length)+" tegn mere"},loadingMore:function(){return"Indlæser flere resultater…"},maximumSelected:function(e){var n="Du kan kun vælge "+e.maximum+" emne";return 1!=e.maximum&&(n+="r"),n},noResults:function(){return"Ingen resultater fundet"},searching:function(){return"Søger…"},removeAllItems:function(){return"Fjern alle elementer"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/de.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/de",[],function(){return{errorLoading:function(){return"Die Ergebnisse konnten nicht geladen werden."},inputTooLong:function(e){return"Bitte "+(e.input.length-e.maximum)+" Zeichen weniger eingeben"},inputTooShort:function(e){return"Bitte "+(e.minimum-e.input.length)+" Zeichen mehr eingeben"},loadingMore:function(){return"Lade mehr Ergebnisse…"},maximumSelected:function(e){var n="Sie können nur "+e.maximum+" Eintr";return 1===e.maximum?n+="ag":n+="äge",n+=" auswählen"},noResults:function(){return"Keine Übereinstimmungen gefunden"},searching:function(){return"Suche…"},removeAllItems:function(){return"Entferne alle Gegenstände"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/dsb.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/dsb",[],function(){var n=["znamuško","znamušce","znamuška","znamuškow"],e=["zapisk","zapiska","zapiski","zapiskow"],u=function(n,e){return 1===n?e[0]:2===n?e[1]:n>2&&n<=4?e[2]:n>=5?e[3]:void 0};return{errorLoading:function(){return"Wuslědki njejsu se dali zacytaś."},inputTooLong:function(e){var a=e.input.length-e.maximum;return"Pšosym lašuj "+a+" "+u(a,n)},inputTooShort:function(e){var a=e.minimum-e.input.length;return"Pšosym zapódaj nanejmjenjej "+a+" "+u(a,n)},loadingMore:function(){return"Dalšne wuslědki se zacytaju…"},maximumSelected:function(n){return"Móžoš jano "+n.maximum+" "+u(n.maximum,e)+"wubraś."},noResults:function(){return"Žedne wuslědki namakane"},searching:function(){return"Pyta se…"},removeAllItems:function(){return"Remove all items"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/el.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/el",[],function(){return{errorLoading:function(){return"Τα αποτελέσματα δεν μπόρεσαν να φορτώσουν."},inputTooLong:function(n){var e=n.input.length-n.maximum,u="Παρακαλώ διαγράψτε "+e+" χαρακτήρ";return 1==e&&(u+="α"),1!=e&&(u+="ες"),u},inputTooShort:function(n){return"Παρακαλώ συμπληρώστε "+(n.minimum-n.input.length)+" ή περισσότερους χαρακτήρες"},loadingMore:function(){return"Φόρτωση περισσότερων αποτελεσμάτων…"},maximumSelected:function(n){var e="Μπορείτε να επιλέξετε μόνο "+n.maximum+" επιλογ";return 1==n.maximum&&(e+="ή"),1!=n.maximum&&(e+="ές"),e},noResults:function(){return"Δεν βρέθηκαν αποτελέσματα"},searching:function(){return"Αναζήτηση…"},removeAllItems:function(){return"Καταργήστε όλα τα στοιχεία"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/en.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/en",[],function(){return{errorLoading:function(){return"The results could not be loaded."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Please delete "+n+" character";return 1!=n&&(r+="s"),r},inputTooShort:function(e){return"Please enter "+(e.minimum-e.input.length)+" or more characters"},loadingMore:function(){return"Loading more results…"},maximumSelected:function(e){var n="You can only select "+e.maximum+" item";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No results found"},searching:function(){return"Searching…"},removeAllItems:function(){return"Remove all items"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/es.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/es",[],function(){return{errorLoading:function(){return"No se pudieron cargar los resultados"},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Por favor, elimine "+n+" car";return r+=1==n?"ácter":"acteres"},inputTooShort:function(e){var n=e.minimum-e.input.length,r="Por favor, introduzca "+n+" car";return r+=1==n?"ácter":"acteres"},loadingMore:function(){return"Cargando más resultados…"},maximumSelected:function(e){var n="Sólo puede seleccionar "+e.maximum+" elemento";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No se encontraron resultados"},searching:function(){return"Buscando…"},removeAllItems:function(){return"Eliminar todos los elementos"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/et.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/et",[],function(){return{inputTooLong:function(e){var n=e.input.length-e.maximum,t="Sisesta "+n+" täht";return 1!=n&&(t+="e"),t+=" vähem"},inputTooShort:function(e){var n=e.minimum-e.input.length,t="Sisesta "+n+" täht";return 1!=n&&(t+="e"),t+=" rohkem"},loadingMore:function(){return"Laen tulemusi…"},maximumSelected:function(e){var n="Saad vaid "+e.maximum+" tulemus";return 1==e.maximum?n+="e":n+="t",n+=" valida"},noResults:function(){return"Tulemused puuduvad"},searching:function(){return"Otsin…"},removeAllItems:function(){return"Eemalda kõik esemed"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/eu.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/eu",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Idatzi ";return n+=1==t?"karaktere bat":t+" karaktere",n+=" gutxiago"},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Idatzi ";return n+=1==t?"karaktere bat":t+" karaktere",n+=" gehiago"},loadingMore:function(){return"Emaitza gehiago kargatzen…"},maximumSelected:function(e){return 1===e.maximum?"Elementu bakarra hauta dezakezu":e.maximum+" elementu hauta ditzakezu soilik"},noResults:function(){return"Ez da bat datorrenik aurkitu"},searching:function(){return"Bilatzen…"},removeAllItems:function(){return"Kendu elementu guztiak"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/fa.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/fa",[],function(){return{errorLoading:function(){return"امکان بارگذاری نتایج وجود ندارد."},inputTooLong:function(n){return"لطفاً "+(n.input.length-n.maximum)+" کاراکتر را حذف نمایید"},inputTooShort:function(n){return"لطفاً تعداد "+(n.minimum-n.input.length)+" کاراکتر یا بیشتر وارد نمایید"},loadingMore:function(){return"در حال بارگذاری نتایج بیشتر..."},maximumSelected:function(n){return"شما تنها می‌توانید "+n.maximum+" آیتم را انتخاب نمایید"},noResults:function(){return"هیچ نتیجه‌ای یافت نشد"},searching:function(){return"در حال جستجو..."},removeAllItems:function(){return"همه موارد را حذف کنید"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/fi.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/fi",[],function(){return{errorLoading:function(){return"Tuloksia ei saatu ladattua."},inputTooLong:function(n){return"Ole hyvä ja anna "+(n.input.length-n.maximum)+" merkkiä vähemmän"},inputTooShort:function(n){return"Ole hyvä ja anna "+(n.minimum-n.input.length)+" merkkiä lisää"},loadingMore:function(){return"Ladataan lisää tuloksia…"},maximumSelected:function(n){return"Voit valita ainoastaan "+n.maximum+" kpl"},noResults:function(){return"Ei tuloksia"},searching:function(){return"Haetaan…"},removeAllItems:function(){return"Poista kaikki kohteet"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/fr.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/fr",[],function(){return{errorLoading:function(){return"Les résultats ne peuvent pas être chargés."},inputTooLong:function(e){var n=e.input.length-e.maximum;return"Supprimez "+n+" caractère"+(n>1?"s":"")},inputTooShort:function(e){var n=e.minimum-e.input.length;return"Saisissez au moins "+n+" caractère"+(n>1?"s":"")},loadingMore:function(){return"Chargement de résultats supplémentaires…"},maximumSelected:function(e){return"Vous pouvez seulement sélectionner "+e.maximum+" élément"+(e.maximum>1?"s":"")},noResults:function(){return"Aucun résultat trouvé"},searching:function(){return"Recherche en cours…"},removeAllItems:function(){return"Supprimer tous les éléments"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/gl.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/gl",[],function(){return{errorLoading:function(){return"Non foi posíbel cargar os resultados."},inputTooLong:function(e){var n=e.input.length-e.maximum;return 1===n?"Elimine un carácter":"Elimine "+n+" caracteres"},inputTooShort:function(e){var n=e.minimum-e.input.length;return 1===n?"Engada un carácter":"Engada "+n+" caracteres"},loadingMore:function(){return"Cargando máis resultados…"},maximumSelected:function(e){return 1===e.maximum?"Só pode seleccionar un elemento":"Só pode seleccionar "+e.maximum+" elementos"},noResults:function(){return"Non se atoparon resultados"},searching:function(){return"Buscando…"},removeAllItems:function(){return"Elimina todos os elementos"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/he.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/he",[],function(){return{errorLoading:function(){return"שגיאה בטעינת התוצאות"},inputTooLong:function(n){var e=n.input.length-n.maximum,r="נא למחוק ";return r+=1===e?"תו אחד":e+" תווים"},inputTooShort:function(n){var e=n.minimum-n.input.length,r="נא להכניס ";return r+=1===e?"תו אחד":e+" תווים",r+=" או יותר"},loadingMore:function(){return"טוען תוצאות נוספות…"},maximumSelected:function(n){var e="באפשרותך לבחור עד ";return 1===n.maximum?e+="פריט אחד":e+=n.maximum+" פריטים",e},noResults:function(){return"לא נמצאו תוצאות"},searching:function(){return"מחפש…"},removeAllItems:function(){return"הסר את כל הפריטים"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/hi.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hi",[],function(){return{errorLoading:function(){return"परिणामों को लोड नहीं किया जा सका।"},inputTooLong:function(n){var e=n.input.length-n.maximum,r=e+" अक्षर को हटा दें";return e>1&&(r=e+" अक्षरों को हटा दें "),r},inputTooShort:function(n){return"कृपया "+(n.minimum-n.input.length)+" या अधिक अक्षर दर्ज करें"},loadingMore:function(){return"अधिक परिणाम लोड हो रहे है..."},maximumSelected:function(n){return"आप केवल "+n.maximum+" आइटम का चयन कर सकते हैं"},noResults:function(){return"कोई परिणाम नहीं मिला"},searching:function(){return"खोज रहा है..."},removeAllItems:function(){return"सभी वस्तुओं को हटा दें"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/hr.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hr",[],function(){function n(n){var e=" "+n+" znak";return n%10<5&&n%10>0&&(n%100<5||n%100>19)?n%10>1&&(e+="a"):e+="ova",e}return{errorLoading:function(){return"Preuzimanje nije uspjelo."},inputTooLong:function(e){return"Unesite "+n(e.input.length-e.maximum)},inputTooShort:function(e){return"Unesite još "+n(e.minimum-e.input.length)},loadingMore:function(){return"Učitavanje rezultata…"},maximumSelected:function(n){return"Maksimalan broj odabranih stavki je "+n.maximum},noResults:function(){return"Nema rezultata"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Ukloni sve stavke"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/hsb.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hsb",[],function(){var n=["znamješko","znamješce","znamješka","znamješkow"],e=["zapisk","zapiskaj","zapiski","zapiskow"],u=function(n,e){return 1===n?e[0]:2===n?e[1]:n>2&&n<=4?e[2]:n>=5?e[3]:void 0};return{errorLoading:function(){return"Wuslědki njedachu so začitać."},inputTooLong:function(e){var a=e.input.length-e.maximum;return"Prošu zhašej "+a+" "+u(a,n)},inputTooShort:function(e){var a=e.minimum-e.input.length;return"Prošu zapodaj znajmjeńša "+a+" "+u(a,n)},loadingMore:function(){return"Dalše wuslědki so začitaja…"},maximumSelected:function(n){return"Móžeš jenož "+n.maximum+" "+u(n.maximum,e)+"wubrać"},noResults:function(){return"Žane wuslědki namakane"},searching:function(){return"Pyta so…"},removeAllItems:function(){return"Remove all items"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/hu.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/hu",[],function(){return{errorLoading:function(){return"Az eredmények betöltése nem sikerült."},inputTooLong:function(e){return"Túl hosszú. "+(e.input.length-e.maximum)+" karakterrel több, mint kellene."},inputTooShort:function(e){return"Túl rövid. Még "+(e.minimum-e.input.length)+" karakter hiányzik."},loadingMore:function(){return"Töltés…"},maximumSelected:function(e){return"Csak "+e.maximum+" elemet lehet kiválasztani."},noResults:function(){return"Nincs találat."},searching:function(){return"Keresés…"},removeAllItems:function(){return"Távolítson el minden elemet"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/hy.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hy",[],function(){return{errorLoading:function(){return"Արդյունքները հնարավոր չէ բեռնել։"},inputTooLong:function(n){return"Խնդրում ենք հեռացնել "+(n.input.length-n.maximum)+" նշան"},inputTooShort:function(n){return"Խնդրում ենք մուտքագրել "+(n.minimum-n.input.length)+" կամ ավել նշաններ"},loadingMore:function(){return"Բեռնվում են նոր արդյունքներ․․․"},maximumSelected:function(n){return"Դուք կարող եք ընտրել առավելագույնը "+n.maximum+" կետ"},noResults:function(){return"Արդյունքներ չեն գտնվել"},searching:function(){return"Որոնում․․․"},removeAllItems:function(){return"Հեռացնել բոլոր տարրերը"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/id.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/id",[],function(){return{errorLoading:function(){return"Data tidak boleh diambil."},inputTooLong:function(n){return"Hapuskan "+(n.input.length-n.maximum)+" huruf"},inputTooShort:function(n){return"Masukkan "+(n.minimum-n.input.length)+" huruf lagi"},loadingMore:function(){return"Mengambil data…"},maximumSelected:function(n){return"Anda hanya dapat memilih "+n.maximum+" pilihan"},noResults:function(){return"Tidak ada data yang sesuai"},searching:function(){return"Mencari…"},removeAllItems:function(){return"Hapus semua item"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/is.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/is",[],function(){return{inputTooLong:function(n){var t=n.input.length-n.maximum,e="Vinsamlegast styttið texta um "+t+" staf";return t<=1?e:e+"i"},inputTooShort:function(n){var t=n.minimum-n.input.length,e="Vinsamlegast skrifið "+t+" staf";return t>1&&(e+="i"),e+=" í viðbót"},loadingMore:function(){return"Sæki fleiri niðurstöður…"},maximumSelected:function(n){return"Þú getur aðeins valið "+n.maximum+" atriði"},noResults:function(){return"Ekkert fannst"},searching:function(){return"Leita…"},removeAllItems:function(){return"Fjarlægðu öll atriði"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/it.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/it",[],function(){return{errorLoading:function(){return"I risultati non possono essere caricati."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Per favore cancella "+n+" caratter";return t+=1!==n?"i":"e"},inputTooShort:function(e){return"Per favore inserisci "+(e.minimum-e.input.length)+" o più caratteri"},loadingMore:function(){return"Caricando più risultati…"},maximumSelected:function(e){var n="Puoi selezionare solo "+e.maximum+" element";return 1!==e.maximum?n+="i":n+="o",n},noResults:function(){return"Nessun risultato trovato"},searching:function(){return"Sto cercando…"},removeAllItems:function(){return"Rimuovi tutti gli oggetti"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/ja.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ja",[],function(){return{errorLoading:function(){return"結果が読み込まれませんでした"},inputTooLong:function(n){return n.input.length-n.maximum+" 文字を削除してください"},inputTooShort:function(n){return"少なくとも "+(n.minimum-n.input.length)+" 文字を入力してください"},loadingMore:function(){return"読み込み中…"},maximumSelected:function(n){return n.maximum+" 件しか選択できません"},noResults:function(){return"対象が見つかりません"},searching:function(){return"検索しています…"},removeAllItems:function(){return"すべてのアイテムを削除"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/ka.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ka",[],function(){return{errorLoading:function(){return"მონაცემების ჩატვირთვა შეუძლებელია."},inputTooLong:function(n){return"გთხოვთ აკრიფეთ "+(n.input.length-n.maximum)+" სიმბოლოთი ნაკლები"},inputTooShort:function(n){return"გთხოვთ აკრიფეთ "+(n.minimum-n.input.length)+" სიმბოლო ან მეტი"},loadingMore:function(){return"მონაცემების ჩატვირთვა…"},maximumSelected:function(n){return"თქვენ შეგიძლიათ აირჩიოთ არაუმეტეს "+n.maximum+" ელემენტი"},noResults:function(){return"რეზულტატი არ მოიძებნა"},searching:function(){return"ძიება…"},removeAllItems:function(){return"ამოიღე ყველა ელემენტი"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/km.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/km",[],function(){return{errorLoading:function(){return"មិនអាចទាញយកទិន្នន័យ"},inputTooLong:function(n){return"សូមលុបចេញ  "+(n.input.length-n.maximum)+" អក្សរ"},inputTooShort:function(n){return"សូមបញ្ចូល"+(n.minimum-n.input.length)+" អក្សរ រឺ ច្រើនជាងនេះ"},loadingMore:function(){return"កំពុងទាញយកទិន្នន័យបន្ថែម..."},maximumSelected:function(n){return"អ្នកអាចជ្រើសរើសបានតែ "+n.maximum+" ជម្រើសប៉ុណ្ណោះ"},noResults:function(){return"មិនមានលទ្ធផល"},searching:function(){return"កំពុងស្វែងរក..."},removeAllItems:function(){return"លុបធាតុទាំងអស់"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/ko.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ko",[],function(){return{errorLoading:function(){return"결과를 불러올 수 없습니다."},inputTooLong:function(n){return"너무 깁니다. "+(n.input.length-n.maximum)+" 글자 지워주세요."},inputTooShort:function(n){return"너무 짧습니다. "+(n.minimum-n.input.length)+" 글자 더 입력해주세요."},loadingMore:function(){return"불러오는 중…"},maximumSelected:function(n){return"최대 "+n.maximum+"개까지만 선택 가능합니다."},noResults:function(){return"결과가 없습니다."},searching:function(){return"검색 중…"},removeAllItems:function(){return"모든 항목 삭제"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/lt.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/lt",[],function(){function n(n,e,i,t){return n%10==1&&(n%100<11||n%100>19)?e:n%10>=2&&n%10<=9&&(n%100<11||n%100>19)?i:t}return{inputTooLong:function(e){var i=e.input.length-e.maximum,t="Pašalinkite "+i+" simbol";return t+=n(i,"į","ius","ių")},inputTooShort:function(e){var i=e.minimum-e.input.length,t="Įrašykite dar "+i+" simbol";return t+=n(i,"į","ius","ių")},loadingMore:function(){return"Kraunama daugiau rezultatų…"},maximumSelected:function(e){var i="Jūs galite pasirinkti tik "+e.maximum+" element";return i+=n(e.maximum,"ą","us","ų")},noResults:function(){return"Atitikmenų nerasta"},searching:function(){return"Ieškoma…"},removeAllItems:function(){return"Pašalinti visus elementus"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/lv.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/lv",[],function(){function e(e,n,u,i){return 11===e?n:e%10==1?u:i}return{inputTooLong:function(n){var u=n.input.length-n.maximum,i="Lūdzu ievadiet par  "+u;return(i+=" simbol"+e(u,"iem","u","iem"))+" mazāk"},inputTooShort:function(n){var u=n.minimum-n.input.length,i="Lūdzu ievadiet vēl "+u;return i+=" simbol"+e(u,"us","u","us")},loadingMore:function(){return"Datu ielāde…"},maximumSelected:function(n){var u="Jūs varat izvēlēties ne vairāk kā "+n.maximum;return u+=" element"+e(n.maximum,"us","u","us")},noResults:function(){return"Sakritību nav"},searching:function(){return"Meklēšana…"},removeAllItems:function(){return"Noņemt visus vienumus"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/mk.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/mk",[],function(){return{inputTooLong:function(n){var e=(n.input.length,n.maximum,"Ве молиме внесете "+n.maximum+" помалку карактер");return 1!==n.maximum&&(e+="и"),e},inputTooShort:function(n){var e=(n.minimum,n.input.length,"Ве молиме внесете уште "+n.maximum+" карактер");return 1!==n.maximum&&(e+="и"),e},loadingMore:function(){return"Вчитување резултати…"},maximumSelected:function(n){var e="Можете да изберете само "+n.maximum+" ставк";return 1===n.maximum?e+="а":e+="и",e},noResults:function(){return"Нема пронајдено совпаѓања"},searching:function(){return"Пребарување…"},removeAllItems:function(){return"Отстрани ги сите предмети"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/ms.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ms",[],function(){return{errorLoading:function(){return"Keputusan tidak berjaya dimuatkan."},inputTooLong:function(n){return"Sila hapuskan "+(n.input.length-n.maximum)+" aksara"},inputTooShort:function(n){return"Sila masukkan "+(n.minimum-n.input.length)+" atau lebih aksara"},loadingMore:function(){return"Sedang memuatkan keputusan…"},maximumSelected:function(n){return"Anda hanya boleh memilih "+n.maximum+" pilihan"},noResults:function(){return"Tiada padanan yang ditemui"},searching:function(){return"Mencari…"},removeAllItems:function(){return"Keluarkan semua item"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/nb.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/nb",[],function(){return{errorLoading:function(){return"Kunne ikke hente resultater."},inputTooLong:function(e){return"Vennligst fjern "+(e.input.length-e.maximum)+" tegn"},inputTooShort:function(e){return"Vennligst skriv inn "+(e.minimum-e.input.length)+" tegn til"},loadingMore:function(){return"Laster flere resultater…"},maximumSelected:function(e){return"Du kan velge maks "+e.maximum+" elementer"},noResults:function(){return"Ingen treff"},searching:function(){return"Søker…"},removeAllItems:function(){return"Fjern alle elementer"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/ne.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ne",[],function(){return{errorLoading:function(){return"नतिजाहरु देखाउन सकिएन।"},inputTooLong:function(n){var e=n.input.length-n.maximum,u="कृपया "+e+" अक्षर मेटाउनुहोस्।";return 1!=e&&(u+="कृपया "+e+" अक्षरहरु मेटाउनुहोस्।"),u},inputTooShort:function(n){return"कृपया बाँकी रहेका "+(n.minimum-n.input.length)+" वा अरु धेरै अक्षरहरु भर्नुहोस्।"},loadingMore:function(){return"अरु नतिजाहरु भरिँदैछन् …"},maximumSelected:function(n){var e="तँपाई "+n.maximum+" वस्तु मात्र छान्न पाउँनुहुन्छ।";return 1!=n.maximum&&(e="तँपाई "+n.maximum+" वस्तुहरु मात्र छान्न पाउँनुहुन्छ।"),e},noResults:function(){return"कुनै पनि नतिजा भेटिएन।"},searching:function(){return"खोजि हुँदैछ…"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/nl.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/nl",[],function(){return{errorLoading:function(){return"De resultaten konden niet worden geladen."},inputTooLong:function(e){return"Gelieve "+(e.input.length-e.maximum)+" karakters te verwijderen"},inputTooShort:function(e){return"Gelieve "+(e.minimum-e.input.length)+" of meer karakters in te voeren"},loadingMore:function(){return"Meer resultaten laden…"},maximumSelected:function(e){var n=1==e.maximum?"kan":"kunnen",r="Er "+n+" maar "+e.maximum+" item";return 1!=e.maximum&&(r+="s"),r+=" worden geselecteerd"},noResults:function(){return"Geen resultaten gevonden…"},searching:function(){return"Zoeken…"},removeAllItems:function(){return"Verwijder alle items"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/pl.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/pl",[],function(){var n=["znak","znaki","znaków"],e=["element","elementy","elementów"],r=function(n,e){return 1===n?e[0]:n>1&&n<=4?e[1]:n>=5?e[2]:void 0};return{errorLoading:function(){return"Nie można załadować wyników."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Usuń "+t+" "+r(t,n)},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Podaj przynajmniej "+t+" "+r(t,n)},loadingMore:function(){return"Trwa ładowanie…"},maximumSelected:function(n){return"Możesz zaznaczyć tylko "+n.maximum+" "+r(n.maximum,e)},noResults:function(){return"Brak wyników"},searching:function(){return"Trwa wyszukiwanie…"},removeAllItems:function(){return"Usuń wszystkie przedmioty"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/ps.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ps",[],function(){return{errorLoading:function(){return"پايلي نه سي ترلاسه کېدای"},inputTooLong:function(n){var e=n.input.length-n.maximum,r="د مهربانۍ لمخي "+e+" توری ړنګ کړئ";return 1!=e&&(r=r.replace("توری","توري")),r},inputTooShort:function(n){return"لږ تر لږه "+(n.minimum-n.input.length)+" يا ډېر توري وليکئ"},loadingMore:function(){return"نوري پايلي ترلاسه کيږي..."},maximumSelected:function(n){var e="تاسو يوازي "+n.maximum+" قلم په نښه کولای سی";return 1!=n.maximum&&(e=e.replace("قلم","قلمونه")),e},noResults:function(){return"پايلي و نه موندل سوې"},searching:function(){return"لټول کيږي..."},removeAllItems:function(){return"ټول توکي لرې کړئ"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/pt-BR.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/pt-BR",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Apague "+n+" caracter";return 1!=n&&(r+="es"),r},inputTooShort:function(e){return"Digite "+(e.minimum-e.input.length)+" ou mais caracteres"},loadingMore:function(){return"Carregando mais resultados…"},maximumSelected:function(e){var n="Você só pode selecionar "+e.maximum+" ite";return 1==e.maximum?n+="m":n+="ns",n},noResults:function(){return"Nenhum resultado encontrado"},searching:function(){return"Buscando…"},removeAllItems:function(){return"Remover todos os itens"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/pt.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/pt",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var r=e.input.length-e.maximum,n="Por favor apague "+r+" ";return n+=1!=r?"caracteres":"caractere"},inputTooShort:function(e){return"Introduza "+(e.minimum-e.input.length)+" ou mais caracteres"},loadingMore:function(){return"A carregar mais resultados…"},maximumSelected:function(e){var r="Apenas pode seleccionar "+e.maximum+" ";return r+=1!=e.maximum?"itens":"item"},noResults:function(){return"Sem resultados"},searching:function(){return"A procurar…"},removeAllItems:function(){return"Remover todos os itens"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/ro.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/ro",[],function(){return{errorLoading:function(){return"Rezultatele nu au putut fi incărcate."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vă rugăm să ștergeți"+t+" caracter";return 1!==t&&(n+="e"),n},inputTooShort:function(e){return"Vă rugăm să introduceți "+(e.minimum-e.input.length)+" sau mai multe caractere"},loadingMore:function(){return"Se încarcă mai multe rezultate…"},maximumSelected:function(e){var t="Aveți voie să selectați cel mult "+e.maximum;return t+=" element",1!==e.maximum&&(t+="e"),t},noResults:function(){return"Nu au fost găsite rezultate"},searching:function(){return"Căutare…"},removeAllItems:function(){return"Eliminați toate elementele"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/ru.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ru",[],function(){function n(n,e,r,u){return n%10<5&&n%10>0&&n%100<5||n%100>20?n%10>1?r:e:u}return{errorLoading:function(){return"Невозможно загрузить результаты"},inputTooLong:function(e){var r=e.input.length-e.maximum,u="Пожалуйста, введите на "+r+" символ";return u+=n(r,"","a","ов"),u+=" меньше"},inputTooShort:function(e){var r=e.minimum-e.input.length,u="Пожалуйста, введите ещё хотя бы "+r+" символ";return u+=n(r,"","a","ов")},loadingMore:function(){return"Загрузка данных…"},maximumSelected:function(e){var r="Вы можете выбрать не более "+e.maximum+" элемент";return r+=n(e.maximum,"","a","ов")},noResults:function(){return"Совпадений не найдено"},searching:function(){return"Поиск…"},removeAllItems:function(){return"Удалить все элементы"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/sk.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/sk",[],function(){var e={2:function(e){return e?"dva":"dve"},3:function(){return"tri"},4:function(){return"štyri"}};return{errorLoading:function(){return"Výsledky sa nepodarilo načítať."},inputTooLong:function(n){var t=n.input.length-n.maximum;return 1==t?"Prosím, zadajte o jeden znak menej":t>=2&&t<=4?"Prosím, zadajte o "+e[t](!0)+" znaky menej":"Prosím, zadajte o "+t+" znakov menej"},inputTooShort:function(n){var t=n.minimum-n.input.length;return 1==t?"Prosím, zadajte ešte jeden znak":t<=4?"Prosím, zadajte ešte ďalšie "+e[t](!0)+" znaky":"Prosím, zadajte ešte ďalších "+t+" znakov"},loadingMore:function(){return"Načítanie ďalších výsledkov…"},maximumSelected:function(n){return 1==n.maximum?"Môžete zvoliť len jednu položku":n.maximum>=2&&n.maximum<=4?"Môžete zvoliť najviac "+e[n.maximum](!1)+" položky":"Môžete zvoliť najviac "+n.maximum+" položiek"},noResults:function(){return"Nenašli sa žiadne položky"},searching:function(){return"Vyhľadávanie…"},removeAllItems:function(){return"Odstráňte všetky položky"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/sl.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/sl",[],function(){return{errorLoading:function(){return"Zadetkov iskanja ni bilo mogoče naložiti."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Prosim zbrišite "+n+" znak";return 2==n?t+="a":1!=n&&(t+="e"),t},inputTooShort:function(e){var n=e.minimum-e.input.length,t="Prosim vpišite še "+n+" znak";return 2==n?t+="a":1!=n&&(t+="e"),t},loadingMore:function(){return"Nalagam več zadetkov…"},maximumSelected:function(e){var n="Označite lahko največ "+e.maximum+" predmet";return 2==e.maximum?n+="a":1!=e.maximum&&(n+="e"),n},noResults:function(){return"Ni zadetkov."},searching:function(){return"Iščem…"},removeAllItems:function(){return"Odstranite vse elemente"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/sq.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/sq",[],function(){return{errorLoading:function(){return"Rezultatet nuk mund të ngarkoheshin."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Të lutem fshi "+n+" karakter";return 1!=n&&(t+="e"),t},inputTooShort:function(e){return"Të lutem shkruaj "+(e.minimum-e.input.length)+" ose më shumë karaktere"},loadingMore:function(){return"Duke ngarkuar më shumë rezultate…"},maximumSelected:function(e){var n="Mund të zgjedhësh vetëm "+e.maximum+" element";return 1!=e.maximum&&(n+="e"),n},noResults:function(){return"Nuk u gjet asnjë rezultat"},searching:function(){return"Duke kërkuar…"},removeAllItems:function(){return"Hiq të gjitha sendet"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/sr-Cyrl.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/sr-Cyrl",[],function(){function n(n,e,r,u){return n%10==1&&n%100!=11?e:n%10>=2&&n%10<=4&&(n%100<12||n%100>14)?r:u}return{errorLoading:function(){return"Преузимање није успело."},inputTooLong:function(e){var r=e.input.length-e.maximum,u="Обришите "+r+" симбол";return u+=n(r,"","а","а")},inputTooShort:function(e){var r=e.minimum-e.input.length,u="Укуцајте бар још "+r+" симбол";return u+=n(r,"","а","а")},loadingMore:function(){return"Преузимање још резултата…"},maximumSelected:function(e){var r="Можете изабрати само "+e.maximum+" ставк";return r+=n(e.maximum,"у","е","и")},noResults:function(){return"Ништа није пронађено"},searching:function(){return"Претрага…"},removeAllItems:function(){return"Уклоните све ставке"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/sr.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/sr",[],function(){function n(n,e,r,t){return n%10==1&&n%100!=11?e:n%10>=2&&n%10<=4&&(n%100<12||n%100>14)?r:t}return{errorLoading:function(){return"Preuzimanje nije uspelo."},inputTooLong:function(e){var r=e.input.length-e.maximum,t="Obrišite "+r+" simbol";return t+=n(r,"","a","a")},inputTooShort:function(e){var r=e.minimum-e.input.length,t="Ukucajte bar još "+r+" simbol";return t+=n(r,"","a","a")},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(e){var r="Možete izabrati samo "+e.maximum+" stavk";return r+=n(e.maximum,"u","e","i")},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Уклоните све ставке"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/sv.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/sv",[],function(){return{errorLoading:function(){return"Resultat kunde inte laddas."},inputTooLong:function(n){return"Vänligen sudda ut "+(n.input.length-n.maximum)+" tecken"},inputTooShort:function(n){return"Vänligen skriv in "+(n.minimum-n.input.length)+" eller fler tecken"},loadingMore:function(){return"Laddar fler resultat…"},maximumSelected:function(n){return"Du kan max välja "+n.maximum+" element"},noResults:function(){return"Inga träffar"},searching:function(){return"Söker…"},removeAllItems:function(){return"Ta bort alla objekt"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/th.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/th",[],function(){return{errorLoading:function(){return"ไม่สามารถค้นข้อมูลได้"},inputTooLong:function(n){return"โปรดลบออก "+(n.input.length-n.maximum)+" ตัวอักษร"},inputTooShort:function(n){return"โปรดพิมพ์เพิ่มอีก "+(n.minimum-n.input.length)+" ตัวอักษร"},loadingMore:function(){return"กำลังค้นข้อมูลเพิ่ม…"},maximumSelected:function(n){return"คุณสามารถเลือกได้ไม่เกิน "+n.maximum+" รายการ"},noResults:function(){return"ไม่พบข้อมูล"},searching:function(){return"กำลังค้นข้อมูล…"},removeAllItems:function(){return"ลบรายการทั้งหมด"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/tk.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/tk",[],function(){return{errorLoading:function(){return"Netije ýüklenmedi."},inputTooLong:function(e){return e.input.length-e.maximum+" harp bozuň."},inputTooShort:function(e){return"Ýene-de iň az "+(e.minimum-e.input.length)+" harp ýazyň."},loadingMore:function(){return"Köpräk netije görkezilýär…"},maximumSelected:function(e){return"Diňe "+e.maximum+" sanysyny saýlaň."},noResults:function(){return"Netije tapylmady."},searching:function(){return"Gözlenýär…"},removeAllItems:function(){return"Remove all items"}}}),e.define,e.require}();

+ 1 - 1
dist/js/i18n/tr.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/tr",[],function(){return{errorLoading:function(){return"Sonuç yüklenemedi"},inputTooLong:function(n){return n.input.length-n.maximum+" karakter daha girmelisiniz"},inputTooShort:function(n){return"En az "+(n.minimum-n.input.length)+" karakter daha girmelisiniz"},loadingMore:function(){return"Daha fazla…"},maximumSelected:function(n){return"Sadece "+n.maximum+" seçim yapabilirsiniz"},noResults:function(){return"Sonuç bulunamadı"},searching:function(){return"Aranıyor…"},removeAllItems:function(){return"Tüm öğeleri kaldır"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/uk.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/uk",[],function(){function n(n,e,u,r){return n%100>10&&n%100<15?r:n%10==1?e:n%10>1&&n%10<5?u:r}return{errorLoading:function(){return"Неможливо завантажити результати"},inputTooLong:function(e){return"Будь ласка, видаліть "+(e.input.length-e.maximum)+" "+n(e.maximum,"літеру","літери","літер")},inputTooShort:function(n){return"Будь ласка, введіть "+(n.minimum-n.input.length)+" або більше літер"},loadingMore:function(){return"Завантаження інших результатів…"},maximumSelected:function(e){return"Ви можете вибрати лише "+e.maximum+" "+n(e.maximum,"пункт","пункти","пунктів")},noResults:function(){return"Нічого не знайдено"},searching:function(){return"Пошук…"},removeAllItems:function(){return"Видалити всі елементи"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/vi.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/vi",[],function(){return{inputTooLong:function(n){return"Vui lòng xóa bớt "+(n.input.length-n.maximum)+" ký tự"},inputTooShort:function(n){return"Vui lòng nhập thêm từ "+(n.minimum-n.input.length)+" ký tự trở lên"},loadingMore:function(){return"Đang lấy thêm kết quả…"},maximumSelected:function(n){return"Chỉ có thể chọn được "+n.maximum+" lựa chọn"},noResults:function(){return"Không tìm thấy kết quả"},searching:function(){return"Đang tìm…"},removeAllItems:function(){return"Xóa tất cả các mục"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/zh-CN.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/zh-CN",[],function(){return{errorLoading:function(){return"无法载入结果。"},inputTooLong:function(n){return"请删除"+(n.input.length-n.maximum)+"个字符"},inputTooShort:function(n){return"请再输入至少"+(n.minimum-n.input.length)+"个字符"},loadingMore:function(){return"载入更多结果…"},maximumSelected:function(n){return"最多只能选择"+n.maximum+"个项目"},noResults:function(){return"未找到结果"},searching:function(){return"搜索中…"},removeAllItems:function(){return"删除所有项目"}}}),n.define,n.require}();

+ 1 - 1
dist/js/i18n/zh-TW.js

@@ -1,3 +1,3 @@
-/*! Select2 4.0.8 | https://github.com/select2/select2/blob/master/LICENSE.md */
+/*! Select2 4.0.9 | https://github.com/select2/select2/blob/master/LICENSE.md */
 
 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/zh-TW",[],function(){return{inputTooLong:function(n){return"請刪掉"+(n.input.length-n.maximum)+"個字元"},inputTooShort:function(n){return"請再輸入"+(n.minimum-n.input.length)+"個字元"},loadingMore:function(){return"載入中…"},maximumSelected:function(n){return"你只能選擇最多"+n.maximum+"項"},noResults:function(){return"沒有找到相符的項目"},searching:function(){return"搜尋中…"},removeAllItems:function(){return"刪除所有項目"}}}),n.define,n.require}();

+ 229 - 99
dist/js/select2.full.js

@@ -1,5 +1,5 @@
 /*!
- * Select2 4.0.8
+ * Select2 4.0.9
  * https://select2.github.io
  *
  * Released under the MIT license
@@ -832,6 +832,8 @@ S2.define('select2/utils',[
     if (Utils.__cache[id] != null) {
       delete Utils.__cache[id];
     }
+
+    element.removeAttribute('data-select2-id');
   };
 
   return Utils;
@@ -853,7 +855,7 @@ S2.define('select2/results',[
 
   Results.prototype.render = function () {
     var $results = $(
-      '<ul class="select2-results__options" role="tree"></ul>'
+      '<ul class="select2-results__options" role="listbox"></ul>'
     );
 
     if (this.options.get('multiple')) {
@@ -876,7 +878,7 @@ S2.define('select2/results',[
     this.hideLoading();
 
     var $message = $(
-      '<li role="treeitem" aria-live="assertive"' +
+      '<li role="alert" aria-live="assertive"' +
       ' class="select2-results__option"></li>'
     );
 
@@ -1010,7 +1012,7 @@ S2.define('select2/results',[
     option.className = 'select2-results__option';
 
     var attrs = {
-      'role': 'treeitem',
+      'role': 'option',
       'aria-selected': 'false'
     };
 
@@ -1430,6 +1432,7 @@ S2.define('select2/selection/base',[
 
     $selection.attr('title', this.$element.attr('title'));
     $selection.attr('tabindex', this._tabindex);
+    $selection.attr('aria-disabled', 'false');
 
     this.$selection = $selection;
 
@@ -1439,7 +1442,6 @@ S2.define('select2/selection/base',[
   BaseSelection.prototype.bind = function (container, $container) {
     var self = this;
 
-    var id = container.id + '-container';
     var resultsId = container.id + '-results';
 
     this.container = container;
@@ -1489,10 +1491,12 @@ S2.define('select2/selection/base',[
 
     container.on('enable', function () {
       self.$selection.attr('tabindex', self._tabindex);
+      self.$selection.attr('aria-disabled', 'false');
     });
 
     container.on('disable', function () {
       self.$selection.attr('tabindex', '-1');
+      self.$selection.attr('aria-disabled', 'true');
     });
   };
 
@@ -1515,7 +1519,6 @@ S2.define('select2/selection/base',[
   };
 
   BaseSelection.prototype._attachCloseHandler = function (container) {
-    var self = this;
 
     $(document.body).on('mousedown.select2.' + container.id, function (e) {
       var $target = $(e.target);
@@ -1525,8 +1528,6 @@ S2.define('select2/selection/base',[
       var $all = $('.select2.select2-container--open');
 
       $all.each(function () {
-        var $this = $(this);
-
         if (this == $select[0]) {
           return;
         }
@@ -1653,7 +1654,14 @@ S2.define('select2/selection/single',[
     var formatted = this.display(selection, $rendered);
 
     $rendered.empty().append(formatted);
-    $rendered.attr('title', selection.title || selection.text);
+
+    var title = selection.title || selection.text;
+
+    if (title) {
+      $rendered.attr('title', title);
+    } else {
+      $rendered.removeAttr('title');
+    }
   };
 
   return SingleSelection;
@@ -1756,7 +1764,12 @@ S2.define('select2/selection/multiple',[
       var formatted = this.display(selection, $selection);
 
       $selection.append(formatted);
-      $selection.attr('title', selection.title || selection.text);
+
+      var title = selection.title || selection.text;
+
+      if (title) {
+        $selection.attr('title', title);
+      }
 
       Utils.StoreData($selection[0], 'data', selection);
 
@@ -1949,7 +1962,7 @@ S2.define('select2/selection/search',[
       '<li class="select2-search select2-search--inline">' +
         '<input class="select2-search__field" type="search" tabindex="-1"' +
         ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
-        ' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
+        ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
       '</li>'
     );
 
@@ -1966,14 +1979,18 @@ S2.define('select2/selection/search',[
   Search.prototype.bind = function (decorated, container, $container) {
     var self = this;
 
+    var resultsId = container.id + '-results';
+
     decorated.call(this, container, $container);
 
     container.on('open', function () {
+      self.$search.attr('aria-controls', resultsId);
       self.$search.trigger('focus');
     });
 
     container.on('close', function () {
       self.$search.val('');
+      self.$search.removeAttr('aria-controls');
       self.$search.removeAttr('aria-activedescendant');
       self.$search.trigger('focus');
     });
@@ -1993,7 +2010,11 @@ S2.define('select2/selection/search',[
     });
 
     container.on('results:focus', function (params) {
-      self.$search.attr('aria-activedescendant', params.id);
+      if (params.data._resultId) {
+        self.$search.attr('aria-activedescendant', params.data._resultId);
+      } else {
+        self.$search.removeAttr('aria-activedescendant');
+      }
     });
 
     this.$selection.on('focusin', '.select2-search--inline', function (evt) {
@@ -2027,6 +2048,12 @@ S2.define('select2/selection/search',[
       }
     });
 
+    this.$selection.on('click', '.select2-search--inline', function (evt) {
+      if (self.$search.val()) {
+        evt.stopPropagation();
+      }
+    });
+
     // Try to detect the IE version should the `documentMode` property that
     // is stored on the document. This is only implemented in IE and is
     // slightly cleaner than doing a user agent check.
@@ -2145,7 +2172,7 @@ S2.define('select2/selection/search',[
     var width = '';
 
     if (this.$search.attr('placeholder') !== '') {
-      width = this.$selection.find('.select2-selection__rendered').innerWidth();
+      width = this.$selection.find('.select2-selection__rendered').width();
     } else {
       var minimumWidth = this.$search.val().length + 1;
 
@@ -3428,15 +3455,19 @@ S2.define('select2/data/array',[
   'jquery'
 ], function (SelectAdapter, Utils, $) {
   function ArrayAdapter ($element, options) {
-    var data = options.get('data') || [];
+    this._dataToConvert = options.get('data') || [];
 
     ArrayAdapter.__super__.constructor.call(this, $element, options);
-
-    this.addOptions(this.convertToOptions(data));
   }
 
   Utils.Extend(ArrayAdapter, SelectAdapter);
 
+  ArrayAdapter.prototype.bind = function (container, $container) {
+    ArrayAdapter.__super__.bind.call(this, container, $container);
+
+    this.addOptions(this.convertToOptions(this._dataToConvert));
+  };
+
   ArrayAdapter.prototype.select = function (data) {
     var $option = this.$element.find('option').filter(function (i, elm) {
       return elm.value == data.id.toString();
@@ -3726,8 +3757,6 @@ S2.define('select2/data/tags',[
   };
 
   Tags.prototype._removeOldTags = function (_) {
-    var tag = this._lastTag;
-
     var $options = this.$element.find('option[data-select2-tag]');
 
     $options.each(function () {
@@ -3931,10 +3960,30 @@ S2.define('select2/data/maximumSelectionLength',[
     decorated.call(this, $e, options);
   }
 
+  MaximumSelectionLength.prototype.bind =
+    function (decorated, container, $container) {
+      var self = this;
+
+      decorated.call(this, container, $container);
+
+      container.on('select', function () {
+        self._checkIfMaximumSelected();
+      });
+  };
+
   MaximumSelectionLength.prototype.query =
     function (decorated, params, callback) {
       var self = this;
 
+      this._checkIfMaximumSelected(function () {
+        decorated.call(self, params, callback);
+      });
+  };
+
+  MaximumSelectionLength.prototype._checkIfMaximumSelected =
+    function (_, successCallback) {
+      var self = this;
+
       this.current(function (currentData) {
         var count = currentData != null ? currentData.length : 0;
         if (self.maximumSelectionLength > 0 &&
@@ -3947,7 +3996,10 @@ S2.define('select2/data/maximumSelectionLength',[
           });
           return;
         }
-        decorated.call(self, params, callback);
+
+        if (successCallback) {
+          successCallback();
+        }
       });
   };
 
@@ -4010,7 +4062,7 @@ S2.define('select2/dropdown/search',[
       '<span class="select2-search select2-search--dropdown">' +
         '<input class="select2-search__field" type="search" tabindex="-1"' +
         ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
-        ' spellcheck="false" role="textbox" />' +
+        ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
       '</span>'
     );
 
@@ -4025,6 +4077,8 @@ S2.define('select2/dropdown/search',[
   Search.prototype.bind = function (decorated, container, $container) {
     var self = this;
 
+    var resultsId = container.id + '-results';
+
     decorated.call(this, container, $container);
 
     this.$search.on('keydown', function (evt) {
@@ -4047,6 +4101,7 @@ S2.define('select2/dropdown/search',[
 
     container.on('open', function () {
       self.$search.attr('tabindex', 0);
+      self.$search.attr('aria-controls', resultsId);
 
       self.$search.trigger('focus');
 
@@ -4057,6 +4112,8 @@ S2.define('select2/dropdown/search',[
 
     container.on('close', function () {
       self.$search.attr('tabindex', -1);
+      self.$search.removeAttr('aria-controls');
+      self.$search.removeAttr('aria-activedescendant');
 
       self.$search.val('');
       self.$search.trigger('blur');
@@ -4079,6 +4136,14 @@ S2.define('select2/dropdown/search',[
         }
       }
     });
+
+    container.on('results:focus', function (params) {
+      if (params.data._resultId) {
+        self.$search.attr('aria-activedescendant', params.data._resultId);
+      } else {
+        self.$search.removeAttr('aria-activedescendant');
+      }
+    });
   };
 
   Search.prototype.handleSearch = function (evt) {
@@ -4223,7 +4288,7 @@ S2.define('select2/dropdown/infiniteScroll',[
     var $option = $(
       '<li ' +
       'class="select2-results__option select2-results__option--load-more"' +
-      'role="treeitem" aria-disabled="true"></li>'
+      'role="option" aria-disabled="true"></li>'
     );
 
     var message = this.options.get('translations').get('loadingMore');
@@ -4249,27 +4314,11 @@ S2.define('select2/dropdown/attachBody',[
   AttachBody.prototype.bind = function (decorated, container, $container) {
     var self = this;
 
-    var setupResultsEvents = false;
-
     decorated.call(this, container, $container);
 
     container.on('open', function () {
       self._showDropdown();
       self._attachPositioningHandler(container);
-
-      if (!setupResultsEvents) {
-        setupResultsEvents = true;
-
-        container.on('results:all', function () {
-          self._positionDropdown();
-          self._resizeDropdown();
-        });
-
-        container.on('results:append', function () {
-          self._positionDropdown();
-          self._resizeDropdown();
-        });
-      }
     });
 
     container.on('close', function () {
@@ -4277,6 +4326,31 @@ S2.define('select2/dropdown/attachBody',[
       self._detachPositioningHandler(container);
     });
 
+    container.on('results:all', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
+    container.on('results:append', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
+    container.on('results:message', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
+    container.on('select', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
+    container.on('unselect', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
     this.$dropdownContainer.on('mousedown', function (evt) {
       evt.stopPropagation();
     });
@@ -4868,66 +4942,29 @@ S2.define('select2/defaults',[
       );
     }
 
-    if (typeof options.language === 'string') {
-      // Check if the language is specified with a region
-      if (options.language.indexOf('-') > 0) {
-        // Extract the region information if it is included
-        var languageParts = options.language.split('-');
-        var baseLanguage = languageParts[0];
-
-        options.language = [options.language, baseLanguage];
-      } else {
-        options.language = [options.language];
-      }
-    }
-
-    if ($.isArray(options.language)) {
-      var languages = new Translation();
-      options.language.push('en');
+    // If the defaults were not previously applied from an element, it is
+    // possible for the language option to have not been resolved
+    options.language = this._resolveLanguage(options.language);
 
-      var languageNames = options.language;
+    // Always fall back to English since it will always be complete
+    options.language.push('en');
 
-      for (var l = 0; l < languageNames.length; l++) {
-        var name = languageNames[l];
-        var language = {};
-
-        try {
-          // Try to load it with the original name
-          language = Translation.loadPath(name);
-        } catch (e) {
-          try {
-            // If we couldn't load it, check if it wasn't the full path
-            name = this.defaults.amdLanguageBase + name;
-            language = Translation.loadPath(name);
-          } catch (ex) {
-            // The translation could not be loaded at all. Sometimes this is
-            // because of a configuration problem, other times this can be
-            // because of how Select2 helps load all possible translation files.
-            if (options.debug && window.console && console.warn) {
-              console.warn(
-                'Select2: The language file for "' + name + '" could not be ' +
-                'automatically loaded. A fallback will be used instead.'
-              );
-            }
+    var uniqueLanguages = [];
 
-            continue;
-          }
-        }
+    for (var l = 0; l < options.language.length; l++) {
+      var language = options.language[l];
 
-        languages.extend(language);
+      if (uniqueLanguages.indexOf(language) === -1) {
+        uniqueLanguages.push(language);
       }
+    }
 
-      options.translations = languages;
-    } else {
-      var baseTranslation = Translation.loadPath(
-        this.defaults.amdLanguageBase + 'en'
-      );
-      var customTranslation = new Translation(options.language);
-
-      customTranslation.extend(baseTranslation);
+    options.language = uniqueLanguages;
 
-      options.translations = customTranslation;
-    }
+    options.translations = this._processTranslations(
+      options.language,
+      options.debug
+    );
 
     return options;
   };
@@ -4994,7 +5031,7 @@ S2.define('select2/defaults',[
       debug: false,
       dropdownAutoWidth: false,
       escapeMarkup: Utils.escapeMarkup,
-      language: EnglishTranslation,
+      language: {},
       matcher: matcher,
       minimumInputLength: 0,
       maximumInputLength: 0,
@@ -5016,6 +5053,103 @@ S2.define('select2/defaults',[
     };
   };
 
+  Defaults.prototype.applyFromElement = function (options, $element) {
+    var optionLanguage = options.language;
+    var defaultLanguage = this.defaults.language;
+    var elementLanguage = $element.prop('lang');
+    var parentLanguage = $element.closest('[lang]').prop('lang');
+
+    var languages = Array.prototype.concat.call(
+      this._resolveLanguage(elementLanguage),
+      this._resolveLanguage(optionLanguage),
+      this._resolveLanguage(defaultLanguage),
+      this._resolveLanguage(parentLanguage)
+    );
+
+    options.language = languages;
+
+    return options;
+  };
+
+  Defaults.prototype._resolveLanguage = function (language) {
+    if (!language) {
+      return [];
+    }
+
+    if ($.isEmptyObject(language)) {
+      return [];
+    }
+
+    if ($.isPlainObject(language)) {
+      return [language];
+    }
+
+    var languages;
+
+    if (!$.isArray(language)) {
+      languages = [language];
+    } else {
+      languages = language;
+    }
+
+    var resolvedLanguages = [];
+
+    for (var l = 0; l < languages.length; l++) {
+      resolvedLanguages.push(languages[l]);
+
+      if (typeof languages[l] === 'string' && languages[l].indexOf('-') > 0) {
+        // Extract the region information if it is included
+        var languageParts = languages[l].split('-');
+        var baseLanguage = languageParts[0];
+
+        resolvedLanguages.push(baseLanguage);
+      }
+    }
+
+    return resolvedLanguages;
+  };
+
+  Defaults.prototype._processTranslations = function (languages, debug) {
+    var translations = new Translation();
+
+    for (var l = 0; l < languages.length; l++) {
+      var languageData = new Translation();
+
+      var language = languages[l];
+
+      if (typeof language === 'string') {
+        try {
+          // Try to load it with the original name
+          languageData = Translation.loadPath(language);
+        } catch (e) {
+          try {
+            // If we couldn't load it, check if it wasn't the full path
+            language = this.defaults.amdLanguageBase + language;
+            languageData = Translation.loadPath(language);
+          } catch (ex) {
+            // The translation could not be loaded at all. Sometimes this is
+            // because of a configuration problem, other times this can be
+            // because of how Select2 helps load all possible translation files
+            if (debug && window.console && console.warn) {
+              console.warn(
+                'Select2: The language file for "' + language + '" could ' +
+                'not be automatically loaded. A fallback will be used instead.'
+              );
+            }
+          }
+        }
+      } else if ($.isPlainObject(language)) {
+        languageData = new Translation(language);
+      } else {
+        languageData = language;
+      }
+
+      translations.extend(languageData);
+    }
+
+    return translations;
+  };
+
   Defaults.prototype.set = function (key, value) {
     var camelKey = $.camelCase(key);
 
@@ -5045,6 +5179,10 @@ S2.define('select2/options',[
       this.fromElement($element);
     }
 
+    if ($element != null) {
+      this.options = Defaults.applyFromElement(this.options, $element);
+    }
+
     this.options = Defaults.apply(this.options);
 
     if ($element && $element.is('input')) {
@@ -5068,14 +5206,6 @@ S2.define('select2/options',[
       this.options.disabled = $e.prop('disabled');
     }
 
-    if (this.options.language == null) {
-      if ($e.prop('lang')) {
-        this.options.language = $e.prop('lang').toLowerCase();
-      } else if ($e.closest('[lang]').prop('lang')) {
-        this.options.language = $e.closest('[lang]').prop('lang');
-      }
-    }
-
     if (this.options.dir == null) {
       if ($e.prop('dir')) {
         this.options.dir = $e.prop('dir');

File diff suppressed because it is too large
+ 0 - 1
dist/js/select2.full.min.js


+ 229 - 99
dist/js/select2.js

@@ -1,5 +1,5 @@
 /*!
- * Select2 4.0.8
+ * Select2 4.0.9
  * https://select2.github.io
  *
  * Released under the MIT license
@@ -832,6 +832,8 @@ S2.define('select2/utils',[
     if (Utils.__cache[id] != null) {
       delete Utils.__cache[id];
     }
+
+    element.removeAttribute('data-select2-id');
   };
 
   return Utils;
@@ -853,7 +855,7 @@ S2.define('select2/results',[
 
   Results.prototype.render = function () {
     var $results = $(
-      '<ul class="select2-results__options" role="tree"></ul>'
+      '<ul class="select2-results__options" role="listbox"></ul>'
     );
 
     if (this.options.get('multiple')) {
@@ -876,7 +878,7 @@ S2.define('select2/results',[
     this.hideLoading();
 
     var $message = $(
-      '<li role="treeitem" aria-live="assertive"' +
+      '<li role="alert" aria-live="assertive"' +
       ' class="select2-results__option"></li>'
     );
 
@@ -1010,7 +1012,7 @@ S2.define('select2/results',[
     option.className = 'select2-results__option';
 
     var attrs = {
-      'role': 'treeitem',
+      'role': 'option',
       'aria-selected': 'false'
     };
 
@@ -1430,6 +1432,7 @@ S2.define('select2/selection/base',[
 
     $selection.attr('title', this.$element.attr('title'));
     $selection.attr('tabindex', this._tabindex);
+    $selection.attr('aria-disabled', 'false');
 
     this.$selection = $selection;
 
@@ -1439,7 +1442,6 @@ S2.define('select2/selection/base',[
   BaseSelection.prototype.bind = function (container, $container) {
     var self = this;
 
-    var id = container.id + '-container';
     var resultsId = container.id + '-results';
 
     this.container = container;
@@ -1489,10 +1491,12 @@ S2.define('select2/selection/base',[
 
     container.on('enable', function () {
       self.$selection.attr('tabindex', self._tabindex);
+      self.$selection.attr('aria-disabled', 'false');
     });
 
     container.on('disable', function () {
       self.$selection.attr('tabindex', '-1');
+      self.$selection.attr('aria-disabled', 'true');
     });
   };
 
@@ -1515,7 +1519,6 @@ S2.define('select2/selection/base',[
   };
 
   BaseSelection.prototype._attachCloseHandler = function (container) {
-    var self = this;
 
     $(document.body).on('mousedown.select2.' + container.id, function (e) {
       var $target = $(e.target);
@@ -1525,8 +1528,6 @@ S2.define('select2/selection/base',[
       var $all = $('.select2.select2-container--open');
 
       $all.each(function () {
-        var $this = $(this);
-
         if (this == $select[0]) {
           return;
         }
@@ -1653,7 +1654,14 @@ S2.define('select2/selection/single',[
     var formatted = this.display(selection, $rendered);
 
     $rendered.empty().append(formatted);
-    $rendered.attr('title', selection.title || selection.text);
+
+    var title = selection.title || selection.text;
+
+    if (title) {
+      $rendered.attr('title', title);
+    } else {
+      $rendered.removeAttr('title');
+    }
   };
 
   return SingleSelection;
@@ -1756,7 +1764,12 @@ S2.define('select2/selection/multiple',[
       var formatted = this.display(selection, $selection);
 
       $selection.append(formatted);
-      $selection.attr('title', selection.title || selection.text);
+
+      var title = selection.title || selection.text;
+
+      if (title) {
+        $selection.attr('title', title);
+      }
 
       Utils.StoreData($selection[0], 'data', selection);
 
@@ -1949,7 +1962,7 @@ S2.define('select2/selection/search',[
       '<li class="select2-search select2-search--inline">' +
         '<input class="select2-search__field" type="search" tabindex="-1"' +
         ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
-        ' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
+        ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
       '</li>'
     );
 
@@ -1966,14 +1979,18 @@ S2.define('select2/selection/search',[
   Search.prototype.bind = function (decorated, container, $container) {
     var self = this;
 
+    var resultsId = container.id + '-results';
+
     decorated.call(this, container, $container);
 
     container.on('open', function () {
+      self.$search.attr('aria-controls', resultsId);
       self.$search.trigger('focus');
     });
 
     container.on('close', function () {
       self.$search.val('');
+      self.$search.removeAttr('aria-controls');
       self.$search.removeAttr('aria-activedescendant');
       self.$search.trigger('focus');
     });
@@ -1993,7 +2010,11 @@ S2.define('select2/selection/search',[
     });
 
     container.on('results:focus', function (params) {
-      self.$search.attr('aria-activedescendant', params.id);
+      if (params.data._resultId) {
+        self.$search.attr('aria-activedescendant', params.data._resultId);
+      } else {
+        self.$search.removeAttr('aria-activedescendant');
+      }
     });
 
     this.$selection.on('focusin', '.select2-search--inline', function (evt) {
@@ -2027,6 +2048,12 @@ S2.define('select2/selection/search',[
       }
     });
 
+    this.$selection.on('click', '.select2-search--inline', function (evt) {
+      if (self.$search.val()) {
+        evt.stopPropagation();
+      }
+    });
+
     // Try to detect the IE version should the `documentMode` property that
     // is stored on the document. This is only implemented in IE and is
     // slightly cleaner than doing a user agent check.
@@ -2145,7 +2172,7 @@ S2.define('select2/selection/search',[
     var width = '';
 
     if (this.$search.attr('placeholder') !== '') {
-      width = this.$selection.find('.select2-selection__rendered').innerWidth();
+      width = this.$selection.find('.select2-selection__rendered').width();
     } else {
       var minimumWidth = this.$search.val().length + 1;
 
@@ -3428,15 +3455,19 @@ S2.define('select2/data/array',[
   'jquery'
 ], function (SelectAdapter, Utils, $) {
   function ArrayAdapter ($element, options) {
-    var data = options.get('data') || [];
+    this._dataToConvert = options.get('data') || [];
 
     ArrayAdapter.__super__.constructor.call(this, $element, options);
-
-    this.addOptions(this.convertToOptions(data));
   }
 
   Utils.Extend(ArrayAdapter, SelectAdapter);
 
+  ArrayAdapter.prototype.bind = function (container, $container) {
+    ArrayAdapter.__super__.bind.call(this, container, $container);
+
+    this.addOptions(this.convertToOptions(this._dataToConvert));
+  };
+
   ArrayAdapter.prototype.select = function (data) {
     var $option = this.$element.find('option').filter(function (i, elm) {
       return elm.value == data.id.toString();
@@ -3726,8 +3757,6 @@ S2.define('select2/data/tags',[
   };
 
   Tags.prototype._removeOldTags = function (_) {
-    var tag = this._lastTag;
-
     var $options = this.$element.find('option[data-select2-tag]');
 
     $options.each(function () {
@@ -3931,10 +3960,30 @@ S2.define('select2/data/maximumSelectionLength',[
     decorated.call(this, $e, options);
   }
 
+  MaximumSelectionLength.prototype.bind =
+    function (decorated, container, $container) {
+      var self = this;
+
+      decorated.call(this, container, $container);
+
+      container.on('select', function () {
+        self._checkIfMaximumSelected();
+      });
+  };
+
   MaximumSelectionLength.prototype.query =
     function (decorated, params, callback) {
       var self = this;
 
+      this._checkIfMaximumSelected(function () {
+        decorated.call(self, params, callback);
+      });
+  };
+
+  MaximumSelectionLength.prototype._checkIfMaximumSelected =
+    function (_, successCallback) {
+      var self = this;
+
       this.current(function (currentData) {
         var count = currentData != null ? currentData.length : 0;
         if (self.maximumSelectionLength > 0 &&
@@ -3947,7 +3996,10 @@ S2.define('select2/data/maximumSelectionLength',[
           });
           return;
         }
-        decorated.call(self, params, callback);
+
+        if (successCallback) {
+          successCallback();
+        }
       });
   };
 
@@ -4010,7 +4062,7 @@ S2.define('select2/dropdown/search',[
       '<span class="select2-search select2-search--dropdown">' +
         '<input class="select2-search__field" type="search" tabindex="-1"' +
         ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
-        ' spellcheck="false" role="textbox" />' +
+        ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
       '</span>'
     );
 
@@ -4025,6 +4077,8 @@ S2.define('select2/dropdown/search',[
   Search.prototype.bind = function (decorated, container, $container) {
     var self = this;
 
+    var resultsId = container.id + '-results';
+
     decorated.call(this, container, $container);
 
     this.$search.on('keydown', function (evt) {
@@ -4047,6 +4101,7 @@ S2.define('select2/dropdown/search',[
 
     container.on('open', function () {
       self.$search.attr('tabindex', 0);
+      self.$search.attr('aria-controls', resultsId);
 
       self.$search.trigger('focus');
 
@@ -4057,6 +4112,8 @@ S2.define('select2/dropdown/search',[
 
     container.on('close', function () {
       self.$search.attr('tabindex', -1);
+      self.$search.removeAttr('aria-controls');
+      self.$search.removeAttr('aria-activedescendant');
 
       self.$search.val('');
       self.$search.trigger('blur');
@@ -4079,6 +4136,14 @@ S2.define('select2/dropdown/search',[
         }
       }
     });
+
+    container.on('results:focus', function (params) {
+      if (params.data._resultId) {
+        self.$search.attr('aria-activedescendant', params.data._resultId);
+      } else {
+        self.$search.removeAttr('aria-activedescendant');
+      }
+    });
   };
 
   Search.prototype.handleSearch = function (evt) {
@@ -4223,7 +4288,7 @@ S2.define('select2/dropdown/infiniteScroll',[
     var $option = $(
       '<li ' +
       'class="select2-results__option select2-results__option--load-more"' +
-      'role="treeitem" aria-disabled="true"></li>'
+      'role="option" aria-disabled="true"></li>'
     );
 
     var message = this.options.get('translations').get('loadingMore');
@@ -4249,27 +4314,11 @@ S2.define('select2/dropdown/attachBody',[
   AttachBody.prototype.bind = function (decorated, container, $container) {
     var self = this;
 
-    var setupResultsEvents = false;
-
     decorated.call(this, container, $container);
 
     container.on('open', function () {
       self._showDropdown();
       self._attachPositioningHandler(container);
-
-      if (!setupResultsEvents) {
-        setupResultsEvents = true;
-
-        container.on('results:all', function () {
-          self._positionDropdown();
-          self._resizeDropdown();
-        });
-
-        container.on('results:append', function () {
-          self._positionDropdown();
-          self._resizeDropdown();
-        });
-      }
     });
 
     container.on('close', function () {
@@ -4277,6 +4326,31 @@ S2.define('select2/dropdown/attachBody',[
       self._detachPositioningHandler(container);
     });
 
+    container.on('results:all', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
+    container.on('results:append', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
+    container.on('results:message', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
+    container.on('select', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
+    container.on('unselect', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
     this.$dropdownContainer.on('mousedown', function (evt) {
       evt.stopPropagation();
     });
@@ -4868,66 +4942,29 @@ S2.define('select2/defaults',[
       );
     }
 
-    if (typeof options.language === 'string') {
-      // Check if the language is specified with a region
-      if (options.language.indexOf('-') > 0) {
-        // Extract the region information if it is included
-        var languageParts = options.language.split('-');
-        var baseLanguage = languageParts[0];
-
-        options.language = [options.language, baseLanguage];
-      } else {
-        options.language = [options.language];
-      }
-    }
-
-    if ($.isArray(options.language)) {
-      var languages = new Translation();
-      options.language.push('en');
+    // If the defaults were not previously applied from an element, it is
+    // possible for the language option to have not been resolved
+    options.language = this._resolveLanguage(options.language);
 
-      var languageNames = options.language;
+    // Always fall back to English since it will always be complete
+    options.language.push('en');
 
-      for (var l = 0; l < languageNames.length; l++) {
-        var name = languageNames[l];
-        var language = {};
-
-        try {
-          // Try to load it with the original name
-          language = Translation.loadPath(name);
-        } catch (e) {
-          try {
-            // If we couldn't load it, check if it wasn't the full path
-            name = this.defaults.amdLanguageBase + name;
-            language = Translation.loadPath(name);
-          } catch (ex) {
-            // The translation could not be loaded at all. Sometimes this is
-            // because of a configuration problem, other times this can be
-            // because of how Select2 helps load all possible translation files.
-            if (options.debug && window.console && console.warn) {
-              console.warn(
-                'Select2: The language file for "' + name + '" could not be ' +
-                'automatically loaded. A fallback will be used instead.'
-              );
-            }
+    var uniqueLanguages = [];
 
-            continue;
-          }
-        }
+    for (var l = 0; l < options.language.length; l++) {
+      var language = options.language[l];
 
-        languages.extend(language);
+      if (uniqueLanguages.indexOf(language) === -1) {
+        uniqueLanguages.push(language);
       }
+    }
 
-      options.translations = languages;
-    } else {
-      var baseTranslation = Translation.loadPath(
-        this.defaults.amdLanguageBase + 'en'
-      );
-      var customTranslation = new Translation(options.language);
-
-      customTranslation.extend(baseTranslation);
+    options.language = uniqueLanguages;
 
-      options.translations = customTranslation;
-    }
+    options.translations = this._processTranslations(
+      options.language,
+      options.debug
+    );
 
     return options;
   };
@@ -4994,7 +5031,7 @@ S2.define('select2/defaults',[
       debug: false,
       dropdownAutoWidth: false,
       escapeMarkup: Utils.escapeMarkup,
-      language: EnglishTranslation,
+      language: {},
       matcher: matcher,
       minimumInputLength: 0,
       maximumInputLength: 0,
@@ -5016,6 +5053,103 @@ S2.define('select2/defaults',[
     };
   };
 
+  Defaults.prototype.applyFromElement = function (options, $element) {
+    var optionLanguage = options.language;
+    var defaultLanguage = this.defaults.language;
+    var elementLanguage = $element.prop('lang');
+    var parentLanguage = $element.closest('[lang]').prop('lang');
+
+    var languages = Array.prototype.concat.call(
+      this._resolveLanguage(elementLanguage),
+      this._resolveLanguage(optionLanguage),
+      this._resolveLanguage(defaultLanguage),
+      this._resolveLanguage(parentLanguage)
+    );
+
+    options.language = languages;
+
+    return options;
+  };
+
+  Defaults.prototype._resolveLanguage = function (language) {
+    if (!language) {
+      return [];
+    }
+
+    if ($.isEmptyObject(language)) {
+      return [];
+    }
+
+    if ($.isPlainObject(language)) {
+      return [language];
+    }
+
+    var languages;
+
+    if (!$.isArray(language)) {
+      languages = [language];
+    } else {
+      languages = language;
+    }
+
+    var resolvedLanguages = [];
+
+    for (var l = 0; l < languages.length; l++) {
+      resolvedLanguages.push(languages[l]);
+
+      if (typeof languages[l] === 'string' && languages[l].indexOf('-') > 0) {
+        // Extract the region information if it is included
+        var languageParts = languages[l].split('-');
+        var baseLanguage = languageParts[0];
+
+        resolvedLanguages.push(baseLanguage);
+      }
+    }
+
+    return resolvedLanguages;
+  };
+
+  Defaults.prototype._processTranslations = function (languages, debug) {
+    var translations = new Translation();
+
+    for (var l = 0; l < languages.length; l++) {
+      var languageData = new Translation();
+
+      var language = languages[l];
+
+      if (typeof language === 'string') {
+        try {
+          // Try to load it with the original name
+          languageData = Translation.loadPath(language);
+        } catch (e) {
+          try {
+            // If we couldn't load it, check if it wasn't the full path
+            language = this.defaults.amdLanguageBase + language;
+            languageData = Translation.loadPath(language);
+          } catch (ex) {
+            // The translation could not be loaded at all. Sometimes this is
+            // because of a configuration problem, other times this can be
+            // because of how Select2 helps load all possible translation files
+            if (debug && window.console && console.warn) {
+              console.warn(
+                'Select2: The language file for "' + language + '" could ' +
+                'not be automatically loaded. A fallback will be used instead.'
+              );
+            }
+          }
+        }
+      } else if ($.isPlainObject(language)) {
+        languageData = new Translation(language);
+      } else {
+        languageData = language;
+      }
+
+      translations.extend(languageData);
+    }
+
+    return translations;
+  };
+
   Defaults.prototype.set = function (key, value) {
     var camelKey = $.camelCase(key);
 
@@ -5045,6 +5179,10 @@ S2.define('select2/options',[
       this.fromElement($element);
     }
 
+    if ($element != null) {
+      this.options = Defaults.applyFromElement(this.options, $element);
+    }
+
     this.options = Defaults.apply(this.options);
 
     if ($element && $element.is('input')) {
@@ -5068,14 +5206,6 @@ S2.define('select2/options',[
       this.options.disabled = $e.prop('disabled');
     }
 
-    if (this.options.language == null) {
-      if ($e.prop('lang')) {
-        this.options.language = $e.prop('lang').toLowerCase();
-      } else if ($e.closest('[lang]').prop('lang')) {
-        this.options.language = $e.closest('[lang]').prop('lang');
-      }
-    }
-
     if (this.options.dir == null) {
       if ($e.prop('dir')) {
         this.options.dir = $e.prop('dir');

File diff suppressed because it is too large
+ 0 - 1
dist/js/select2.min.js


+ 2 - 2
package.json

@@ -39,7 +39,7 @@
     "src",
     "dist"
   ],
-  "version": "4.0.8",
+  "version": "4.0.9",
   "jspm": {
     "main": "js/select2",
     "directories": {
@@ -48,7 +48,7 @@
   },
   "devDependencies": {
     "almond": "~0.3.1",
-    "grunt": "^0.4.5",
+    "grunt": "^1.0.4",
     "grunt-cli": "^1.3.2",
     "grunt-contrib-concat": "^1.0.1",
     "grunt-contrib-connect": "^2.0.0",

+ 7 - 3
src/js/select2/data/array.js

@@ -4,15 +4,19 @@ define([
   'jquery'
 ], function (SelectAdapter, Utils, $) {
   function ArrayAdapter ($element, options) {
-    var data = options.get('data') || [];
+    this._dataToConvert = options.get('data') || [];
 
     ArrayAdapter.__super__.constructor.call(this, $element, options);
-
-    this.addOptions(this.convertToOptions(data));
   }
 
   Utils.Extend(ArrayAdapter, SelectAdapter);
 
+  ArrayAdapter.prototype.bind = function (container, $container) {
+    ArrayAdapter.__super__.bind.call(this, container, $container);
+
+    this.addOptions(this.convertToOptions(this._dataToConvert));
+  };
+
   ArrayAdapter.prototype.select = function (data) {
     var $option = this.$element.find('option').filter(function (i, elm) {
       return elm.value == data.id.toString();

+ 24 - 1
src/js/select2/data/maximumSelectionLength.js

@@ -7,10 +7,30 @@ define([
     decorated.call(this, $e, options);
   }
 
+  MaximumSelectionLength.prototype.bind =
+    function (decorated, container, $container) {
+      var self = this;
+
+      decorated.call(this, container, $container);
+
+      container.on('select', function () {
+        self._checkIfMaximumSelected();
+      });
+  };
+
   MaximumSelectionLength.prototype.query =
     function (decorated, params, callback) {
       var self = this;
 
+      this._checkIfMaximumSelected(function () {
+        decorated.call(self, params, callback);
+      });
+  };
+
+  MaximumSelectionLength.prototype._checkIfMaximumSelected =
+    function (_, successCallback) {
+      var self = this;
+
       this.current(function (currentData) {
         var count = currentData != null ? currentData.length : 0;
         if (self.maximumSelectionLength > 0 &&
@@ -23,7 +43,10 @@ define([
           });
           return;
         }
-        decorated.call(self, params, callback);
+
+        if (successCallback) {
+          successCallback();
+        }
       });
   };
 

+ 0 - 2
src/js/select2/data/tags.js

@@ -111,8 +111,6 @@ define([
   };
 
   Tags.prototype._removeOldTags = function (_) {
-    var tag = this._lastTag;
-
     var $options = this.$element.find('option[data-select2-tag]');
 
     $options.each(function () {

+ 114 - 54
src/js/select2/defaults.js

@@ -232,66 +232,29 @@ define([
       );
     }
 
-    if (typeof options.language === 'string') {
-      // Check if the language is specified with a region
-      if (options.language.indexOf('-') > 0) {
-        // Extract the region information if it is included
-        var languageParts = options.language.split('-');
-        var baseLanguage = languageParts[0];
-
-        options.language = [options.language, baseLanguage];
-      } else {
-        options.language = [options.language];
-      }
-    }
-
-    if ($.isArray(options.language)) {
-      var languages = new Translation();
-      options.language.push('en');
-
-      var languageNames = options.language;
+    // If the defaults were not previously applied from an element, it is
+    // possible for the language option to have not been resolved
+    options.language = this._resolveLanguage(options.language);
 
-      for (var l = 0; l < languageNames.length; l++) {
-        var name = languageNames[l];
-        var language = {};
+    // Always fall back to English since it will always be complete
+    options.language.push('en');
 
-        try {
-          // Try to load it with the original name
-          language = Translation.loadPath(name);
-        } catch (e) {
-          try {
-            // If we couldn't load it, check if it wasn't the full path
-            name = this.defaults.amdLanguageBase + name;
-            language = Translation.loadPath(name);
-          } catch (ex) {
-            // The translation could not be loaded at all. Sometimes this is
-            // because of a configuration problem, other times this can be
-            // because of how Select2 helps load all possible translation files.
-            if (options.debug && window.console && console.warn) {
-              console.warn(
-                'Select2: The language file for "' + name + '" could not be ' +
-                'automatically loaded. A fallback will be used instead.'
-              );
-            }
+    var uniqueLanguages = [];
 
-            continue;
-          }
-        }
+    for (var l = 0; l < options.language.length; l++) {
+      var language = options.language[l];
 
-        languages.extend(language);
+      if (uniqueLanguages.indexOf(language) === -1) {
+        uniqueLanguages.push(language);
       }
+    }
 
-      options.translations = languages;
-    } else {
-      var baseTranslation = Translation.loadPath(
-        this.defaults.amdLanguageBase + 'en'
-      );
-      var customTranslation = new Translation(options.language);
-
-      customTranslation.extend(baseTranslation);
+    options.language = uniqueLanguages;
 
-      options.translations = customTranslation;
-    }
+    options.translations = this._processTranslations(
+      options.language,
+      options.debug
+    );
 
     return options;
   };
@@ -358,7 +321,7 @@ define([
       debug: false,
       dropdownAutoWidth: false,
       escapeMarkup: Utils.escapeMarkup,
-      language: EnglishTranslation,
+      language: {},
       matcher: matcher,
       minimumInputLength: 0,
       maximumInputLength: 0,
@@ -380,6 +343,103 @@ define([
     };
   };
 
+  Defaults.prototype.applyFromElement = function (options, $element) {
+    var optionLanguage = options.language;
+    var defaultLanguage = this.defaults.language;
+    var elementLanguage = $element.prop('lang');
+    var parentLanguage = $element.closest('[lang]').prop('lang');
+
+    var languages = Array.prototype.concat.call(
+      this._resolveLanguage(elementLanguage),
+      this._resolveLanguage(optionLanguage),
+      this._resolveLanguage(defaultLanguage),
+      this._resolveLanguage(parentLanguage)
+    );
+
+    options.language = languages;
+
+    return options;
+  };
+
+  Defaults.prototype._resolveLanguage = function (language) {
+    if (!language) {
+      return [];
+    }
+
+    if ($.isEmptyObject(language)) {
+      return [];
+    }
+
+    if ($.isPlainObject(language)) {
+      return [language];
+    }
+
+    var languages;
+
+    if (!$.isArray(language)) {
+      languages = [language];
+    } else {
+      languages = language;
+    }
+
+    var resolvedLanguages = [];
+
+    for (var l = 0; l < languages.length; l++) {
+      resolvedLanguages.push(languages[l]);
+
+      if (typeof languages[l] === 'string' && languages[l].indexOf('-') > 0) {
+        // Extract the region information if it is included
+        var languageParts = languages[l].split('-');
+        var baseLanguage = languageParts[0];
+
+        resolvedLanguages.push(baseLanguage);
+      }
+    }
+
+    return resolvedLanguages;
+  };
+
+  Defaults.prototype._processTranslations = function (languages, debug) {
+    var translations = new Translation();
+
+    for (var l = 0; l < languages.length; l++) {
+      var languageData = new Translation();
+
+      var language = languages[l];
+
+      if (typeof language === 'string') {
+        try {
+          // Try to load it with the original name
+          languageData = Translation.loadPath(language);
+        } catch (e) {
+          try {
+            // If we couldn't load it, check if it wasn't the full path
+            language = this.defaults.amdLanguageBase + language;
+            languageData = Translation.loadPath(language);
+          } catch (ex) {
+            // The translation could not be loaded at all. Sometimes this is
+            // because of a configuration problem, other times this can be
+            // because of how Select2 helps load all possible translation files
+            if (debug && window.console && console.warn) {
+              console.warn(
+                'Select2: The language file for "' + language + '" could ' +
+                'not be automatically loaded. A fallback will be used instead.'
+              );
+            }
+          }
+        }
+      } else if ($.isPlainObject(language)) {
+        languageData = new Translation(language);
+      } else {
+        languageData = language;
+      }
+
+      translations.extend(languageData);
+    }
+
+    return translations;
+  };
+
   Defaults.prototype.set = function (key, value) {
     var camelKey = $.camelCase(key);
 

+ 25 - 16
src/js/select2/dropdown/attachBody.js

@@ -11,27 +11,11 @@ define([
   AttachBody.prototype.bind = function (decorated, container, $container) {
     var self = this;
 
-    var setupResultsEvents = false;
-
     decorated.call(this, container, $container);
 
     container.on('open', function () {
       self._showDropdown();
       self._attachPositioningHandler(container);
-
-      if (!setupResultsEvents) {
-        setupResultsEvents = true;
-
-        container.on('results:all', function () {
-          self._positionDropdown();
-          self._resizeDropdown();
-        });
-
-        container.on('results:append', function () {
-          self._positionDropdown();
-          self._resizeDropdown();
-        });
-      }
     });
 
     container.on('close', function () {
@@ -39,6 +23,31 @@ define([
       self._detachPositioningHandler(container);
     });
 
+    container.on('results:all', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
+    container.on('results:append', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
+    container.on('results:message', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
+    container.on('select', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
+    container.on('unselect', function () {
+      self._positionDropdown();
+      self._resizeDropdown();
+    });
+
     this.$dropdownContainer.on('mousedown', function (evt) {
       evt.stopPropagation();
     });

+ 1 - 1
src/js/select2/dropdown/infiniteScroll.js

@@ -78,7 +78,7 @@ define([
     var $option = $(
       '<li ' +
       'class="select2-results__option select2-results__option--load-more"' +
-      'role="treeitem" aria-disabled="true"></li>'
+      'role="option" aria-disabled="true"></li>'
     );
 
     var message = this.options.get('translations').get('loadingMore');

+ 14 - 1
src/js/select2/dropdown/search.js

@@ -11,7 +11,7 @@ define([
       '<span class="select2-search select2-search--dropdown">' +
         '<input class="select2-search__field" type="search" tabindex="-1"' +
         ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
-        ' spellcheck="false" role="textbox" />' +
+        ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
       '</span>'
     );
 
@@ -26,6 +26,8 @@ define([
   Search.prototype.bind = function (decorated, container, $container) {
     var self = this;
 
+    var resultsId = container.id + '-results';
+
     decorated.call(this, container, $container);
 
     this.$search.on('keydown', function (evt) {
@@ -48,6 +50,7 @@ define([
 
     container.on('open', function () {
       self.$search.attr('tabindex', 0);
+      self.$search.attr('aria-controls', resultsId);
 
       self.$search.trigger('focus');
 
@@ -58,6 +61,8 @@ define([
 
     container.on('close', function () {
       self.$search.attr('tabindex', -1);
+      self.$search.removeAttr('aria-controls');
+      self.$search.removeAttr('aria-activedescendant');
 
       self.$search.val('');
       self.$search.trigger('blur');
@@ -80,6 +85,14 @@ define([
         }
       }
     });
+
+    container.on('results:focus', function (params) {
+      if (params.data._resultId) {
+        self.$search.attr('aria-activedescendant', params.data._resultId);
+      } else {
+        self.$search.removeAttr('aria-activedescendant');
+      }
+    });
   };
 
   Search.prototype.handleSearch = function (evt) {

+ 4 - 6
src/js/select2/i18n/de.js

@@ -18,12 +18,10 @@ define(function () {
       return 'Lade mehr Ergebnisse…';
     },
     maximumSelected: function (args) {
-      var message = 'Sie können nur ' + args.maximum + ' Eintr';
+      var message = 'Sie können nur ' + args.maximum + ' Element';
 
-      if (args.maximum === 1) {
-        message += 'ag';
-      } else {
-        message += 'äge';
+      if (args.maximum != 1) {
+        message += 'e';
       }
 
       message += ' auswählen';
@@ -37,7 +35,7 @@ define(function () {
       return 'Suche…';
     },
     removeAllItems: function () {
-      return 'Entferne alle Gegenstände';
+      return 'Entferne alle Elemente';
     }
   };
 });

+ 4 - 8
src/js/select2/options.js

@@ -11,6 +11,10 @@ define([
       this.fromElement($element);
     }
 
+    if ($element != null) {
+      this.options = Defaults.applyFromElement(this.options, $element);
+    }
+
     this.options = Defaults.apply(this.options);
 
     if ($element && $element.is('input')) {
@@ -34,14 +38,6 @@ define([
       this.options.disabled = $e.prop('disabled');
     }
 
-    if (this.options.language == null) {
-      if ($e.prop('lang')) {
-        this.options.language = $e.prop('lang').toLowerCase();
-      } else if ($e.closest('[lang]').prop('lang')) {
-        this.options.language = $e.closest('[lang]').prop('lang');
-      }
-    }
-
     if (this.options.dir == null) {
       if ($e.prop('dir')) {
         this.options.dir = $e.prop('dir');

+ 3 - 3
src/js/select2/results.js

@@ -14,7 +14,7 @@ define([
 
   Results.prototype.render = function () {
     var $results = $(
-      '<ul class="select2-results__options" role="tree"></ul>'
+      '<ul class="select2-results__options" role="listbox"></ul>'
     );
 
     if (this.options.get('multiple')) {
@@ -37,7 +37,7 @@ define([
     this.hideLoading();
 
     var $message = $(
-      '<li role="treeitem" aria-live="assertive"' +
+      '<li role="alert" aria-live="assertive"' +
       ' class="select2-results__option"></li>'
     );
 
@@ -171,7 +171,7 @@ define([
     option.className = 'select2-results__option';
 
     var attrs = {
-      'role': 'treeitem',
+      'role': 'option',
       'aria-selected': 'false'
     };
 

+ 3 - 4
src/js/select2/selection/base.js

@@ -29,6 +29,7 @@ define([
 
     $selection.attr('title', this.$element.attr('title'));
     $selection.attr('tabindex', this._tabindex);
+    $selection.attr('aria-disabled', 'false');
 
     this.$selection = $selection;
 
@@ -38,7 +39,6 @@ define([
   BaseSelection.prototype.bind = function (container, $container) {
     var self = this;
 
-    var id = container.id + '-container';
     var resultsId = container.id + '-results';
 
     this.container = container;
@@ -88,10 +88,12 @@ define([
 
     container.on('enable', function () {
       self.$selection.attr('tabindex', self._tabindex);
+      self.$selection.attr('aria-disabled', 'false');
     });
 
     container.on('disable', function () {
       self.$selection.attr('tabindex', '-1');
+      self.$selection.attr('aria-disabled', 'true');
     });
   };
 
@@ -114,7 +116,6 @@ define([
   };
 
   BaseSelection.prototype._attachCloseHandler = function (container) {
-    var self = this;
 
     $(document.body).on('mousedown.select2.' + container.id, function (e) {
       var $target = $(e.target);
@@ -124,8 +125,6 @@ define([
       var $all = $('.select2.select2-container--open');
 
       $all.each(function () {
-        var $this = $(this);
-
         if (this == $select[0]) {
           return;
         }

+ 6 - 1
src/js/select2/selection/multiple.js

@@ -95,7 +95,12 @@ define([
       var formatted = this.display(selection, $selection);
 
       $selection.append(formatted);
-      $selection.attr('title', selection.title || selection.text);
+
+      var title = selection.title || selection.text;
+
+      if (title) {
+        $selection.attr('title', title);
+      }
 
       Utils.StoreData($selection[0], 'data', selection);
 

+ 17 - 3
src/js/select2/selection/search.js

@@ -12,7 +12,7 @@ define([
       '<li class="select2-search select2-search--inline">' +
         '<input class="select2-search__field" type="search" tabindex="-1"' +
         ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
-        ' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
+        ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
       '</li>'
     );
 
@@ -29,14 +29,18 @@ define([
   Search.prototype.bind = function (decorated, container, $container) {
     var self = this;
 
+    var resultsId = container.id + '-results';
+
     decorated.call(this, container, $container);
 
     container.on('open', function () {
+      self.$search.attr('aria-controls', resultsId);
       self.$search.trigger('focus');
     });
 
     container.on('close', function () {
       self.$search.val('');
+      self.$search.removeAttr('aria-controls');
       self.$search.removeAttr('aria-activedescendant');
       self.$search.trigger('focus');
     });
@@ -56,7 +60,11 @@ define([
     });
 
     container.on('results:focus', function (params) {
-      self.$search.attr('aria-activedescendant', params.id);
+      if (params.data._resultId) {
+        self.$search.attr('aria-activedescendant', params.data._resultId);
+      } else {
+        self.$search.removeAttr('aria-activedescendant');
+      }
     });
 
     this.$selection.on('focusin', '.select2-search--inline', function (evt) {
@@ -90,6 +98,12 @@ define([
       }
     });
 
+    this.$selection.on('click', '.select2-search--inline', function (evt) {
+      if (self.$search.val()) {
+        evt.stopPropagation();
+      }
+    });
+
     // Try to detect the IE version should the `documentMode` property that
     // is stored on the document. This is only implemented in IE and is
     // slightly cleaner than doing a user agent check.
@@ -208,7 +222,7 @@ define([
     var width = '';
 
     if (this.$search.attr('placeholder') !== '') {
-      width = this.$selection.find('.select2-selection__rendered').innerWidth();
+      width = this.$selection.find('.select2-selection__rendered').width();
     } else {
       var minimumWidth = this.$search.val().length + 1;
 

+ 8 - 1
src/js/select2/selection/single.js

@@ -93,7 +93,14 @@ define([
     var formatted = this.display(selection, $rendered);
 
     $rendered.empty().append(formatted);
-    $rendered.attr('title', selection.title || selection.text);
+
+    var title = selection.title || selection.text;
+
+    if (title) {
+      $rendered.attr('title', title);
+    } else {
+      $rendered.removeAttr('title');
+    }
   };
 
   return SingleSelection;

+ 2 - 0
src/js/select2/utils.js

@@ -332,6 +332,8 @@ define([
     if (Utils.__cache[id] != null) {
       delete Utils.__cache[id];
     }
+
+    element.removeAttribute('data-select2-id');
   };
 
   return Utils;

+ 6 - 0
src/scss/theme/default/_multiple.scss

@@ -22,6 +22,12 @@
     font-weight: bold;
     margin-top: 5px;
     margin-right: 10px;
+
+    // This padding is to account for the bottom border for the first
+    // selection row and the top border of the second selection row.
+    // Without it, selections on the first row may be offset incorrectly
+    // and appear in their own row instead of going to the second row
+    padding: 1px;
   }
 
   .select2-selection__choice {

+ 0 - 51
tests/a11y/search-tests.js

@@ -1,51 +0,0 @@
-module('Accessibility - Search');
-
-var MultipleSelection = require('select2/selection/multiple');
-var InlineSearch = require('select2/selection/search');
-
-var $ = require('jquery');
-
-var Utils = require('select2/utils');
-var Options = require('select2/options');
-var options = new Options({});
-
-test('aria-autocomplete attribute is present', function (assert) {
-  var $select = $('#qunit-fixture .multiple');
-
-  var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
-  var selection = new CustomSelection($select, options);
-  var $selection = selection.render();
-
-  // Update the selection so the search is rendered
-  selection.update([]);
-
-  assert.equal(
-    $selection.find('input').attr('aria-autocomplete'),
-    'list',
-    'The search box is marked as autocomplete'
-  );
-});
-
-test('aria-activedescendant should be removed when closed', function (assert) {
-  var $select = $('#qunit-fixture .multiple');
-
-  var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
-  var selection = new CustomSelection($select, options);
-  var $selection = selection.render();
-
-  var container = new MockContainer();
-  selection.bind(container, $('<span></span>'));
-
-  // Update the selection so the search is rendered
-  selection.update([]);
-
-  var $search = $selection.find('input');
-  $search.attr('aria-activedescendant', 'something');
-
-  container.trigger('close');
-
-  assert.ok(
-    !$search.attr('aria-activedescendant'),
-    'There is no active descendant when the dropdown is closed'
-  );
-});

+ 32 - 0
tests/a11y/selection-tests.js

@@ -131,6 +131,38 @@ test('a custom tabindex is copied', function (assert) {
   );
 });
 
+test('aria-disabled should reflected disabled state', function (assert) {
+  var $select = $('#qunit-fixture .single');
+
+  var selection = new BaseSelection($select, options);
+  var $selection = selection.render();
+
+  var container = new MockContainer();
+  selection.bind(container, $('<span></span>'));
+
+  assert.equal(
+    $selection.attr('aria-disabled'),
+    'false',
+    'The tab index should match the original tab index'
+  );
+
+  container.trigger('disable');
+
+  assert.equal(
+    $selection.attr('aria-disabled'),
+    'true',
+    'The selection should be dropped out of the tab order when disabled'
+  );
+
+  container.trigger('enable');
+
+  assert.equal(
+    $selection.attr('aria-disabled'),
+    'false',
+    'The tab index should be restored when re-enabled'
+  );
+});
+
 module('Accessibility - Single');
 
 test('aria-labelledby should match the rendered container', function (assert) {

+ 54 - 0
tests/data/array-tests.js

@@ -71,6 +71,9 @@ test('current gets default for single', function (assert) {
 
   var data = new ArrayData($select, arrayOptions);
 
+  var container = new MockContainer();
+  data.bind(container, $('<div></div>'));
+
   data.current(function (val) {
     assert.equal(
       val.length,
@@ -93,6 +96,9 @@ test('current gets default for multiple', function (assert) {
 
   var data = new ArrayData($select, arrayOptions);
 
+  var container = new MockContainer();
+  data.bind(container, $('<div></div>'));
+
   data.current(function (val) {
     assert.equal(
       val.length,
@@ -107,6 +113,9 @@ test('current works with existing selections', function (assert) {
 
   var data = new ArrayData($select, arrayOptions);
 
+  var container = new MockContainer();
+  data.bind(container, $('<div></div>'));
+
   $select.val(['One']);
 
   data.current(function (val) {
@@ -137,6 +146,9 @@ test('current works with selected data', function (assert) {
 
   var data = new ArrayData($select, arrayOptions);
 
+  var container = new MockContainer();
+  data.bind(container, $('<div></div>'));
+
   data.select({
     id: '2',
     text: '2'
@@ -170,6 +182,9 @@ test('select works for single', function (assert) {
 
   var data = new ArrayData($select, arrayOptions);
 
+  var container = new MockContainer();
+  data.bind(container, $('<div></div>'));
+
   assert.equal(
     $select.val(),
     'default',
@@ -193,6 +208,9 @@ test('multiple sets the value', function (assert) {
 
   var data = new ArrayData($select, arrayOptions);
 
+  var container = new MockContainer();
+  data.bind(container, $('<div></div>'));
+
   assert.ok(
     $select.val() == null || $select.val().length == 0,
     'nothing should be selected'
@@ -211,6 +229,9 @@ test('multiple adds to the old value', function (assert) {
 
   var data = new ArrayData($select, arrayOptions);
 
+  var container = new MockContainer();
+  data.bind(container, $('<div></div>'));
+
   $select.val(['One']);
 
   assert.deepEqual($select.val(), ['One']);
@@ -228,6 +249,9 @@ test('option tags are automatically generated', function (assert) {
 
   var data = new ArrayData($select, arrayOptions);
 
+  var container = new MockContainer();
+  data.bind(container, $('<div></div>'));
+
   assert.equal(
     $select.find('option').length,
     4,
@@ -235,11 +259,32 @@ test('option tags are automatically generated', function (assert) {
   );
 });
 
+test('automatically generated option tags have a result id', function (assert) {
+  var $select = $('#qunit-fixture .single-empty');
+
+  var data = new ArrayData($select, arrayOptions);
+
+  var container = new MockContainer();
+  data.bind(container, $('<div></div>'));
+
+  data.select({
+    id: 'default'
+  });
+
+  assert.ok(
+    Utils.GetData($select.find(':selected')[0], 'data')._resultId,
+    '<option> default should have a result ID assigned'
+  );
+});
+
 test('option tags can receive new data', function(assert) {
   var $select = $('#qunit-fixture .single');
 
   var data = new ArrayData($select, extraOptions);
 
+  var container = new MockContainer();
+  data.bind(container, $('<div></div>'));
+
   assert.equal(
     $select.find('option').length,
     2,
@@ -270,6 +315,9 @@ test('optgroup tags can also be generated', function (assert) {
 
   var data = new ArrayData($select, nestedOptions);
 
+  var container = new MockContainer();
+  data.bind(container, $('<div></div>'));
+
   assert.equal(
     $select.find('option').length,
     1,
@@ -288,6 +336,9 @@ test('optgroup tags have the right properties', function (assert) {
 
   var data = new ArrayData($select, nestedOptions);
 
+  var container = new MockContainer();
+  data.bind(container, $('<div></div>'));
+
   var $group = $select.children('optgroup');
 
   assert.equal(
@@ -328,5 +379,8 @@ test('existing selections are respected on initialization', function (assert) {
 
     var data = new ArrayData($select, options);
 
+    var container = new MockContainer();
+    data.bind(container, $('<div></div>'));
+
     assert.equal($select.val(), 'Second');
 });

+ 15 - 0
tests/data/inputData-tests.js

@@ -23,6 +23,9 @@ test('test that options can be selected', function (assert) {
 
   var adapter = new InputAdapter($element, options);
 
+  var container = new MockContainer();
+  adapter.bind(container, $('<div></div>'));
+
   adapter.select({
     id: 'test'
   });
@@ -48,6 +51,9 @@ test('unselect the single selected option clears the value', function (assert) {
 
   var adapter = new InputAdapter($element, options);
 
+  var container = new MockContainer();
+  adapter.bind(container, $('<div></div>'));
+
   adapter.unselect({
     id: 'test'
   });
@@ -81,6 +87,9 @@ test('options can be unselected individually', function (assert) {
 
   var adapter = new InputAdapter($element, options);
 
+  var container = new MockContainer();
+  adapter.bind(container, $('<div></div>'));
+
   adapter.unselect({
     id: 'test2'
   });
@@ -107,6 +116,9 @@ test('default values can be set', function (assert) {
 
   var adapter = new InputAdapter($element, options);
 
+  var container = new MockContainer();
+  adapter.bind(container, $('<div></div>'));
+
   adapter.current(function (data) {
     assert.equal(
       data.length,
@@ -142,6 +154,9 @@ test('no default value', function (assert) {
 
   var adapter = new InputAdapter($element, options);
 
+  var container = new MockContainer();
+  adapter.bind(container, $('<div></div>'));
+
   adapter.current(function (data) {
     assert.equal(
       data.length,

+ 70 - 120
tests/data/maximumSelectionLength-tests.js

@@ -1,202 +1,152 @@
 module('Data adapters - Maximum selection length');
 
+var SelectData = require('select2/data/select');
 var MaximumSelectionLength = require('select2/data/maximumSelectionLength');
 
 var $ = require('jquery');
 var Options = require('select2/options');
 var Utils = require('select2/utils');
 
-function MaximumSelectionStub () {
-  this.called = false;
-  this.currentData = [];
-}
+var MaximumSelectionData = Utils.Decorate(SelectData, MaximumSelectionLength);
 
-MaximumSelectionStub.prototype.current = function (callback) {
-  callback(this.currentData);
-};
-
-MaximumSelectionStub.prototype.val = function (val) {
-  this.currentData.push(val);
-};
-
-MaximumSelectionStub.prototype.query = function (params, callback) {
-  this.called = true;
-};
+test('0 never displays the notice', function (assert) {
+  assert.expect(3);
 
-var MaximumSelectionData = Utils.Decorate(
-  MaximumSelectionStub,
-  MaximumSelectionLength
-);
+  var $select = $('#qunit-fixture .multiple');
 
-test('0 never displays the notice', function (assert) {
   var zeroOptions = new Options({
     maximumSelectionLength: 0
   });
 
-  var data = new MaximumSelectionData(null, zeroOptions);
+  var container = new MockContainer();
+  var data = new MaximumSelectionData($select, zeroOptions);
 
-  data.trigger = function () {
-    assert.ok(false, 'No events should be triggered');
-  };
+  data.bind(container, null);
+
+  data.on('results:message', function () {
+    assert.ok(false, 'The message should not be displayed');
+  });
 
   data.query({
     term: ''
+  }, function () {
+    assert.ok(true, 'The results should be queried');
   });
 
-  assert.ok(data.called);
-
-  data = new MaximumSelectionData(null, zeroOptions);
-
-  data.trigger = function () {
-    assert.ok(false, 'No events should be triggered');
-  };
-
-  data.val('1');
+  $select.val(['One']);
 
   data.query({
     term: ''
+  }, function () {
+    assert.ok(true, 'The results should be queried');
   });
 
-  assert.ok(data.called);
-
-  data = new MaximumSelectionData(null, zeroOptions);
-
-  data.trigger = function () {
-    assert.ok(false, 'No events should be triggered');
-  };
-
-  data.val('1');
-  data.val('2');
+  $select.val(['One', 'Two']);
 
   data.query({
     term: ''
+  }, function () {
+    assert.ok(true, 'The results should be queried');
   });
-
-  assert.ok(data.called);
 });
 
 test('< 0 never displays the notice', function (assert) {
+  assert.expect(3);
+
+  var $select = $('#qunit-fixture .multiple');
+
   var negativeOptions = new Options({
     maximumSelectionLength: -1
   });
 
-  var data = new MaximumSelectionData(null, negativeOptions);
+  var container = new MockContainer();
+  var data = new MaximumSelectionData($select, negativeOptions);
+
+  data.bind(container, null);
 
-  data.trigger = function () {
-    assert.ok(false, 'No events should be triggered');
-  };
+  data.on('results:message', function () {
+    assert.ok(false, 'The message should not be displayed');
+  });
 
   data.query({
     term: ''
+  }, function () {
+    assert.ok(true, 'The results should be queried');
   });
 
-  assert.ok(data.called);
-
-  data = new MaximumSelectionData(null, negativeOptions);
-
-  data.trigger = function () {
-    assert.ok(false, 'No events should be triggered');
-  };
-
-  data.val('1');
+  $select.val(['One']);
 
   data.query({
     term: ''
+  }, function () {
+    assert.ok(true, 'The results should be queried');
   });
 
-  assert.ok(data.called);
-
-  data = new MaximumSelectionData(null, negativeOptions);
-
-  data.trigger = function () {
-    assert.ok(false, 'No events should be triggered');
-  };
-
-  data.val('1');
-  data.val('2');
+  $select.val(['One', 'Two']);
 
   data.query({
     term: ''
+  }, function () {
+    assert.ok(true, 'The results should be queried');
   });
-
-  assert.ok(data.called);
 });
 
 test('triggers when >= 1 selection' , function (assert) {
-  var maxOfOneOptions = new Options({
-    maximumSelectionLength: 1
-  });
-  var data = new MaximumSelectionData(null, maxOfOneOptions);
+  assert.expect(2);
 
-  data.trigger = function () {
-    assert.ok(false, 'No events should be triggered');
-  };
+  var $select = $('#qunit-fixture .multiple');
 
-  data.query({
-    term: ''
+  var maxOfOneOptions = new Options({
+    maximumSelectionLength: 1
   });
 
-  assert.ok(data.called);
+  var container = new MockContainer();
+  var data = new MaximumSelectionData($select, maxOfOneOptions);
 
-  data = new MaximumSelectionData(null, maxOfOneOptions);
+  data.bind(container, null);
 
-  data.trigger = function () {
-    assert.ok(true, 'The event should be triggered.');
-  };
+  data.on('results:message', function () {
+    assert.ok(true, 'The message should be displayed');
+  });
 
-  data.val('1');
+  $select.val(['One']);
 
   data.query({
     term: ''
+  }, function () {
+    assert.ok(false, 'The results should not be queried');
   });
 
-  assert.ok(!data.called);
-
-});
-
-test('triggers when >= 2 selections' , function (assert) {
-  var maxOfTwoOptions = new Options({
-    maximumSelectionLength: 2
-  });
-  var data = new MaximumSelectionData(null, maxOfTwoOptions);
-
-  data.trigger = function () {
-    assert.ok(false, 'No events should be triggered');
-  };
+  $select.val(['One', 'Two']);
 
   data.query({
     term: ''
+  }, function () {
+    assert.ok(false, 'The results should not be queried');
   });
+});
 
-  assert.ok(data.called);
-
-  data = new MaximumSelectionData(null, maxOfTwoOptions);
-
-  data.trigger = function () {
-    assert.ok(false, 'No events should be triggered');
-  };
+test('triggers after selection' , function (assert) {
+  assert.expect(1);
 
-  data.val('1');
+  var $select = $('#qunit-fixture .multiple');
 
-  data.query({
-    term: ''
+  var maxOfOneOptions = new Options({
+    maximumSelectionLength: 1
   });
 
-  assert.ok(data.called);
-
-  data = new MaximumSelectionData(null, maxOfTwoOptions);
-
-  data.trigger = function () {
-    assert.ok(true, 'The event should be triggered.');
-  };
+  var container = new MockContainer();
+  var data = new MaximumSelectionData($select, maxOfOneOptions);
 
-  data.val('1');
-  data.val('2');
+  data.bind(container, null);
 
-  data.query({
-    term: ''
+  data.on('results:message', function () {
+    assert.ok(true, 'The message should be displayed');
   });
 
-  assert.ok(!data.called);
+  $select.val(['One']);
 
+  container.trigger('select', {
+    data: {}
+  });
 });

+ 185 - 0
tests/dropdown/search-a11y-tests.js

@@ -0,0 +1,185 @@
+module('Dropdown - Search - Accessibility');
+
+var Utils = require('select2/utils');
+
+var Dropdown = require('select2/dropdown');
+var DropdownSearch = Utils.Decorate(
+  Dropdown,
+  require('select2/dropdown/search')
+);
+
+var $ = require('jquery');
+
+var Options = require('select2/options');
+var options = new Options({});
+
+test('role attribute is set to searchbox', function (assert) {
+  var $select = $('#qunit-fixture .single');
+
+  var dropdown = new DropdownSearch($select, options);
+  var $dropdown = dropdown.render();
+
+  var container = new MockContainer();
+  dropdown.bind(container, $('<span></span>'));
+
+  assert.equal(
+    $dropdown.find('input').attr('role'),
+    'searchbox',
+    'The search box is marked as a search box'
+  );
+});
+
+test('aria-autocomplete attribute is present', function (assert) {
+  var $select = $('#qunit-fixture .single');
+
+  var dropdown = new DropdownSearch($select, options);
+  var $dropdown = dropdown.render();
+
+  var container = new MockContainer();
+  dropdown.bind(container, $('<span></span>'));
+
+  assert.equal(
+    $dropdown.find('input').attr('aria-autocomplete'),
+    'list',
+    'The search box is marked as autocomplete'
+  );
+});
+
+test('aria-activedescendant should not be set initiailly', function (assert) {
+  var $select = $('#qunit-fixture .single');
+
+  var dropdown = new DropdownSearch($select, options);
+  var $dropdown = dropdown.render();
+
+  var container = new MockContainer();
+  dropdown.bind(container, $('<span></span>'));
+
+  var $search = $dropdown.find('input');
+
+  assert.ok(
+    !$search.attr('aria-activedescendant'),
+    'The search box should not point to anything when it is first rendered'
+  );
+});
+
+test('aria-activedescendant should be set after highlight', function (assert) {
+  var $select = $('#qunit-fixture .single');
+
+  var dropdown = new DropdownSearch($select, options);
+  var $dropdown = dropdown.render();
+
+  var container = new MockContainer();
+  dropdown.bind(container, $('<span></span>'));
+
+  container.trigger('results:focus', {
+    data: {
+      _resultId: 'test'
+    }
+  });
+
+  var $search = $dropdown.find('input');
+
+  assert.equal(
+    $search.attr('aria-activedescendant'),
+    'test',
+    'The search is pointing to the focused result'
+  );
+});
+
+test('activedescendant should remove if there is no ID', function (assert) {
+  var $select = $('#qunit-fixture .single');
+
+  var dropdown = new DropdownSearch($select, options);
+  var $dropdown = dropdown.render();
+
+  var container = new MockContainer();
+  dropdown.bind(container, $('<span></span>'));
+
+  var $search = $dropdown.find('input');
+  $search.attr('aria-activedescendant', 'test');
+
+  container.trigger('results:focus', {
+    data: {}
+  });
+
+  assert.ok(
+    !$search.attr('aria-activedescendant'),
+    'There is no result for the search to be pointing to'
+  );
+});
+
+test('aria-activedescendant should be removed when closed', function (assert) {
+  var $select = $('#qunit-fixture .single');
+
+  var dropdown = new DropdownSearch($select, options);
+  var $dropdown = dropdown.render();
+
+  var container = new MockContainer();
+  dropdown.bind(container, $('<span></span>'));
+
+  var $search = $dropdown.find('input');
+  $search.attr('aria-activedescendant', 'something');
+
+  container.trigger('close');
+
+  assert.ok(
+    !$search.attr('aria-activedescendant'),
+    'There is no active descendant when the dropdown is closed'
+  );
+});
+
+test('aria-controls should not be set initiailly', function (assert) {
+  var $select = $('#qunit-fixture .single');
+
+  var dropdown = new DropdownSearch($select, options);
+  var $dropdown = dropdown.render();
+
+  var container = new MockContainer();
+  dropdown.bind(container, $('<span></span>'));
+
+  var $search = $dropdown.find('input');
+
+  assert.ok(
+    !$search.attr('aria-controls'),
+    'The search box should not point to the results when it is first rendered'
+  );
+});
+
+test('aria-controls should be set when opened', function (assert) {
+  var $select = $('#qunit-fixture .single');
+
+  var dropdown = new DropdownSearch($select, options);
+  var $dropdown = dropdown.render();
+
+  var container = new MockContainer();
+  dropdown.bind(container, $('<span></span>'));
+
+  var $search = $dropdown.find('input');
+
+  container.trigger('open');
+
+  assert.ok(
+    $search.attr('aria-controls'),
+    'The search should point to the results when it is opened'
+  );
+});
+
+test('aria-controls should be removed when closed', function (assert) {
+  var $select = $('#qunit-fixture .single');
+
+  var dropdown = new DropdownSearch($select, options);
+  var $dropdown = dropdown.render();
+
+  var container = new MockContainer();
+  dropdown.bind(container, $('<span></span>'));
+
+  var $search = $dropdown.find('input');
+  $search.attr('aria-controls', 'something');
+
+  container.trigger('close');
+
+  assert.ok(
+    !$search.attr('aria-controls'),
+    'There are no results for the search box to point to when it is closed'
+  );
+});

+ 262 - 2
tests/options/translation-tests.js

@@ -1,17 +1,145 @@
-module('Options - Translations');
-
 var $ = require('jquery');
 var Options = require('select2/options');
+var Defaults = require('select2/defaults');
+
+module('Options - Translations', {
+  beforeEach: function () {
+    Defaults.reset();
+  },
+  afterEach: function () {
+    Defaults.reset();
+  }
+});
+
+test('partial dictonaries are reset when default reset', function (assert) {
+  Defaults.set('language', {
+    test: 'testing'
+  });
+
+  Defaults.reset();
+
+  assert.ok(
+    !Defaults.defaults.language.test,
+    'The partial dictionary should have been reset'
+  );
+});
+
+test('default language chain is English', function (assert) {
+  var $element = $('<select></select>');
+
+  var options = new Options({}, $element);
+
+  assert.deepEqual(
+    options.get('language'),
+    ['en']
+  );
+});
+
+test(
+  'default translation includes all of the required messages',
+  function (assert) {
+    var $element = $('<select></select>');
+
+    var options = new Options({}, $element);
+
+    assert.deepEqual(
+      Object.keys(options.get('translations').all()),
+      [
+        'errorLoading',
+        'inputTooLong',
+        'inputTooShort',
+        'loadingMore',
+        'maximumSelected',
+        'noResults',
+        'searching',
+        'removeAllItems'
+      ]
+    );
+  }
+);
 
 test('partial dictionaries can be passed', function (assert) {
+  var $element = $('<select></select>');
+
   var options = new Options({
     language: {
       searching: function () {
         return 'Something';
       }
     }
+  }, $element);
+
+  var translations = options.get('translations');
+
+  assert.equal(
+    translations.get('searching')(),
+    'Something',
+    'The partial dictionary still overrides translations'
+  );
+
+  assert.equal(
+    translations.get('noResults')(),
+    'No results found',
+    'You can still get English translations for keys not passed in'
+  );
+});
+
+test('partial dictionaries can be combined with defaults', function (assert) {
+  var $element = $('<select></select>');
+
+  Defaults.set('language', {
+    test: function () {
+      return 'Testing';
+    }
   });
 
+  var options = new Options({
+    language: {
+      searching: function () {
+        return 'Something';
+      }
+    }
+  }, $element);
+
+  var translations = options.get('translations');
+
+  assert.equal(
+    translations.get('searching')(),
+    'Something',
+    'The partial dictionary still overrides translations'
+  );
+
+  assert.equal(
+    translations.get('test')(),
+    'Testing',
+    'The defaults were included in the fallback chain'
+  );
+
+  assert.equal(
+    translations.get('noResults')(),
+    'No results found',
+    'You can still get English translations for keys not passed in'
+  );
+});
+
+test('partial dictionaries can used in fallback chains', function (assert) {
+  var $element = $('<select></select>');
+
+  var options = new Options({
+    language: [
+      {
+        searching: function () {
+          return 'Something';
+        }
+      },
+      {
+        test: function () {
+          return 'Testing';
+        }
+      }
+    ]
+  }, $element);
+
   var translations = options.get('translations');
 
   assert.equal(
@@ -20,9 +148,141 @@ test('partial dictionaries can be passed', function (assert) {
     'The partial dictionary still overrides translations'
   );
 
+  assert.equal(
+    translations.get('test')(),
+    'Testing',
+    'The defaults were included in the fallback chain'
+  );
+
   assert.equal(
     translations.get('noResults')(),
     'No results found',
     'You can still get English translations for keys not passed in'
   );
 });
+
+test('language can be set via the options', function (assert) {
+  var $element = $('<select></select>');
+
+  var options = new Options({
+    language: 'es'
+  }, $element);
+
+  assert.deepEqual(
+    options.get('language'),
+    ['es', 'en']
+  );
+});
+
+test('multi-part language is broken out', function (assert) {
+  var $element = $('<select></select>');
+
+  var options = new Options({
+    language: 'pt-BR'
+  }, $element);
+
+  assert.deepEqual(
+    options.get('language'),
+    ['pt-BR', 'pt', 'en']
+  );
+});
+
+test('default language can be set', function (assert) {
+  var $element = $('<select></select>');
+
+  Defaults.set('language', 'es');
+
+  var options = new Options({}, $element);
+
+  assert.deepEqual(
+    options.get('language'),
+    ['es', 'en']
+  );
+});
+
+test('lanugage set via options adds to default chain', function (assert) {
+  var $element = $('<select></select>');
+
+  Defaults.set('language', 'es');
+
+  var options = new Options({
+    language: 'it'
+  }, $element);
+
+  assert.deepEqual(
+    options.get('language'),
+    ['it', 'es', 'en']
+  );
+});
+
+test('default language chain can be set', function (assert) {
+  var $element = $('<select></select>');
+
+  Defaults.set('language', ['es', 'it', 'en']);
+
+  var options = new Options({}, $element);
+
+  assert.deepEqual(
+    options.get('language'),
+    ['es', 'it', 'en']
+  );
+});
+
+test('language can be set by lang attr', function (assert) {
+  var $element = $('<select lang="es"></select>');
+
+  var options = new Options({}, $element);
+
+  assert.deepEqual(
+    options.get('language'),
+    ['es', 'en']
+  );
+});
+
+test('language can be inherited by lang attr', function (assert) {
+  var $element = $('<div lang="es"><select></select></div>').find('select');
+
+  var options = new Options({}, $element);
+
+  assert.deepEqual(
+    options.get('language'),
+    ['es', 'en']
+  );
+});
+
+test('multi-part language can be inherited by lang attr', function (assert) {
+  var $element = $('<div lang="pt-BR"><select></select></div>').find('select');
+
+  var options = new Options({}, $element);
+
+  assert.deepEqual(
+    options.get('language'),
+    ['pt-BR', 'pt', 'en']
+  );
+});
+
+test('lang attr overrides default language', function (assert) {
+  var $element = $('<select lang="it"></select>');
+
+  Defaults.set('language', 'es');
+
+  var options = new Options({}, $element);
+
+  assert.deepEqual(
+    options.get('language'),
+    ['it', 'es', 'en']
+  );
+});
+
+test('default language overrides inherited lang attr', function (assert) {
+  var $element = $('<div lang="it"><select></select></div>').find('select');
+
+  Defaults.set('language', 'es');
+
+  var options = new Options({}, $element);
+
+  assert.deepEqual(
+    options.get('language'),
+    ['es', 'it', 'en']
+  );
+});

+ 25 - 0
tests/results/a11y-tests.js

@@ -0,0 +1,25 @@
+module('Results - Accessibility');
+
+var $ = require('jquery');
+
+var Options = require('select2/options');
+
+var Results = require('select2/results');
+
+test('role of results should be a listbox', function (assert) {
+  var results = new Results($('<select></select>'), new Options({}));
+
+  var $results = results.render();
+
+  assert.equal($results.attr('role'), 'listbox');
+});
+
+test('multiple select should have aria-multiselectable', function (assert) {
+  var results = new Results($('<select></select>'), new Options({
+    multiple: true
+  }));
+
+  var $results = results.render();
+
+  assert.equal($results.attr('aria-multiselectable'), 'true');
+});

+ 54 - 1
tests/results/option-tests.js

@@ -60,4 +60,57 @@ test('option in disabled optgroup is disabled', function (assert) {
   });
 
   assert.equal(option.getAttribute('aria-disabled'), 'true');
-});
+});
+
+test('options are not selected by default', function (assert) {
+  var results = new Results($('<select></select>'), new Options({}));
+
+  var $option = $('<option></option>');
+  var option = results.option({
+    id: 'test',
+    element: $option[0]
+  });
+
+  assert.equal(option.getAttribute('aria-selected'), 'false');
+});
+
+test('options with children are given the group role', function(assert) {
+  var results = new Results($('<select></select>'), new Options({}));
+
+  var $option = $('<optgroup></optgroup>');
+  var option = results.option({
+    children: [{
+      id: 'test'
+    }],
+    element: $option[0]
+  });
+
+  assert.equal(option.getAttribute('role'), 'group');
+});
+
+test('options with children have the aria-label set', function (assert) {
+  var results = new Results($('<select></select>'), new Options({}));
+
+  var $option = $('<optgroup></optgroup>');
+  var option = results.option({
+    children: [{
+      id: 'test'
+    }],
+    element: $option[0],
+    text: 'test'
+  });
+
+  assert.equal(option.getAttribute('aria-label'), 'test');
+});
+
+test('non-group options are given the option role', function (assert) {
+  var results = new Results($('<select></select>'), new Options({}));
+
+  var $option = $('<option></option>');
+  var option = results.option({
+    id: 'test',
+    element: $option[0]
+  });
+
+  assert.equal(option.getAttribute('role'), 'option');
+});

+ 70 - 0
tests/selection/allowClear-tests.js

@@ -4,6 +4,7 @@ var Placeholder = require('select2/selection/placeholder');
 var AllowClear = require('select2/selection/allowClear');
 
 var SingleSelection = require('select2/selection/single');
+var MultipleSelection = require('select2/selection/multiple');
 
 var $ = require('jquery');
 var Options = require('select2/options');
@@ -328,3 +329,72 @@ test('clear does not work when disabled', function (assert) {
     'The placeholder should not have been set'
   );
 });
+
+test('clear button doesnt visually break selected options', function (assert) {
+  var $element = $('<select></select>');
+
+  var Selection = Utils.Decorate(
+    Utils.Decorate(MultipleSelection, Placeholder),
+    AllowClear
+  );
+
+  var selection = new Selection(
+    $element,
+    allowClearOptions
+  );
+  var container = new MockContainer();
+
+  var $container = $(
+    '<span class="select2-container select2-container--default"></span>'
+  );
+  $('#qunit-fixture').append($container);
+
+  var $selection = selection.render();
+  $container.append($selection);
+  $container.css('width', '100px');
+
+  selection.bind(container, $container);
+
+  selection.update([{
+    id: '1',
+    text: '1'
+  }]);
+
+  var singleHeight = $container.height();
+
+  selection.update([
+    {
+      id: '10',
+      text: '10'
+    },
+    {
+      id: '20',
+      text: '20'
+    }
+  ]);
+
+  var doubleHeight = $container.height();
+
+  selection.update([
+    {
+      id: '1',
+      text: '1'
+    },
+    {
+      id: '2',
+      text: '2'
+    }
+  ]);
+
+  assert.notEqual(
+    singleHeight,
+    doubleHeight,
+    'The height of the two different rows should be different'
+  );
+
+  assert.equal(
+    $container.height(),
+    doubleHeight,
+    'There should be two full lines of selections'
+  );
+});

+ 110 - 3
tests/selection/multiple-tests.js

@@ -72,12 +72,119 @@ test('empty update clears the selection', function (assert) {
   var $rendered = $selection.find('.select2-selection__rendered');
 
   $rendered.text('testing');
-  $rendered.attr('title', 'testing');
 
   selection.update([]);
 
-  assert.equal($rendered.text(), '');
-  assert.equal($rendered.attr('title'), undefined);
+  assert.equal(
+    $rendered.text(),
+    '',
+    'There should have been nothing rendered'
+  );
+});
+
+test('empty update clears the selection title', function (assert) {
+  var selection = new MultipleSelection(
+    $('#qunit-fixture .multiple'),
+    options
+  );
+
+  var $selection = selection.render();
+
+  selection.update([]);
+
+  var $rendered = $selection.find('.select2-selection__rendered li');
+
+  assert.equal(
+    $rendered.attr('title'),
+    undefined,
+    'The title should be removed if nothing is rendered'
+  );
+});
+
+test('update sets the title to the data text', function (assert) {
+  var selection = new MultipleSelection(
+    $('#qunit-fixture .multiple'),
+    options
+  );
+
+  var $selection = selection.render();
+
+  selection.update([{
+    text: 'test'
+  }]);
+
+  var $rendered = $selection.find('.select2-selection__rendered li');
+
+  assert.equal(
+    $rendered.attr('title'),
+    'test',
+    'The title should have been set to the text'
+  );
+});
+
+test('update sets the title to the data title', function (assert) {
+  var selection = new MultipleSelection(
+    $('#qunit-fixture .multiple'),
+    options
+  );
+
+  var $selection = selection.render();
+
+  selection.update([{
+    text: 'test',
+    title: 'correct'
+  }]);
+
+  var $rendered = $selection.find('.select2-selection__rendered li');
+
+  assert.equal(
+    $rendered.attr('title'),
+    'correct',
+    'The title should have taken precedence over the text'
+  );
+});
+
+test('update should clear title for placeholder options', function (assert) {
+  var selection = new MultipleSelection(
+    $('#qunit-fixture .multiple'),
+    options
+  );
+
+  var $selection = selection.render();
+
+  selection.update([{
+    id: '',
+    text: ''
+  }]);
+
+  var $rendered = $selection.find('.select2-selection__rendered li');
+
+  assert.equal(
+    $rendered.attr('title'),
+    undefined,
+    'The title should be removed if a placeholder is rendered'
+  );
+});
+
+test('update should clear title for options without text', function (assert) {
+  var selection = new MultipleSelection(
+    $('#qunit-fixture .multiple'),
+    options
+  );
+
+  var $selection = selection.render();
+
+  selection.update([{
+    id: ''
+  }]);
+
+  var $rendered = $selection.find('.select2-selection__rendered li');
+
+  assert.equal(
+    $rendered.attr('title'),
+    undefined,
+    'The title should be removed if there is no text or title property'
+  );
 });
 
 test('escapeMarkup is being used', function (assert) {

+ 217 - 0
tests/selection/search-a11y-tests.js

@@ -0,0 +1,217 @@
+module('Selection containers - Inline search - Accessibility');
+
+var MultipleSelection = require('select2/selection/multiple');
+var InlineSearch = require('select2/selection/search');
+
+var $ = require('jquery');
+
+var Utils = require('select2/utils');
+var Options = require('select2/options');
+var options = new Options({});
+
+test('role attribute is set to searchbox', function (assert) {
+  var $select = $('#qunit-fixture .multiple');
+
+  var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
+  var selection = new CustomSelection($select, options);
+  var $selection = selection.render();
+
+  var container = new MockContainer();
+  selection.bind(container, $('<span></span>'));
+
+  // Update the selection so the search is rendered
+  selection.update([]);
+
+  assert.equal(
+    $selection.find('input').attr('role'),
+    'searchbox',
+    'The search box is marked as a search box'
+  );
+});
+
+test('aria-autocomplete attribute is present', function (assert) {
+  var $select = $('#qunit-fixture .multiple');
+
+  var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
+  var selection = new CustomSelection($select, options);
+  var $selection = selection.render();
+
+  var container = new MockContainer();
+  selection.bind(container, $('<span></span>'));
+
+  // Update the selection so the search is rendered
+  selection.update([]);
+
+  assert.equal(
+    $selection.find('input').attr('aria-autocomplete'),
+    'list',
+    'The search box is marked as autocomplete'
+  );
+});
+
+test('aria-activedescendant should not be set initiailly', function (assert) {
+  var $select = $('#qunit-fixture .multiple');
+
+  var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
+  var selection = new CustomSelection($select, options);
+  var $selection = selection.render();
+
+  var container = new MockContainer();
+  selection.bind(container, $('<span></span>'));
+
+  // Update the selection so the search is rendered
+  selection.update([]);
+
+  var $search = $selection.find('input');
+
+  assert.ok(
+    !$search.attr('aria-activedescendant'),
+    'The search box should not point to anything when it is first rendered'
+  );
+});
+
+test('aria-activedescendant should be set after highlight', function (assert) {
+  var $select = $('#qunit-fixture .multiple');
+
+  var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
+  var selection = new CustomSelection($select, options);
+  var $selection = selection.render();
+
+  var container = new MockContainer();
+  selection.bind(container, $('<span></span>'));
+
+  // Update the selection so the search is rendered
+  selection.update([]);
+
+  container.trigger('results:focus', {
+    data: {
+      _resultId: 'test'
+    }
+  });
+
+  var $search = $selection.find('input');
+
+  assert.equal(
+    $search.attr('aria-activedescendant'),
+    'test',
+    'The search is pointing to the focused result'
+  );
+});
+
+test('activedescendant should remove if there is no ID', function (assert) {
+  var $select = $('#qunit-fixture .multiple');
+
+  var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
+  var selection = new CustomSelection($select, options);
+  var $selection = selection.render();
+
+  var container = new MockContainer();
+  selection.bind(container, $('<span></span>'));
+
+  // Update the selection so the search is rendered
+  selection.update([]);
+
+  var $search = $selection.find('input');
+  $search.attr('aria-activedescendant', 'test');
+
+  container.trigger('results:focus', {
+    data: {}
+  });
+
+  assert.ok(
+    !$search.attr('aria-activedescendant'),
+    'There is no result for the search to be pointing to'
+  );
+});
+
+test('aria-activedescendant should be removed when closed', function (assert) {
+  var $select = $('#qunit-fixture .multiple');
+
+  var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
+  var selection = new CustomSelection($select, options);
+  var $selection = selection.render();
+
+  var container = new MockContainer();
+  selection.bind(container, $('<span></span>'));
+
+  // Update the selection so the search is rendered
+  selection.update([]);
+
+  var $search = $selection.find('input');
+  $search.attr('aria-activedescendant', 'something');
+
+  container.trigger('close');
+
+  assert.ok(
+    !$search.attr('aria-activedescendant'),
+    'There is no active descendant when the dropdown is closed'
+  );
+});
+
+test('aria-controls should not be set initiailly', function (assert) {
+  var $select = $('#qunit-fixture .multiple');
+
+  var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
+  var selection = new CustomSelection($select, options);
+  var $selection = selection.render();
+
+  var container = new MockContainer();
+  selection.bind(container, $('<span></span>'));
+
+  // Update the selection so the search is rendered
+  selection.update([]);
+
+  var $search = $selection.find('input');
+
+  assert.ok(
+    !$search.attr('aria-controls'),
+    'The search box should not point to the results when it is first rendered'
+  );
+});
+
+test('aria-controls should be set when opened', function (assert) {
+  var $select = $('#qunit-fixture .multiple');
+
+  var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
+  var selection = new CustomSelection($select, options);
+  var $selection = selection.render();
+
+  var container = new MockContainer();
+  selection.bind(container, $('<span></span>'));
+
+  // Update the selection so the search is rendered
+  selection.update([]);
+
+  var $search = $selection.find('input');
+
+  container.trigger('open');
+
+  assert.ok(
+    $search.attr('aria-controls'),
+    'The search should point to the results when it is opened'
+  );
+});
+
+test('aria-controls should be removed when closed', function (assert) {
+  var $select = $('#qunit-fixture .multiple');
+
+  var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
+  var selection = new CustomSelection($select, options);
+  var $selection = selection.render();
+
+  var container = new MockContainer();
+  selection.bind(container, $('<span></span>'));
+
+  // Update the selection so the search is rendered
+  selection.update([]);
+
+  var $search = $selection.find('input');
+  $search.attr('aria-controls', 'something');
+
+  container.trigger('close');
+
+  assert.ok(
+    !$search.attr('aria-controls'),
+    'There are no results for the search box to point to when it is closed'
+  );
+});

+ 55 - 0
tests/selection/search-placeholder-tests.js

@@ -0,0 +1,55 @@
+module('Selection containers - Inline search - Placeholder');
+
+var MultipleSelection = require('select2/selection/multiple');
+var InlineSearch = require('select2/selection/search');
+var SelectionPlaceholder = require('select2/selection/placeholder');
+
+var $ = require('jquery');
+var Options = require('select2/options');
+var Utils = require('select2/utils');
+
+var CustomSelection = Utils.Decorate(
+  Utils.Decorate(MultipleSelection, SelectionPlaceholder),
+  InlineSearch
+);
+
+test('width does not extend the search box', function (assert) {
+    assert.expect(2);
+
+    var $container = $(
+      '<div style="width: 100px; display: table-cell">' +
+      '<div style="width: 100%" ' +
+      'class="select2-container select2-container--default"></div>' +
+      '</div>'
+    );
+    var container = new MockContainer();
+
+    var $element = $('#qunit-fixture .multiple');
+    var selection = new CustomSelection($element, new Options({
+      placeholder: 'Test placeholder'
+    }));
+
+    var $selection = selection.render();
+    selection.bind(container, $container);
+
+    // Make it visible so the browser can place focus on the search
+    $container.append($selection);
+    $('#qunit-fixture').append($container);
+
+    // Update the selection so the search is rendered
+    selection.update([]);
+
+    var $search = $selection.find('input');
+
+    assert.equal(
+      $search.outerWidth(),
+      60,
+      'The search should not be the entire width of the container'
+    );
+
+    assert.equal(
+      $container.children().outerWidth(),
+      100,
+      'The container should be the width assigned to the parent in CSS'
+    );
+  });

+ 87 - 1
tests/selection/search-tests.js

@@ -188,4 +188,90 @@ test('the focus event shifts the focus', function (assert) {
     $search[0],
     'The search did not have focus originally'
   );
-});
+});
+
+test('search box without text should propagate click', function (assert) {
+  assert.expect(1);
+
+  var $container = $('#qunit-fixture .event-container');
+  var container = new MockContainer();
+
+  var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
+
+  var $element = $('#qunit-fixture .multiple');
+  var selection = new CustomSelection($element, options);
+
+  var $selection = selection.render();
+  selection.bind(container, $container);
+
+  // Update the selection so the search is rendered
+  selection.update([]);
+
+  // Make it visible so the browser can place focus on the search
+  $container.append($selection);
+
+  $selection.on('click', function () {
+    assert.ok(true, 'The click event should not have been trapped');
+  });
+
+  var $search = $selection.find('input');
+  $search.trigger('click');
+});
+
+test('search box with text should not propagate click', function (assert) {
+  assert.expect(0);
+
+  var $container = $('#qunit-fixture .event-container');
+  var container = new MockContainer();
+
+  var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
+
+  var $element = $('#qunit-fixture .multiple');
+  var selection = new CustomSelection($element, options);
+
+  var $selection = selection.render();
+  selection.bind(container, $container);
+
+  // Update the selection so the search is rendered
+  selection.update([]);
+
+  // Make it visible so the browser can place focus on the search
+  $container.append($selection);
+
+  $selection.on('click', function () {
+    assert.ok(false, 'The click event should have been trapped');
+  });
+
+  var $search = $selection.find('input');
+  $search.val('test');
+  $search.trigger('click');
+});
+
+test('search box with text should not close dropdown', function (assert) {
+  assert.expect(0);
+
+  var $container = $('#qunit-fixture .event-container');
+  var container = new MockContainer();
+
+  var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
+
+  var $element = $('#qunit-fixture .multiple');
+  var selection = new CustomSelection($element, options);
+
+  var $selection = selection.render();
+  selection.bind(container, $container);
+
+  // Update the selection so the search is rendered
+  selection.update([]);
+
+  // Make it visible so the browser can place focus on the search
+  $container.append($selection);
+
+  container.on('close', function () {
+    assert.ok(false, 'The dropdown should not have closed');
+  });
+
+  var $search = $selection.find('input');
+  $search.val('test');
+  $search.trigger('click');
+});

+ 112 - 4
tests/selection/single-tests.js

@@ -50,7 +50,7 @@ test('templateSelection can addClass', function (assert) {
   );
 
   var $container = selection.selectionContainer();
-  
+
   var out = selection.display({
     text: 'test'
   }, $container);
@@ -58,7 +58,7 @@ test('templateSelection can addClass', function (assert) {
   assert.ok(called);
 
   assert.equal(out, 'test');
-  
+
   assert.ok($container.hasClass('testclass'));
 });
 
@@ -72,12 +72,34 @@ test('empty update clears the selection', function (assert) {
   var $rendered = $selection.find('.select2-selection__rendered');
 
   $rendered.text('testing');
+
+  selection.update([]);
+
+  assert.equal(
+    $rendered.text(),
+    '',
+    'There should have been nothing rendered'
+  );
+});
+
+test('empty update clears the selection title', function (assert) {
+  var selection = new SingleSelection(
+    $('#qunit-fixture .single'),
+    options
+  );
+
+  var $selection = selection.render();
+  var $rendered = $selection.find('.select2-selection__rendered');
+
   $rendered.attr('title', 'testing');
 
   selection.update([]);
 
-  assert.equal($rendered.text(), '');
-  assert.equal($rendered.attr('title'), undefined);
+  assert.equal(
+    $rendered.attr('title'),
+    undefined,
+    'The title should be removed if nothing is rendered'
+  );
 });
 
 test('update renders the data text', function (assert) {
@@ -96,6 +118,92 @@ test('update renders the data text', function (assert) {
   assert.equal($rendered.text(), 'test');
 });
 
+test('update sets the title to the data text', function (assert) {
+  var selection = new SingleSelection(
+    $('#qunit-fixture .single'),
+    options
+  );
+
+  var $selection = selection.render();
+  var $rendered = $selection.find('.select2-selection__rendered');
+
+  selection.update([{
+    text: 'test'
+  }]);
+
+  assert.equal(
+    $rendered.attr('title'),
+    'test',
+    'The title should have been set to the text'
+  );
+});
+
+test('update sets the title to the data title', function (assert) {
+  var selection = new SingleSelection(
+    $('#qunit-fixture .single'),
+    options
+  );
+
+  var $selection = selection.render();
+  var $rendered = $selection.find('.select2-selection__rendered');
+
+  selection.update([{
+    text: 'test',
+    title: 'correct'
+  }]);
+
+  assert.equal(
+    $rendered.attr('title'),
+    'correct',
+    'The title should have taken precedence over the text'
+  );
+});
+
+test('update should clear title for placeholder options', function (assert) {
+  var selection = new SingleSelection(
+    $('#qunit-fixture .single'),
+    options
+  );
+
+  var $selection = selection.render();
+  var $rendered = $selection.find('.select2-selection__rendered');
+
+  $rendered.attr('title', 'testing');
+
+  selection.update([{
+    id: '',
+    text: ''
+  }]);
+
+  assert.equal(
+    $rendered.attr('title'),
+    undefined,
+    'The title should be removed if a placeholder is rendered'
+  );
+});
+
+test('update should clear title for options without text', function (assert) {
+  var selection = new SingleSelection(
+    $('#qunit-fixture .single'),
+    options
+  );
+
+  var $selection = selection.render();
+  var $rendered = $selection.find('.select2-selection__rendered');
+
+  $rendered.attr('title', 'testing');
+
+  selection.update([{
+    id: ''
+  }]);
+
+  assert.equal(
+    $rendered.attr('title'),
+    undefined,
+    'The title should be removed if there is no text or title property'
+  );
+});
+
 test('escapeMarkup is being used', function (assert) {
   var selection = new SingleSelection(
     $('#qunit-fixture .single'),

+ 5 - 1
tests/unit-jq1.html

@@ -57,7 +57,6 @@
     <script src="helpers.js" type="text/javascript"></script>
 
     <script src="a11y/selection-tests.js" type="text/javascript"></script>
-    <script src="a11y/search-tests.js" type="text/javascript"></script>
 
     <script src="data/array-tests.js" type="text/javascript"></script>
     <script src="data/base-tests.js" type="text/javascript"></script>
@@ -72,6 +71,7 @@
 
     <script src="dropdown/dropdownCss-tests.js" type="text/javascript"></script>
     <script src="dropdown/positioning-tests.js" type="text/javascript"></script>
+    <script src="dropdown/search-a11y-tests.js" type="text/javascript"></script>
     <script src="dropdown/selectOnClose-tests.js" type="text/javascript"></script>
     <script src="dropdown/stopPropagation-tests.js" type="text/javascript"></script>
 
@@ -81,6 +81,7 @@
     <script src="options/translation-tests.js" type="text/javascript"></script>
     <script src="options/width-tests.js" type="text/javascript"></script>
 
+    <script src="results/a11y-tests.js" type="text/javascript"></script>
     <script src="results/focusing-tests.js" type="text/javascript"></script>
     <script src="results/infiniteScroll-tests.js" type="text/javascript"></script>
     <script src="results/option-tests.js" type="text/javascript"></script>
@@ -91,9 +92,12 @@
     <script src="selection/multiple-tests.js" type="text/javascript"></script>
     <script src="selection/placeholder-tests.js" type="text/javascript"></script>
     <script src="selection/search-tests.js" type="text/javascript"></script>
+    <script src="selection/search-a11y-tests.js" type="text/javascript"></script>
+    <script src="selection/search-placeholder-tests.js" type="text/javascript"></script>
     <script src="selection/single-tests.js" type="text/javascript"></script>
     <script src="selection/stopPropagation-tests.js" type="text/javascript"></script>
 
+    <script src="utils/data-tests.js" type="text/javascript"></script>
     <script src="utils/decorator-tests.js" type="text/javascript"></script>
     <script src="utils/escapeMarkup-tests.js" type="text/javascript"></script>
   </body>

Some files were not shown because too many files changed in this diff