Skip to content

Commit a8e6cbc

Browse files
committed
Add back keyboard support within allowClear
This adds back keyboard support, so you can now clear a selected item using either the backspace or delete key. This only work when the container is closed, to prevent issues with the selection being clear while a user is searching. This was a regression in accessibility from 3.x. This closes select2#3224.
1 parent 00a78bd commit a8e6cbc

5 files changed

Lines changed: 162 additions & 80 deletions

File tree

dist/js/select2.full.js

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,17 +1638,18 @@ S2.define('select2/selection/placeholder',[
16381638
});
16391639

16401640
S2.define('select2/selection/allowClear',[
1641-
'jquery'
1642-
], function ($) {
1641+
'jquery',
1642+
'../keys'
1643+
], function ($, KEYS) {
16431644
function AllowClear () { }
16441645

16451646
AllowClear.prototype.bind = function (decorated, container, $container) {
16461647
var self = this;
16471648

16481649
decorated.call(this, container, $container);
16491650

1650-
if (self.placeholder == null) {
1651-
if (self.options.get('debug') && window.console && console.error) {
1651+
if (this.placeholder == null) {
1652+
if (this.options.get('debug') && window.console && console.error) {
16521653
console.error(
16531654
'Select2: The `allowClear` option should be used in combination ' +
16541655
'with the `placeholder` option.'
@@ -1658,34 +1659,61 @@ S2.define('select2/selection/allowClear',[
16581659

16591660
this.$selection.on('mousedown', '.select2-selection__clear',
16601661
function (evt) {
1661-
// Ignore the event if it is disabled
1662-
if (self.options.get('disabled')) {
1663-
return;
1664-
}
1662+
self._handleClear(evt);
1663+
});
16651664

1666-
evt.stopPropagation();
1665+
container.on('keypress', function (evt) {
1666+
self._handleKeyboardClear(evt, container);
1667+
});
1668+
};
16671669

1668-
var data = $(this).data('data');
1670+
AllowClear.prototype._handleClear = function (_, evt) {
1671+
console.log(arguments);
16691672

1670-
for (var d = 0; d < data.length; d++) {
1671-
var unselectData = {
1672-
data: data[d]
1673-
};
1673+
// Ignore the event if it is disabled
1674+
if (this.options.get('disabled')) {
1675+
return;
1676+
}
16741677

1675-
// Trigger the `unselect` event, so people can prevent it from being
1676-
// cleared.
1677-
self.trigger('unselect', unselectData);
1678+
var $clear = this.$selection.find('.select2-selection__clear');
16781679

1679-
// If the event was prevented, don't clear it out.
1680-
if (unselectData.prevented) {
1681-
return;
1682-
}
1683-
}
1680+
// Ignore the event if nothing has been selected
1681+
if ($clear.length === 0) {
1682+
return;
1683+
}
16841684

1685-
self.$element.val(self.placeholder.id).trigger('change');
1685+
evt.stopPropagation();
16861686

1687-
self.trigger('toggle');
1688-
});
1687+
var data = $clear.data('data');
1688+
1689+
for (var d = 0; d < data.length; d++) {
1690+
var unselectData = {
1691+
data: data[d]
1692+
};
1693+
1694+
// Trigger the `unselect` event, so people can prevent it from being
1695+
// cleared.
1696+
this.trigger('unselect', unselectData);
1697+
1698+
// If the event was prevented, don't clear it out.
1699+
if (unselectData.prevented) {
1700+
return;
1701+
}
1702+
}
1703+
1704+
this.$element.val(this.placeholder.id).trigger('change');
1705+
1706+
this.trigger('toggle');
1707+
};
1708+
1709+
AllowClear.prototype._handleKeyboardClear = function (_, evt, container) {
1710+
if (container.isOpen()) {
1711+
return;
1712+
}
1713+
1714+
if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) {
1715+
this._handleClear(evt);
1716+
}
16891717
};
16901718

16911719
AllowClear.prototype.update = function (decorated, data) {

dist/js/select2.full.min.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/js/select2.js

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,17 +1638,18 @@ S2.define('select2/selection/placeholder',[
16381638
});
16391639

16401640
S2.define('select2/selection/allowClear',[
1641-
'jquery'
1642-
], function ($) {
1641+
'jquery',
1642+
'../keys'
1643+
], function ($, KEYS) {
16431644
function AllowClear () { }
16441645

16451646
AllowClear.prototype.bind = function (decorated, container, $container) {
16461647
var self = this;
16471648

16481649
decorated.call(this, container, $container);
16491650

1650-
if (self.placeholder == null) {
1651-
if (self.options.get('debug') && window.console && console.error) {
1651+
if (this.placeholder == null) {
1652+
if (this.options.get('debug') && window.console && console.error) {
16521653
console.error(
16531654
'Select2: The `allowClear` option should be used in combination ' +
16541655
'with the `placeholder` option.'
@@ -1658,34 +1659,61 @@ S2.define('select2/selection/allowClear',[
16581659

16591660
this.$selection.on('mousedown', '.select2-selection__clear',
16601661
function (evt) {
1661-
// Ignore the event if it is disabled
1662-
if (self.options.get('disabled')) {
1663-
return;
1664-
}
1662+
self._handleClear(evt);
1663+
});
16651664

1666-
evt.stopPropagation();
1665+
container.on('keypress', function (evt) {
1666+
self._handleKeyboardClear(evt, container);
1667+
});
1668+
};
16671669

1668-
var data = $(this).data('data');
1670+
AllowClear.prototype._handleClear = function (_, evt) {
1671+
console.log(arguments);
16691672

1670-
for (var d = 0; d < data.length; d++) {
1671-
var unselectData = {
1672-
data: data[d]
1673-
};
1673+
// Ignore the event if it is disabled
1674+
if (this.options.get('disabled')) {
1675+
return;
1676+
}
16741677

1675-
// Trigger the `unselect` event, so people can prevent it from being
1676-
// cleared.
1677-
self.trigger('unselect', unselectData);
1678+
var $clear = this.$selection.find('.select2-selection__clear');
16781679

1679-
// If the event was prevented, don't clear it out.
1680-
if (unselectData.prevented) {
1681-
return;
1682-
}
1683-
}
1680+
// Ignore the event if nothing has been selected
1681+
if ($clear.length === 0) {
1682+
return;
1683+
}
16841684

1685-
self.$element.val(self.placeholder.id).trigger('change');
1685+
evt.stopPropagation();
16861686

1687-
self.trigger('toggle');
1688-
});
1687+
var data = $clear.data('data');
1688+
1689+
for (var d = 0; d < data.length; d++) {
1690+
var unselectData = {
1691+
data: data[d]
1692+
};
1693+
1694+
// Trigger the `unselect` event, so people can prevent it from being
1695+
// cleared.
1696+
this.trigger('unselect', unselectData);
1697+
1698+
// If the event was prevented, don't clear it out.
1699+
if (unselectData.prevented) {
1700+
return;
1701+
}
1702+
}
1703+
1704+
this.$element.val(this.placeholder.id).trigger('change');
1705+
1706+
this.trigger('toggle');
1707+
};
1708+
1709+
AllowClear.prototype._handleKeyboardClear = function (_, evt, container) {
1710+
if (container.isOpen()) {
1711+
return;
1712+
}
1713+
1714+
if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) {
1715+
this._handleClear(evt);
1716+
}
16891717
};
16901718

16911719
AllowClear.prototype.update = function (decorated, data) {

dist/js/select2.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/js/select2/selection/allowClear.js

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
define([
2-
'jquery'
3-
], function ($) {
2+
'jquery',
3+
'../keys'
4+
], function ($, KEYS) {
45
function AllowClear () { }
56

67
AllowClear.prototype.bind = function (decorated, container, $container) {
78
var self = this;
89

910
decorated.call(this, container, $container);
1011

11-
if (self.placeholder == null) {
12-
if (self.options.get('debug') && window.console && console.error) {
12+
if (this.placeholder == null) {
13+
if (this.options.get('debug') && window.console && console.error) {
1314
console.error(
1415
'Select2: The `allowClear` option should be used in combination ' +
1516
'with the `placeholder` option.'
@@ -19,34 +20,59 @@ define([
1920

2021
this.$selection.on('mousedown', '.select2-selection__clear',
2122
function (evt) {
22-
// Ignore the event if it is disabled
23-
if (self.options.get('disabled')) {
24-
return;
25-
}
23+
self._handleClear(evt);
24+
});
25+
26+
container.on('keypress', function (evt) {
27+
self._handleKeyboardClear(evt, container);
28+
});
29+
};
30+
31+
AllowClear.prototype._handleClear = function (_, evt) {
32+
// Ignore the event if it is disabled
33+
if (this.options.get('disabled')) {
34+
return;
35+
}
2636

27-
evt.stopPropagation();
37+
var $clear = this.$selection.find('.select2-selection__clear');
2838

29-
var data = $(this).data('data');
39+
// Ignore the event if nothing has been selected
40+
if ($clear.length === 0) {
41+
return;
42+
}
3043

31-
for (var d = 0; d < data.length; d++) {
32-
var unselectData = {
33-
data: data[d]
34-
};
44+
evt.stopPropagation();
3545

36-
// Trigger the `unselect` event, so people can prevent it from being
37-
// cleared.
38-
self.trigger('unselect', unselectData);
46+
var data = $clear.data('data');
3947

40-
// If the event was prevented, don't clear it out.
41-
if (unselectData.prevented) {
42-
return;
43-
}
44-
}
48+
for (var d = 0; d < data.length; d++) {
49+
var unselectData = {
50+
data: data[d]
51+
};
4552

46-
self.$element.val(self.placeholder.id).trigger('change');
53+
// Trigger the `unselect` event, so people can prevent it from being
54+
// cleared.
55+
this.trigger('unselect', unselectData);
4756

48-
self.trigger('toggle');
49-
});
57+
// If the event was prevented, don't clear it out.
58+
if (unselectData.prevented) {
59+
return;
60+
}
61+
}
62+
63+
this.$element.val(this.placeholder.id).trigger('change');
64+
65+
this.trigger('toggle');
66+
};
67+
68+
AllowClear.prototype._handleKeyboardClear = function (_, evt, container) {
69+
if (container.isOpen()) {
70+
return;
71+
}
72+
73+
if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) {
74+
this._handleClear(evt);
75+
}
5076
};
5177

5278
AllowClear.prototype.update = function (decorated, data) {

0 commit comments

Comments
 (0)