1
0
mirror of synced 2025-03-10 14:46:10 +03:00

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:
Kevin Brown 2015-02-13 23:57:18 -05:00
parent ef5c88a6f6
commit b382fdca9c
10 changed files with 105 additions and 42 deletions

View File

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

View File

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

View File

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

File diff suppressed because one or more lines are too long

20
dist/js/select2.js vendored
View File

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

File diff suppressed because one or more lines are too long

View File

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

View File

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

View File

@ -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'); module('Accessibility - Single');
test('aria-labelledby should match the rendered container', function (assert) { test('aria-labelledby should match the rendered container', function (assert) {

View File

@ -7,19 +7,19 @@
<body> <body>
<div id="qunit"></div> <div id="qunit"></div>
<div id="qunit-fixture"> <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="default">Default</option>
<option value="1">One</option> <option value="1">One</option>
<option>2</option> <option>2</option>
</select> </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="default">Default</option>
<option value="1">One</option> <option value="1">One</option>
<option>2</option> <option>2</option>
</select> </select>
<select class="groups"> <select class="groups" tabindex="0">
<optgroup label="Test"> <optgroup label="Test">
<option value="one">One</option> <option value="one">One</option>
<option value="two">Two</option> <option value="two">Two</option>