select2-rails 4.0.0 → 4.0.1

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