select2-rails 4.0.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -0
  3. data/lib/select2-rails/source_file.rb +3 -4
  4. data/lib/select2-rails/version.rb +1 -1
  5. data/vendor/assets/javascripts/select2.js +280 -113
  6. data/vendor/assets/javascripts/select2_locale_ar.js +3 -0
  7. data/vendor/assets/javascripts/select2_locale_az.js +1 -1
  8. data/vendor/assets/javascripts/select2_locale_bg.js +1 -1
  9. data/vendor/assets/javascripts/select2_locale_ca.js +1 -1
  10. data/vendor/assets/javascripts/select2_locale_cs.js +1 -1
  11. data/vendor/assets/javascripts/select2_locale_da.js +2 -2
  12. data/vendor/assets/javascripts/select2_locale_de.js +1 -1
  13. data/vendor/assets/javascripts/select2_locale_en.js +1 -1
  14. data/vendor/assets/javascripts/select2_locale_es.js +1 -1
  15. data/vendor/assets/javascripts/select2_locale_et.js +1 -1
  16. data/vendor/assets/javascripts/select2_locale_eu.js +1 -1
  17. data/vendor/assets/javascripts/select2_locale_fa.js +1 -1
  18. data/vendor/assets/javascripts/select2_locale_fi.js +1 -1
  19. data/vendor/assets/javascripts/select2_locale_fr.js +1 -1
  20. data/vendor/assets/javascripts/select2_locale_gl.js +2 -2
  21. data/vendor/assets/javascripts/select2_locale_he.js +2 -2
  22. data/vendor/assets/javascripts/select2_locale_hi.js +1 -1
  23. data/vendor/assets/javascripts/select2_locale_hr.js +2 -2
  24. data/vendor/assets/javascripts/select2_locale_hu.js +1 -1
  25. data/vendor/assets/javascripts/select2_locale_id.js +2 -2
  26. data/vendor/assets/javascripts/select2_locale_is.js +1 -1
  27. data/vendor/assets/javascripts/select2_locale_it.js +1 -1
  28. data/vendor/assets/javascripts/select2_locale_ja.js +3 -0
  29. data/vendor/assets/javascripts/select2_locale_ko.js +1 -1
  30. data/vendor/assets/javascripts/select2_locale_lt.js +1 -1
  31. data/vendor/assets/javascripts/select2_locale_lv.js +1 -1
  32. data/vendor/assets/javascripts/select2_locale_mk.js +1 -1
  33. data/vendor/assets/javascripts/select2_locale_ms.js +3 -0
  34. data/vendor/assets/javascripts/select2_locale_nb.js +1 -1
  35. data/vendor/assets/javascripts/select2_locale_nl.js +2 -2
  36. data/vendor/assets/javascripts/select2_locale_pl.js +2 -2
  37. data/vendor/assets/javascripts/select2_locale_pt-BR.js +1 -1
  38. data/vendor/assets/javascripts/select2_locale_pt.js +1 -1
  39. data/vendor/assets/javascripts/select2_locale_ro.js +1 -1
  40. data/vendor/assets/javascripts/select2_locale_ru.js +1 -1
  41. data/vendor/assets/javascripts/select2_locale_sk.js +1 -1
  42. data/vendor/assets/javascripts/select2_locale_sr-Cyrl.js +3 -0
  43. data/vendor/assets/javascripts/select2_locale_sr.js +2 -2
  44. data/vendor/assets/javascripts/select2_locale_sv.js +1 -1
  45. data/vendor/assets/javascripts/select2_locale_th.js +2 -2
  46. data/vendor/assets/javascripts/select2_locale_tr.js +1 -1
  47. data/vendor/assets/javascripts/select2_locale_uk.js +1 -1
  48. data/vendor/assets/javascripts/select2_locale_vi.js +1 -1
  49. data/vendor/assets/javascripts/select2_locale_zh-CN.js +1 -1
  50. data/vendor/assets/javascripts/select2_locale_zh-TW.js +1 -1
  51. data/vendor/assets/stylesheets/select2-bootstrap.css +56 -22
  52. data/vendor/assets/stylesheets/select2.css +77 -26
  53. metadata +7 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 35dee159738ab03828527d0362c979fae5885a92
4
- data.tar.gz: e034756a968b0628b747e05af1e400e2aeb3dc2d
3
+ metadata.gz: ff7c6750781db2709e18feeebcf02776af295fbd
4
+ data.tar.gz: 48ba6caef7b2a14fd31bc88be1a1574ab170ab9a
5
5
  SHA512:
6
- metadata.gz: 1fbb76bad647c33d14560523a4854b948f71170b683f4d93df0e8779357caf8104eaa5d65f0740d63e3c4a33f215751aef11db585814cd2c1254597631a3581b
7
- data.tar.gz: 7e7aa3ee1986954f196a64dac6d84340f2212ee60f7f87fb805e854fa618049ebaff20e7a49ed14ca8e739201efface9d7bb65f02f222b18bd4011cc300b1231
6
+ metadata.gz: 54b35921268818caa65940a654a946009fa3d3ff3d5682d765a26b7981538910ee53454f0adec1faa2e198e73bc80653369dd6400a094b60ecc60fc325e2bb8e
7
+ data.tar.gz: b14c5149ad12cca1e7b3483c053ea46d1560f095fbea391669dc604007e3ffef2fff8b7eefbd31e6e030fb757c74aef796acfbc23b1c4fc59d60bcdce06ffd21
data/README.md CHANGED
@@ -30,6 +30,12 @@ If you are using Twitter Boostrap you need to also require the bootstrap theme C
30
30
 
31
31
  *= require select2-bootstrap
32
32
 
33
+ To apply the theme, tell Select2 to do so by passing `bootstrap` to the [`theme`](https://select2.github.io/examples.html#themes) option when initializing Select2:
34
+
35
+ $( "#dropdown" ).select2({
36
+ theme: "bootstrap"
37
+ });
38
+
33
39
  ## Internationalization (i18n)
34
40
 
35
41
  The `select2-rails` now supports multiple languages.
@@ -27,10 +27,9 @@ class SourceFile < Thor
27
27
  end
28
28
 
29
29
  def languages
30
- [ "az", "bg", "ca", "cs", "da", "de", "en", "es", "et", "eu", "fa", "fi", "fr", "gl", "he", "hi", "hr", "hu",
31
- "id", "is", "it", "ko", "lt", "lv", "mk", "nb", "nl", "pl", "pt-BR", "pt", "ro", "ru", "sk", "sr",
32
- "sv", "th", "tr", "uk", "vi", "zh-CN", "zh-TW"
33
- ].sort
30
+ [ "ar", "az", "bg", "ca", "cs", "da", "de", "en", "es", "et", "eu", "fa", "fi", "fr", "gl", "he", "hi", "hr", "hu",
31
+ "id", "is", "it", "ja", "ko", "lt", "lv", "mk", "ms", "nb", "nl", "pl", "pt", "pt-BR", "ro", "ru", "sk", "sr", "sr-Cyrl",
32
+ "sv", "th", "tr", "uk", "vi", "zh-CN", "zh-TW"].sort
34
33
  end
35
34
 
36
35
  def select msg, elements
@@ -1,5 +1,5 @@
1
1
  module Select2
2
2
  module Rails
3
- VERSION = "4.0.0"
3
+ VERSION = "4.0.1"
4
4
  end
5
5
  end
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Select2 4.0.0
2
+ * Select2 4.0.1
3
3
  * https://select2.github.io
4
4
  *
5
5
  * Released under the MIT license
@@ -30,7 +30,7 @@
30
30
  var S2;(function () { if (!S2 || !S2.requirejs) {
31
31
  if (!S2) { S2 = {}; } else { require = S2; }
32
32
  /**
33
- * @license almond 0.2.9 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
33
+ * @license almond 0.3.1 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
34
34
  * Available via the MIT or new BSD license.
35
35
  * see: http://github.com/jrburke/almond for details
36
36
  */
@@ -75,12 +75,6 @@ var requirejs, require, define;
75
75
  //otherwise, assume it is a top-level require that will
76
76
  //be relative to baseUrl in the end.
77
77
  if (baseName) {
78
- //Convert baseName to array, and lop off the last part,
79
- //so that . matches that "directory" and not name of the baseName's
80
- //module. For instance, baseName of "one/two/three", maps to
81
- //"one/two/three.js", but we want the directory, "one/two" for
82
- //this normalization.
83
- baseParts = baseParts.slice(0, baseParts.length - 1);
84
78
  name = name.split('/');
85
79
  lastIndex = name.length - 1;
86
80
 
@@ -89,7 +83,11 @@ var requirejs, require, define;
89
83
  name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
90
84
  }
91
85
 
92
- name = baseParts.concat(name);
86
+ //Lop off the last part of baseParts, so that . matches the
87
+ //"directory" and not name of the baseName's module. For instance,
88
+ //baseName of "one/two/three", maps to "one/two/three.js", but we
89
+ //want the directory, "one/two" for this normalization.
90
+ name = baseParts.slice(0, baseParts.length - 1).concat(name);
93
91
 
94
92
  //start trimDots
95
93
  for (i = 0; i < name.length; i += 1) {
@@ -181,7 +179,15 @@ var requirejs, require, define;
181
179
  //A version of a require function that passes a moduleName
182
180
  //value for items that may need to
183
181
  //look up paths relative to the moduleName
184
- return req.apply(undef, aps.call(arguments, 0).concat([relName, forceSync]));
182
+ var args = aps.call(arguments, 0);
183
+
184
+ //If first arg is not require('string'), and there is only
185
+ //one arg, it is the array form without a callback. Insert
186
+ //a null so that the following concat is correct.
187
+ if (typeof args[0] !== 'string' && args.length === 1) {
188
+ args.push(null);
189
+ }
190
+ return req.apply(undef, args.concat([relName, forceSync]));
185
191
  };
186
192
  }
187
193
 
@@ -431,6 +437,9 @@ var requirejs, require, define;
431
437
  requirejs._defined = defined;
432
438
 
433
439
  define = function (name, deps, callback) {
440
+ if (typeof name !== 'string') {
441
+ throw new Error('See almond README: incorrect module build, no module name');
442
+ }
434
443
 
435
444
  //This module may not have dependencies
436
445
  if (!deps.splice) {
@@ -773,7 +782,8 @@ S2.define('select2/results',[
773
782
  this.hideLoading();
774
783
 
775
784
  var $message = $(
776
- '<li role="treeitem" class="select2-results__option"></li>'
785
+ '<li role="treeitem" aria-live="assertive"' +
786
+ ' class="select2-results__option"></li>'
777
787
  );
778
788
 
779
789
  var message = this.options.get('translations').get(params.message);
@@ -784,9 +794,15 @@ S2.define('select2/results',[
784
794
  )
785
795
  );
786
796
 
797
+ $message[0].className += ' select2-results__message';
798
+
787
799
  this.$results.append($message);
788
800
  };
789
801
 
802
+ Results.prototype.hideMessages = function () {
803
+ this.$results.find('.select2-results__message').remove();
804
+ };
805
+
790
806
  Results.prototype.append = function (data) {
791
807
  this.hideLoading();
792
808
 
@@ -986,6 +1002,7 @@ S2.define('select2/results',[
986
1002
  });
987
1003
 
988
1004
  container.on('query', function (params) {
1005
+ self.hideMessages();
989
1006
  self.showLoading(params);
990
1007
  });
991
1008
 
@@ -1041,7 +1058,7 @@ S2.define('select2/results',[
1041
1058
  var data = $highlighted.data('data');
1042
1059
 
1043
1060
  if ($highlighted.attr('aria-selected') == 'true') {
1044
- self.trigger('close');
1061
+ self.trigger('close', {});
1045
1062
  } else {
1046
1063
  self.trigger('select', {
1047
1064
  data: data
@@ -1163,7 +1180,7 @@ S2.define('select2/results',[
1163
1180
  data: data
1164
1181
  });
1165
1182
  } else {
1166
- self.trigger('close');
1183
+ self.trigger('close', {});
1167
1184
  }
1168
1185
 
1169
1186
  return;
@@ -1229,7 +1246,7 @@ S2.define('select2/results',[
1229
1246
  var template = this.options.get('templateResult');
1230
1247
  var escapeMarkup = this.options.get('escapeMarkup');
1231
1248
 
1232
- var content = template(result);
1249
+ var content = template(result, container);
1233
1250
 
1234
1251
  if (content == null) {
1235
1252
  container.style.display = 'none';
@@ -1286,7 +1303,7 @@ S2.define('select2/selection/base',[
1286
1303
  BaseSelection.prototype.render = function () {
1287
1304
  var $selection = $(
1288
1305
  '<span class="select2-selection" role="combobox" ' +
1289
- 'aria-autocomplete="list" aria-haspopup="true" aria-expanded="false">' +
1306
+ ' aria-haspopup="true" aria-expanded="false">' +
1290
1307
  '</span>'
1291
1308
  );
1292
1309
 
@@ -1319,7 +1336,7 @@ S2.define('select2/selection/base',[
1319
1336
  });
1320
1337
 
1321
1338
  this.$selection.on('blur', function (evt) {
1322
- self.trigger('blur', evt);
1339
+ self._handleBlur(evt);
1323
1340
  });
1324
1341
 
1325
1342
  this.$selection.on('keydown', function (evt) {
@@ -1366,6 +1383,24 @@ S2.define('select2/selection/base',[
1366
1383
  });
1367
1384
  };
1368
1385
 
1386
+ BaseSelection.prototype._handleBlur = function (evt) {
1387
+ var self = this;
1388
+
1389
+ // This needs to be delayed as the active element is the body when the tab
1390
+ // key is pressed, possibly along with others.
1391
+ window.setTimeout(function () {
1392
+ // Don't trigger `blur` if the focus is still in the selection
1393
+ if (
1394
+ (document.activeElement == self.$selection[0]) ||
1395
+ ($.contains(self.$selection[0], document.activeElement))
1396
+ ) {
1397
+ return;
1398
+ }
1399
+
1400
+ self.trigger('blur', evt);
1401
+ }, 1);
1402
+ };
1403
+
1369
1404
  BaseSelection.prototype._attachCloseHandler = function (container) {
1370
1405
  var self = this;
1371
1406
 
@@ -1475,11 +1510,11 @@ S2.define('select2/selection/single',[
1475
1510
  this.$selection.find('.select2-selection__rendered').empty();
1476
1511
  };
1477
1512
 
1478
- SingleSelection.prototype.display = function (data) {
1513
+ SingleSelection.prototype.display = function (data, container) {
1479
1514
  var template = this.options.get('templateSelection');
1480
1515
  var escapeMarkup = this.options.get('escapeMarkup');
1481
1516
 
1482
- return escapeMarkup(template(data));
1517
+ return escapeMarkup(template(data, container));
1483
1518
  };
1484
1519
 
1485
1520
  SingleSelection.prototype.selectionContainer = function () {
@@ -1494,9 +1529,9 @@ S2.define('select2/selection/single',[
1494
1529
 
1495
1530
  var selection = data[0];
1496
1531
 
1497
- var formatted = this.display(selection);
1498
-
1499
1532
  var $rendered = this.$selection.find('.select2-selection__rendered');
1533
+ var formatted = this.display(selection, $rendered);
1534
+
1500
1535
  $rendered.empty().append(formatted);
1501
1536
  $rendered.prop('title', selection.title || selection.text);
1502
1537
  };
@@ -1538,29 +1573,37 @@ S2.define('select2/selection/multiple',[
1538
1573
  });
1539
1574
  });
1540
1575
 
1541
- this.$selection.on('click', '.select2-selection__choice__remove',
1576
+ this.$selection.on(
1577
+ 'click',
1578
+ '.select2-selection__choice__remove',
1542
1579
  function (evt) {
1543
- var $remove = $(this);
1544
- var $selection = $remove.parent();
1580
+ // Ignore the event if it is disabled
1581
+ if (self.options.get('disabled')) {
1582
+ return;
1583
+ }
1545
1584
 
1546
- var data = $selection.data('data');
1585
+ var $remove = $(this);
1586
+ var $selection = $remove.parent();
1547
1587
 
1548
- self.trigger('unselect', {
1549
- originalEvent: evt,
1550
- data: data
1551
- });
1552
- });
1588
+ var data = $selection.data('data');
1589
+
1590
+ self.trigger('unselect', {
1591
+ originalEvent: evt,
1592
+ data: data
1593
+ });
1594
+ }
1595
+ );
1553
1596
  };
1554
1597
 
1555
1598
  MultipleSelection.prototype.clear = function () {
1556
1599
  this.$selection.find('.select2-selection__rendered').empty();
1557
1600
  };
1558
1601
 
1559
- MultipleSelection.prototype.display = function (data) {
1602
+ MultipleSelection.prototype.display = function (data, container) {
1560
1603
  var template = this.options.get('templateSelection');
1561
1604
  var escapeMarkup = this.options.get('escapeMarkup');
1562
1605
 
1563
- return escapeMarkup(template(data));
1606
+ return escapeMarkup(template(data, container));
1564
1607
  };
1565
1608
 
1566
1609
  MultipleSelection.prototype.selectionContainer = function () {
@@ -1587,8 +1630,8 @@ S2.define('select2/selection/multiple',[
1587
1630
  for (var d = 0; d < data.length; d++) {
1588
1631
  var selection = data[d];
1589
1632
 
1590
- var formatted = this.display(selection);
1591
1633
  var $selection = this.selectionContainer();
1634
+ var formatted = this.display(selection, $selection);
1592
1635
 
1593
1636
  $selection.append(formatted);
1594
1637
  $selection.prop('title', selection.title || selection.text);
@@ -1720,7 +1763,7 @@ S2.define('select2/selection/allowClear',[
1720
1763
 
1721
1764
  this.$element.val(this.placeholder.id).trigger('change');
1722
1765
 
1723
- this.trigger('toggle');
1766
+ this.trigger('toggle', {});
1724
1767
  };
1725
1768
 
1726
1769
  AllowClear.prototype._handleKeyboardClear = function (_, evt, container) {
@@ -1768,7 +1811,7 @@ S2.define('select2/selection/search',[
1768
1811
  '<li class="select2-search select2-search--inline">' +
1769
1812
  '<input class="select2-search__field" type="search" tabindex="-1"' +
1770
1813
  ' autocomplete="off" autocorrect="off" autocapitalize="off"' +
1771
- ' spellcheck="false" role="textbox" />' +
1814
+ ' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
1772
1815
  '</li>'
1773
1816
  );
1774
1817
 
@@ -1777,6 +1820,8 @@ S2.define('select2/selection/search',[
1777
1820
 
1778
1821
  var $rendered = decorated.call(this);
1779
1822
 
1823
+ this._transferTabIndex();
1824
+
1780
1825
  return $rendered;
1781
1826
  };
1782
1827
 
@@ -1786,32 +1831,39 @@ S2.define('select2/selection/search',[
1786
1831
  decorated.call(this, container, $container);
1787
1832
 
1788
1833
  container.on('open', function () {
1789
- self.$search.attr('tabindex', 0);
1790
-
1791
- self.$search.focus();
1834
+ self.$search.trigger('focus');
1792
1835
  });
1793
1836
 
1794
1837
  container.on('close', function () {
1795
- self.$search.attr('tabindex', -1);
1796
-
1797
1838
  self.$search.val('');
1798
- self.$search.focus();
1839
+ self.$search.removeAttr('aria-activedescendant');
1840
+ self.$search.trigger('focus');
1799
1841
  });
1800
1842
 
1801
1843
  container.on('enable', function () {
1802
1844
  self.$search.prop('disabled', false);
1845
+
1846
+ self._transferTabIndex();
1803
1847
  });
1804
1848
 
1805
1849
  container.on('disable', function () {
1806
1850
  self.$search.prop('disabled', true);
1807
1851
  });
1808
1852
 
1853
+ container.on('focus', function (evt) {
1854
+ self.$search.trigger('focus');
1855
+ });
1856
+
1857
+ container.on('results:focus', function (params) {
1858
+ self.$search.attr('aria-activedescendant', params.id);
1859
+ });
1860
+
1809
1861
  this.$selection.on('focusin', '.select2-search--inline', function (evt) {
1810
1862
  self.trigger('focus', evt);
1811
1863
  });
1812
1864
 
1813
1865
  this.$selection.on('focusout', '.select2-search--inline', function (evt) {
1814
- self.trigger('blur', evt);
1866
+ self._handleBlur(evt);
1815
1867
  });
1816
1868
 
1817
1869
  this.$selection.on('keydown', '.select2-search--inline', function (evt) {
@@ -1837,18 +1889,73 @@ S2.define('select2/selection/search',[
1837
1889
  }
1838
1890
  });
1839
1891
 
1892
+ // Try to detect the IE version should the `documentMode` property that
1893
+ // is stored on the document. This is only implemented in IE and is
1894
+ // slightly cleaner than doing a user agent check.
1895
+ // This property is not available in Edge, but Edge also doesn't have
1896
+ // this bug.
1897
+ var msie = document.documentMode;
1898
+ var disableInputEvents = msie && msie <= 11;
1899
+
1840
1900
  // Workaround for browsers which do not support the `input` event
1841
1901
  // This will prevent double-triggering of events for browsers which support
1842
1902
  // both the `keyup` and `input` events.
1843
- this.$selection.on('input', '.select2-search--inline', function (evt) {
1844
- // Unbind the duplicated `keyup` event
1845
- self.$selection.off('keyup.search');
1846
- });
1903
+ this.$selection.on(
1904
+ 'input.searchcheck',
1905
+ '.select2-search--inline',
1906
+ function (evt) {
1907
+ // IE will trigger the `input` event when a placeholder is used on a
1908
+ // search box. To get around this issue, we are forced to ignore all
1909
+ // `input` events in IE and keep using `keyup`.
1910
+ if (disableInputEvents) {
1911
+ self.$selection.off('input.search input.searchcheck');
1912
+ return;
1913
+ }
1847
1914
 
1848
- this.$selection.on('keyup.search input', '.select2-search--inline',
1849
- function (evt) {
1850
- self.handleSearch(evt);
1851
- });
1915
+ // Unbind the duplicated `keyup` event
1916
+ self.$selection.off('keyup.search');
1917
+ }
1918
+ );
1919
+
1920
+ this.$selection.on(
1921
+ 'keyup.search input.search',
1922
+ '.select2-search--inline',
1923
+ function (evt) {
1924
+ // IE will trigger the `input` event when a placeholder is used on a
1925
+ // search box. To get around this issue, we are forced to ignore all
1926
+ // `input` events in IE and keep using `keyup`.
1927
+ if (disableInputEvents && evt.type === 'input') {
1928
+ self.$selection.off('input.search input.searchcheck');
1929
+ return;
1930
+ }
1931
+
1932
+ var key = evt.which;
1933
+
1934
+ // We can freely ignore events from modifier keys
1935
+ if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) {
1936
+ return;
1937
+ }
1938
+
1939
+ // Tabbing will be handled during the `keydown` phase
1940
+ if (key == KEYS.TAB) {
1941
+ return;
1942
+ }
1943
+
1944
+ self.handleSearch(evt);
1945
+ }
1946
+ );
1947
+ };
1948
+
1949
+ /**
1950
+ * This method will transfer the tabindex attribute from the rendered
1951
+ * selection to the search box. This allows for the search box to be used as
1952
+ * the primary focus instead of the selection container.
1953
+ *
1954
+ * @private
1955
+ */
1956
+ Search.prototype._transferTabIndex = function (decorated) {
1957
+ this.$search.attr('tabindex', this.$selection.attr('tabindex'));
1958
+ this.$selection.attr('tabindex', '-1');
1852
1959
  };
1853
1960
 
1854
1961
  Search.prototype.createPlaceholder = function (decorated, placeholder) {
@@ -1856,6 +1963,8 @@ S2.define('select2/selection/search',[
1856
1963
  };
1857
1964
 
1858
1965
  Search.prototype.update = function (decorated, data) {
1966
+ var searchHadFocus = this.$search[0] == document.activeElement;
1967
+
1859
1968
  this.$search.attr('placeholder', '');
1860
1969
 
1861
1970
  decorated.call(this, data);
@@ -1864,6 +1973,9 @@ S2.define('select2/selection/search',[
1864
1973
  .append(this.$searchContainer);
1865
1974
 
1866
1975
  this.resizeSearch();
1976
+ if (searchHadFocus) {
1977
+ this.$search.focus();
1978
+ }
1867
1979
  };
1868
1980
 
1869
1981
  Search.prototype.handleSearch = function () {
@@ -1885,9 +1997,8 @@ S2.define('select2/selection/search',[
1885
1997
  data: item
1886
1998
  });
1887
1999
 
1888
- this.trigger('open');
1889
-
1890
- this.$search.val(item.text + ' ');
2000
+ this.$search.val(item.text);
2001
+ this.handleSearch();
1891
2002
  };
1892
2003
 
1893
2004
  Search.prototype.resizeSearch = function () {
@@ -3223,7 +3334,7 @@ S2.define('select2/data/array',[
3223
3334
  var existingData = this.item($existingOption);
3224
3335
  var newData = $.extend(true, {}, existingData, item);
3225
3336
 
3226
- var $newOption = this.option(existingData);
3337
+ var $newOption = this.option(newData);
3227
3338
 
3228
3339
  $existingOption.replaceWith($newOption);
3229
3340
 
@@ -3259,7 +3370,7 @@ S2.define('select2/data/ajax',[
3259
3370
  this.processResults = this.ajaxOptions.processResults;
3260
3371
  }
3261
3372
 
3262
- ArrayAdapter.__super__.constructor.call(this, $element, options);
3373
+ AjaxAdapter.__super__.constructor.call(this, $element, options);
3263
3374
  }
3264
3375
 
3265
3376
  Utils.Extend(AjaxAdapter, ArrayAdapter);
@@ -3267,9 +3378,9 @@ S2.define('select2/data/ajax',[
3267
3378
  AjaxAdapter.prototype._applyDefaults = function (options) {
3268
3379
  var defaults = {
3269
3380
  data: function (params) {
3270
- return {
3381
+ return $.extend({}, params, {
3271
3382
  q: params.term
3272
- };
3383
+ });
3273
3384
  },
3274
3385
  transport: function (params, success, failure) {
3275
3386
  var $request = $.ajax(params);
@@ -3306,11 +3417,11 @@ S2.define('select2/data/ajax',[
3306
3417
  }, this.ajaxOptions);
3307
3418
 
3308
3419
  if (typeof options.url === 'function') {
3309
- options.url = options.url(params);
3420
+ options.url = options.url.call(this.$element, params);
3310
3421
  }
3311
3422
 
3312
3423
  if (typeof options.data === 'function') {
3313
- options.data = options.data(params);
3424
+ options.data = options.data.call(this.$element, params);
3314
3425
  }
3315
3426
 
3316
3427
  function request () {
@@ -3493,7 +3604,9 @@ S2.define('select2/data/tokenizer',[
3493
3604
  var self = this;
3494
3605
 
3495
3606
  function select (data) {
3496
- self.select(data);
3607
+ self.trigger('select', {
3608
+ data: data
3609
+ });
3497
3610
  }
3498
3611
 
3499
3612
  params.term = params.term || '';
@@ -3541,6 +3654,11 @@ S2.define('select2/data/tokenizer',[
3541
3654
 
3542
3655
  var data = createTag(partParams);
3543
3656
 
3657
+ if (data == null) {
3658
+ i++;
3659
+ continue;
3660
+ }
3661
+
3544
3662
  callback(data);
3545
3663
 
3546
3664
  // Reset the term to not include the tokenized portion
@@ -3678,6 +3796,10 @@ S2.define('select2/dropdown',[
3678
3796
  return $dropdown;
3679
3797
  };
3680
3798
 
3799
+ Dropdown.prototype.bind = function () {
3800
+ // Should be implemented in subclasses
3801
+ };
3802
+
3681
3803
  Dropdown.prototype.position = function ($dropdown, $container) {
3682
3804
  // Should be implmented in subclasses
3683
3805
  };
@@ -3904,7 +4026,9 @@ S2.define('select2/dropdown/infiniteScroll',[
3904
4026
 
3905
4027
  InfiniteScroll.prototype.createLoadingMore = function () {
3906
4028
  var $option = $(
3907
- '<li class="option load-more" role="treeitem"></li>'
4029
+ '<li ' +
4030
+ 'class="select2-results__option select2-results__option--load-more"' +
4031
+ 'role="treeitem" aria-disabled="true"></li>'
3908
4032
  );
3909
4033
 
3910
4034
  var message = this.options.get('translations').get('loadingMore');
@@ -3922,7 +4046,7 @@ S2.define('select2/dropdown/attachBody',[
3922
4046
  '../utils'
3923
4047
  ], function ($, Utils) {
3924
4048
  function AttachBody (decorated, $element, options) {
3925
- this.$dropdownParent = options.get('dropdownParent') || document.body;
4049
+ this.$dropdownParent = options.get('dropdownParent') || $(document.body);
3926
4050
 
3927
4051
  decorated.call(this, $element, options);
3928
4052
  }
@@ -3963,6 +4087,12 @@ S2.define('select2/dropdown/attachBody',[
3963
4087
  });
3964
4088
  };
3965
4089
 
4090
+ AttachBody.prototype.destroy = function (decorated) {
4091
+ decorated.call(this);
4092
+
4093
+ this.$dropdownContainer.remove();
4094
+ };
4095
+
3966
4096
  AttachBody.prototype.position = function (decorated, $dropdown, $container) {
3967
4097
  // Clone all of the container classes
3968
4098
  $dropdown.attr('class', $container.attr('class'));
@@ -3993,7 +4123,8 @@ S2.define('select2/dropdown/attachBody',[
3993
4123
  this.$dropdownContainer.detach();
3994
4124
  };
3995
4125
 
3996
- AttachBody.prototype._attachPositioningHandler = function (container) {
4126
+ AttachBody.prototype._attachPositioningHandler =
4127
+ function (decorated, container) {
3997
4128
  var self = this;
3998
4129
 
3999
4130
  var scrollEvent = 'scroll.select2.' + container.id;
@@ -4020,7 +4151,8 @@ S2.define('select2/dropdown/attachBody',[
4020
4151
  });
4021
4152
  };
4022
4153
 
4023
- AttachBody.prototype._detachPositioningHandler = function (container) {
4154
+ AttachBody.prototype._detachPositioningHandler =
4155
+ function (decorated, container) {
4024
4156
  var scrollEvent = 'scroll.select2.' + container.id;
4025
4157
  var resizeEvent = 'resize.select2.' + container.id;
4026
4158
  var orientationEvent = 'orientationchange.select2.' + container.id;
@@ -4068,6 +4200,14 @@ S2.define('select2/dropdown/attachBody',[
4068
4200
  top: container.bottom
4069
4201
  };
4070
4202
 
4203
+ // Fix positioning with static parents
4204
+ if (this.$dropdownParent[0].style.position !== 'static') {
4205
+ var parentOffset = this.$dropdownParent.offset();
4206
+
4207
+ css.top -= parentOffset.top;
4208
+ css.left -= parentOffset.left;
4209
+ }
4210
+
4071
4211
  if (!isCurrentlyAbove && !isCurrentlyBelow) {
4072
4212
  newDirection = 'below';
4073
4213
  }
@@ -4096,8 +4236,6 @@ S2.define('select2/dropdown/attachBody',[
4096
4236
  };
4097
4237
 
4098
4238
  AttachBody.prototype._resizeDropdown = function () {
4099
- this.$dropdownContainer.width();
4100
-
4101
4239
  var css = {
4102
4240
  width: this.$container.outerWidth(false) + 'px'
4103
4241
  };
@@ -4178,12 +4316,23 @@ S2.define('select2/dropdown/selectOnClose',[
4178
4316
  SelectOnClose.prototype._handleSelectOnClose = function () {
4179
4317
  var $highlightedResults = this.getHighlightedResults();
4180
4318
 
4319
+ // Only select highlighted results
4181
4320
  if ($highlightedResults.length < 1) {
4182
4321
  return;
4183
4322
  }
4184
4323
 
4324
+ var data = $highlightedResults.data('data');
4325
+
4326
+ // Don't re-select already selected resulte
4327
+ if (
4328
+ (data.element != null && data.element.selected) ||
4329
+ (data.element == null && data.selected)
4330
+ ) {
4331
+ return;
4332
+ }
4333
+
4185
4334
  this.trigger('select', {
4186
- data: $highlightedResults.data('data')
4335
+ data: data
4187
4336
  });
4188
4337
  };
4189
4338
 
@@ -4217,7 +4366,7 @@ S2.define('select2/dropdown/closeOnSelect',[
4217
4366
  return;
4218
4367
  }
4219
4368
 
4220
- this.trigger('close');
4369
+ this.trigger('close', {});
4221
4370
  };
4222
4371
 
4223
4372
  return CloseOnSelect;
@@ -4868,8 +5017,8 @@ S2.define('select2/core',[
4868
5017
 
4869
5018
  // Hide the original select
4870
5019
  $element.addClass('select2-hidden-accessible');
4871
- $element.attr('aria-hidden', 'true');
4872
-
5020
+ $element.attr('aria-hidden', 'true');
5021
+
4873
5022
  // Synchronize any monitored attributes
4874
5023
  this._syncAttributes();
4875
5024
 
@@ -5004,12 +5153,16 @@ S2.define('select2/core',[
5004
5153
 
5005
5154
  Select2.prototype._registerSelectionEvents = function () {
5006
5155
  var self = this;
5007
- var nonRelayEvents = ['toggle'];
5156
+ var nonRelayEvents = ['toggle', 'focus'];
5008
5157
 
5009
5158
  this.selection.on('toggle', function () {
5010
5159
  self.toggleDropdown();
5011
5160
  });
5012
5161
 
5162
+ this.selection.on('focus', function (params) {
5163
+ self.focus(params);
5164
+ });
5165
+
5013
5166
  this.selection.on('*', function (name, params) {
5014
5167
  if ($.inArray(name, nonRelayEvents) !== -1) {
5015
5168
  return;
@@ -5054,17 +5207,13 @@ S2.define('select2/core',[
5054
5207
  self.$container.addClass('select2-container--disabled');
5055
5208
  });
5056
5209
 
5057
- this.on('focus', function () {
5058
- self.$container.addClass('select2-container--focus');
5059
- });
5060
-
5061
5210
  this.on('blur', function () {
5062
5211
  self.$container.removeClass('select2-container--focus');
5063
5212
  });
5064
5213
 
5065
5214
  this.on('query', function (params) {
5066
5215
  if (!self.isOpen()) {
5067
- self.trigger('open');
5216
+ self.trigger('open', {});
5068
5217
  }
5069
5218
 
5070
5219
  this.dataAdapter.query(params, function (data) {
@@ -5088,30 +5237,31 @@ S2.define('select2/core',[
5088
5237
  var key = evt.which;
5089
5238
 
5090
5239
  if (self.isOpen()) {
5091
- if (key === KEYS.ENTER) {
5092
- self.trigger('results:select');
5240
+ if (key === KEYS.ESC || key === KEYS.TAB ||
5241
+ (key === KEYS.UP && evt.altKey)) {
5242
+ self.close();
5243
+
5244
+ evt.preventDefault();
5245
+ } else if (key === KEYS.ENTER) {
5246
+ self.trigger('results:select', {});
5093
5247
 
5094
5248
  evt.preventDefault();
5095
5249
  } else if ((key === KEYS.SPACE && evt.ctrlKey)) {
5096
- self.trigger('results:toggle');
5250
+ self.trigger('results:toggle', {});
5097
5251
 
5098
5252
  evt.preventDefault();
5099
5253
  } else if (key === KEYS.UP) {
5100
- self.trigger('results:previous');
5254
+ self.trigger('results:previous', {});
5101
5255
 
5102
5256
  evt.preventDefault();
5103
5257
  } else if (key === KEYS.DOWN) {
5104
- self.trigger('results:next');
5105
-
5106
- evt.preventDefault();
5107
- } else if (key === KEYS.ESC || key === KEYS.TAB) {
5108
- self.close();
5258
+ self.trigger('results:next', {});
5109
5259
 
5110
5260
  evt.preventDefault();
5111
5261
  }
5112
5262
  } else {
5113
5263
  if (key === KEYS.ENTER || key === KEYS.SPACE ||
5114
- ((key === KEYS.DOWN || key === KEYS.UP) && evt.altKey)) {
5264
+ (key === KEYS.DOWN && evt.altKey)) {
5115
5265
  self.open();
5116
5266
 
5117
5267
  evt.preventDefault();
@@ -5128,9 +5278,9 @@ S2.define('select2/core',[
5128
5278
  this.close();
5129
5279
  }
5130
5280
 
5131
- this.trigger('disable');
5281
+ this.trigger('disable', {});
5132
5282
  } else {
5133
- this.trigger('enable');
5283
+ this.trigger('enable', {});
5134
5284
  }
5135
5285
  };
5136
5286
 
@@ -5147,6 +5297,10 @@ S2.define('select2/core',[
5147
5297
  'unselect': 'unselecting'
5148
5298
  };
5149
5299
 
5300
+ if (args === undefined) {
5301
+ args = {};
5302
+ }
5303
+
5150
5304
  if (name in preTriggerMap) {
5151
5305
  var preTriggerName = preTriggerMap[name];
5152
5306
  var preTriggerArgs = {
@@ -5185,8 +5339,6 @@ S2.define('select2/core',[
5185
5339
  }
5186
5340
 
5187
5341
  this.trigger('query', {});
5188
-
5189
- this.trigger('open');
5190
5342
  };
5191
5343
 
5192
5344
  Select2.prototype.close = function () {
@@ -5194,13 +5346,27 @@ S2.define('select2/core',[
5194
5346
  return;
5195
5347
  }
5196
5348
 
5197
- this.trigger('close');
5349
+ this.trigger('close', {});
5198
5350
  };
5199
5351
 
5200
5352
  Select2.prototype.isOpen = function () {
5201
5353
  return this.$container.hasClass('select2-container--open');
5202
5354
  };
5203
5355
 
5356
+ Select2.prototype.hasFocus = function () {
5357
+ return this.$container.hasClass('select2-container--focus');
5358
+ };
5359
+
5360
+ Select2.prototype.focus = function (data) {
5361
+ // No need to re-trigger focus events if we are already focused
5362
+ if (this.hasFocus()) {
5363
+ return;
5364
+ }
5365
+
5366
+ this.$container.addClass('select2-container--focus');
5367
+ this.trigger('focus', {});
5368
+ };
5369
+
5204
5370
  Select2.prototype.enable = function (args) {
5205
5371
  if (this.options.get('debug') && window.console && console.warn) {
5206
5372
  console.warn(
@@ -5281,7 +5447,7 @@ S2.define('select2/core',[
5281
5447
  this.$element.attr('tabindex', this.$element.data('old-tabindex'));
5282
5448
 
5283
5449
  this.$element.removeClass('select2-hidden-accessible');
5284
- this.$element.attr('aria-hidden', 'false');
5450
+ this.$element.attr('aria-hidden', 'false');
5285
5451
  this.$element.removeData('select2');
5286
5452
 
5287
5453
  this.dataAdapter.destroy();
@@ -5317,16 +5483,20 @@ S2.define('select2/core',[
5317
5483
  return Select2;
5318
5484
  });
5319
5485
 
5486
+ S2.define('jquery-mousewheel',[
5487
+ 'jquery'
5488
+ ], function ($) {
5489
+ // Used to shim jQuery.mousewheel for non-full builds.
5490
+ return $;
5491
+ });
5492
+
5320
5493
  S2.define('jquery.select2',[
5321
5494
  'jquery',
5322
- 'require',
5495
+ 'jquery-mousewheel',
5323
5496
 
5324
5497
  './select2/core',
5325
5498
  './select2/defaults'
5326
- ], function ($, require, Select2, Defaults) {
5327
- // Force jQuery.mousewheel to be loaded if it hasn't already
5328
- require('jquery.mousewheel');
5329
-
5499
+ ], function ($, _, Select2, Defaults) {
5330
5500
  if ($.fn.select2 == null) {
5331
5501
  // All methods that should return the element
5332
5502
  var thisMethods = ['open', 'close', 'destroy'];
@@ -5336,25 +5506,29 @@ S2.define('jquery.select2',[
5336
5506
 
5337
5507
  if (typeof options === 'object') {
5338
5508
  this.each(function () {
5339
- var instanceOptions = $.extend({}, options, true);
5509
+ var instanceOptions = $.extend(true, {}, options);
5340
5510
 
5341
5511
  var instance = new Select2($(this), instanceOptions);
5342
5512
  });
5343
5513
 
5344
5514
  return this;
5345
5515
  } else if (typeof options === 'string') {
5346
- var instance = this.data('select2');
5516
+ var ret;
5347
5517
 
5348
- if (instance == null && window.console && console.error) {
5349
- console.error(
5350
- 'The select2(\'' + options + '\') method was called on an ' +
5351
- 'element that is not using Select2.'
5352
- );
5353
- }
5518
+ this.each(function () {
5519
+ var instance = $(this).data('select2');
5520
+
5521
+ if (instance == null && window.console && console.error) {
5522
+ console.error(
5523
+ 'The select2(\'' + options + '\') method was called on an ' +
5524
+ 'element that is not using Select2.'
5525
+ );
5526
+ }
5354
5527
 
5355
- var args = Array.prototype.slice.call(arguments, 1);
5528
+ var args = Array.prototype.slice.call(arguments, 1);
5356
5529
 
5357
- var ret = instance[options](args);
5530
+ ret = instance[options].apply(instance, args);
5531
+ });
5358
5532
 
5359
5533
  // Check if we should be returning `this`
5360
5534
  if ($.inArray(options, thisMethods) > -1) {
@@ -5375,13 +5549,6 @@ S2.define('jquery.select2',[
5375
5549
  return Select2;
5376
5550
  });
5377
5551
 
5378
- S2.define('jquery.mousewheel',[
5379
- 'jquery'
5380
- ], function ($) {
5381
- // Used to shim jQuery.mousewheel for non-full builds.
5382
- return $;
5383
- });
5384
-
5385
5552
  // Return the AMD loader configuration so it can be used outside of this file
5386
5553
  return {
5387
5554
  define: S2.define,