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.
This commit is contained in:
parent
ef5c88a6f6
commit
b382fdca9c
20
dist/js/select2.amd.full.js
vendored
20
dist/js/select2.amd.full.js
vendored
@ -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');
|
||||
|
20
dist/js/select2.amd.js
vendored
20
dist/js/select2.amd.js
vendored
@ -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');
|
||||
|
20
dist/js/select2.full.js
vendored
20
dist/js/select2.full.js
vendored
@ -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');
|
||||
|
4
dist/js/select2.full.min.js
vendored
4
dist/js/select2.full.min.js
vendored
File diff suppressed because one or more lines are too long
20
dist/js/select2.js
vendored
20
dist/js/select2.js
vendored
@ -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');
|
||||
|
4
dist/js/select2.min.js
vendored
4
dist/js/select2.min.js
vendored
File diff suppressed because one or more lines are too long
12
src/js/select2/core.js
vendored
12
src/js/select2/core.js
vendored
@ -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');
|
||||
|
8
src/js/select2/selection/base.js
vendored
8
src/js/select2/selection/base.js
vendored
@ -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 () {
|
||||
|
@ -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) {
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user