소스 검색

Clone the `tabindex` from the original select

Previously Select2 would assume that the tab index for the
`<select>` was `0`, which is the browser default.  Now Select2 will
clone the tab index from the original element, and correctly restore
it when it is destroyed or disabled/enabled.

This closes https://github.com/select2/select2/issues/3031.
Kevin Brown 10 년 전
부모
커밋
b382fdca9c

+ 13 - 7
dist/js/select2.amd.full.js

@@ -787,12 +787,16 @@ define('select2/selection/base',[
 
   BaseSelection.prototype.render = function () {
     var $selection = $(
-      '<span class="select2-selection" tabindex="0" role="combobox" ' +
+      '<span class="select2-selection" role="combobox" ' +
       'aria-autocomplete="list" aria-haspopup="true" aria-expanded="false">' +
       '</span>'
     );
 
+    this._tabindex = this.$element.data('old-tabindex') ||
+      this.$element.attr('tabindex') || 0;
+
     $selection.attr('title', this.$element.attr('title'));
+    $selection.attr('tabindex', this._tabindex);
 
     this.$selection = $selection;
 
@@ -843,7 +847,7 @@ define('select2/selection/base',[
     });
 
     container.on('enable', function () {
-      self.$selection.attr('tabindex', '0');
+      self.$selection.attr('tabindex', self._tabindex);
     });
 
     container.on('disable', function () {
@@ -4146,6 +4150,12 @@ define('select2/core',[
 
     Select2.__super__.constructor.call(this);
 
+    // Set up the tabindex
+
+    var tabindex = $element.attr('tabindex') || 0;
+    $element.data('old-tabindex', tabindex);
+    $element.attr('tabindex', '-1');
+
     // Set up containers and adapters
 
     var DataAdapter = this.options.get('dataAdapter');
@@ -4203,10 +4213,6 @@ define('select2/core',[
     // Synchronize any monitored attributes
     this._syncAttributes();
 
-    this._tabindex = $element.attr('tabindex') || 0;
-
-    $element.attr('tabindex', '-1');
-
     $element.data('select2', this);
   };
 
@@ -4595,7 +4601,7 @@ define('select2/core',[
     this._sync = null;
 
     this.$element.off('.select2');
-    this.$element.attr('tabindex', this._tabindex);
+    this.$element.attr('tabindex', this.$element.data('old-tabindex'));
 
     this.$element.show();
     this.$element.removeData('select2');

+ 13 - 7
dist/js/select2.amd.js

@@ -787,12 +787,16 @@ define('select2/selection/base',[
 
   BaseSelection.prototype.render = function () {
     var $selection = $(
-      '<span class="select2-selection" tabindex="0" role="combobox" ' +
+      '<span class="select2-selection" role="combobox" ' +
       'aria-autocomplete="list" aria-haspopup="true" aria-expanded="false">' +
       '</span>'
     );
 
+    this._tabindex = this.$element.data('old-tabindex') ||
+      this.$element.attr('tabindex') || 0;
+
     $selection.attr('title', this.$element.attr('title'));
+    $selection.attr('tabindex', this._tabindex);
 
     this.$selection = $selection;
 
@@ -843,7 +847,7 @@ define('select2/selection/base',[
     });
 
     container.on('enable', function () {
-      self.$selection.attr('tabindex', '0');
+      self.$selection.attr('tabindex', self._tabindex);
     });
 
     container.on('disable', function () {
@@ -4146,6 +4150,12 @@ define('select2/core',[
 
     Select2.__super__.constructor.call(this);
 
+    // Set up the tabindex
+
+    var tabindex = $element.attr('tabindex') || 0;
+    $element.data('old-tabindex', tabindex);
+    $element.attr('tabindex', '-1');
+
     // Set up containers and adapters
 
     var DataAdapter = this.options.get('dataAdapter');
@@ -4203,10 +4213,6 @@ define('select2/core',[
     // Synchronize any monitored attributes
     this._syncAttributes();
 
-    this._tabindex = $element.attr('tabindex') || 0;
-
-    $element.attr('tabindex', '-1');
-
     $element.data('select2', this);
   };
 
@@ -4595,7 +4601,7 @@ define('select2/core',[
     this._sync = null;
 
     this.$element.off('.select2');
-    this.$element.attr('tabindex', this._tabindex);
+    this.$element.attr('tabindex', this.$element.data('old-tabindex'));
 
     this.$element.show();
     this.$element.removeData('select2');

+ 13 - 7
dist/js/select2.full.js

@@ -1226,12 +1226,16 @@ define('select2/selection/base',[
 
   BaseSelection.prototype.render = function () {
     var $selection = $(
-      '<span class="select2-selection" tabindex="0" role="combobox" ' +
+      '<span class="select2-selection" role="combobox" ' +
       'aria-autocomplete="list" aria-haspopup="true" aria-expanded="false">' +
       '</span>'
     );
 
+    this._tabindex = this.$element.data('old-tabindex') ||
+      this.$element.attr('tabindex') || 0;
+
     $selection.attr('title', this.$element.attr('title'));
+    $selection.attr('tabindex', this._tabindex);
 
     this.$selection = $selection;
 
@@ -1282,7 +1286,7 @@ define('select2/selection/base',[
     });
 
     container.on('enable', function () {
-      self.$selection.attr('tabindex', '0');
+      self.$selection.attr('tabindex', self._tabindex);
     });
 
     container.on('disable', function () {
@@ -4585,6 +4589,12 @@ define('select2/core',[
 
     Select2.__super__.constructor.call(this);
 
+    // Set up the tabindex
+
+    var tabindex = $element.attr('tabindex') || 0;
+    $element.data('old-tabindex', tabindex);
+    $element.attr('tabindex', '-1');
+
     // Set up containers and adapters
 
     var DataAdapter = this.options.get('dataAdapter');
@@ -4642,10 +4652,6 @@ define('select2/core',[
     // Synchronize any monitored attributes
     this._syncAttributes();
 
-    this._tabindex = $element.attr('tabindex') || 0;
-
-    $element.attr('tabindex', '-1');
-
     $element.data('select2', this);
   };
 
@@ -5034,7 +5040,7 @@ define('select2/core',[
     this._sync = null;
 
     this.$element.off('.select2');
-    this.$element.attr('tabindex', this._tabindex);
+    this.$element.attr('tabindex', this.$element.data('old-tabindex'));
 
     this.$element.show();
     this.$element.removeData('select2');

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
dist/js/select2.full.min.js


+ 13 - 7
dist/js/select2.js

@@ -1226,12 +1226,16 @@ define('select2/selection/base',[
 
   BaseSelection.prototype.render = function () {
     var $selection = $(
-      '<span class="select2-selection" tabindex="0" role="combobox" ' +
+      '<span class="select2-selection" role="combobox" ' +
       'aria-autocomplete="list" aria-haspopup="true" aria-expanded="false">' +
       '</span>'
     );
 
+    this._tabindex = this.$element.data('old-tabindex') ||
+      this.$element.attr('tabindex') || 0;
+
     $selection.attr('title', this.$element.attr('title'));
+    $selection.attr('tabindex', this._tabindex);
 
     this.$selection = $selection;
 
@@ -1282,7 +1286,7 @@ define('select2/selection/base',[
     });
 
     container.on('enable', function () {
-      self.$selection.attr('tabindex', '0');
+      self.$selection.attr('tabindex', self._tabindex);
     });
 
     container.on('disable', function () {
@@ -4585,6 +4589,12 @@ define('select2/core',[
 
     Select2.__super__.constructor.call(this);
 
+    // Set up the tabindex
+
+    var tabindex = $element.attr('tabindex') || 0;
+    $element.data('old-tabindex', tabindex);
+    $element.attr('tabindex', '-1');
+
     // Set up containers and adapters
 
     var DataAdapter = this.options.get('dataAdapter');
@@ -4642,10 +4652,6 @@ define('select2/core',[
     // Synchronize any monitored attributes
     this._syncAttributes();
 
-    this._tabindex = $element.attr('tabindex') || 0;
-
-    $element.attr('tabindex', '-1');
-
     $element.data('select2', this);
   };
 
@@ -5034,7 +5040,7 @@ define('select2/core',[
     this._sync = null;
 
     this.$element.off('.select2');
-    this.$element.attr('tabindex', this._tabindex);
+    this.$element.attr('tabindex', this.$element.data('old-tabindex'));
 
     this.$element.show();
     this.$element.removeData('select2');

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
dist/js/select2.min.js


+ 7 - 5
src/js/select2/core.js

@@ -19,6 +19,12 @@ define([
 
     Select2.__super__.constructor.call(this);
 
+    // Set up the tabindex
+
+    var tabindex = $element.attr('tabindex') || 0;
+    $element.data('old-tabindex', tabindex);
+    $element.attr('tabindex', '-1');
+
     // Set up containers and adapters
 
     var DataAdapter = this.options.get('dataAdapter');
@@ -76,10 +82,6 @@ define([
     // Synchronize any monitored attributes
     this._syncAttributes();
 
-    this._tabindex = $element.attr('tabindex') || 0;
-
-    $element.attr('tabindex', '-1');
-
     $element.data('select2', this);
   };
 
@@ -468,7 +470,7 @@ define([
     this._sync = null;
 
     this.$element.off('.select2');
-    this.$element.attr('tabindex', this._tabindex);
+    this.$element.attr('tabindex', this.$element.data('old-tabindex'));
 
     this.$element.show();
     this.$element.removeData('select2');

+ 6 - 2
src/js/select2/selection/base.js

@@ -14,12 +14,16 @@ define([
 
   BaseSelection.prototype.render = function () {
     var $selection = $(
-      '<span class="select2-selection" tabindex="0" role="combobox" ' +
+      '<span class="select2-selection" role="combobox" ' +
       'aria-autocomplete="list" aria-haspopup="true" aria-expanded="false">' +
       '</span>'
     );
 
+    this._tabindex = this.$element.data('old-tabindex') ||
+      this.$element.attr('tabindex') || 0;
+
     $selection.attr('title', this.$element.attr('title'));
+    $selection.attr('tabindex', this._tabindex);
 
     this.$selection = $selection;
 
@@ -70,7 +74,7 @@ define([
     });
 
     container.on('enable', function () {
-      self.$selection.attr('tabindex', '0');
+      self.$selection.attr('tabindex', self._tabindex);
     });
 
     container.on('disable', function () {

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

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

+ 3 - 3
tests/a11y/selection.html

@@ -7,19 +7,19 @@
   <body>
     <div id="qunit"></div>
     <div id="qunit-fixture">
-      <select class="single" title="This is an example title">
+      <select class="single" title="This is an example title" tabindex="0">
         <option value="default">Default</option>
         <option value="1">One</option>
         <option>2</option>
       </select>
 
-      <select class="multiple" multiple="multiple" title="One more example title">
+      <select class="multiple" multiple="multiple" title="One more example title" tabindex="0">
         <option value="default">Default</option>
         <option value="1">One</option>
         <option>2</option>
       </select>
 
-      <select class="groups">
+      <select class="groups" tabindex="0">
         <optgroup label="Test">
           <option value="one">One</option>
           <option value="two">Two</option>

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.