Working on accessibility
This makes quite a few changes, one of the major ones being the removal of classes for marking options as selected or selectable, and instead using the ARIA attributes which should already be present.
This commit is contained in:
parent
e601e33ff3
commit
cc9419928e
9
dist/css/select2.css
vendored
9
dist/css/select2.css
vendored
@ -55,10 +55,11 @@
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
.select2-container .dropdown .results .options .option {
|
||||
cursor: pointer;
|
||||
padding: 6px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; }
|
||||
.select2-container .dropdown .results .options .option[aria-selected] {
|
||||
cursor: pointer; }
|
||||
.select2-container.open .dropdown {
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
@ -115,11 +116,11 @@
|
||||
cursor: default;
|
||||
display: block;
|
||||
padding: 6px; }
|
||||
.select2-container.select2-theme-default .dropdown .results .options .option.disabled {
|
||||
.select2-container.select2-theme-default .dropdown .results .options .option[aria-disabled=true] {
|
||||
color: #666; }
|
||||
.select2-container.select2-theme-default .dropdown .results .options .option.selected {
|
||||
.select2-container.select2-theme-default .dropdown .results .options .option[aria-selected=true] {
|
||||
background-color: #ddd; }
|
||||
.select2-container.select2-theme-default .dropdown .results .options .option.highlightable.highlighted {
|
||||
.select2-container.select2-theme-default .dropdown .results .options .option[aria-selected].highlighted {
|
||||
background-color: #5897fb;
|
||||
color: white; }
|
||||
|
||||
|
2
dist/css/select2.min.css
vendored
2
dist/css/select2.min.css
vendored
File diff suppressed because one or more lines are too long
169
dist/js/select2.amd.full.js
vendored
169
dist/js/select2.amd.full.js
vendored
@ -151,7 +151,7 @@ define('select2/results',[
|
||||
|
||||
Results.prototype.render = function () {
|
||||
var $results = $(
|
||||
'<ul class="options"></ul>'
|
||||
'<ul class="options" role="listbox"></ul>'
|
||||
);
|
||||
|
||||
this.$results = $results;
|
||||
@ -191,28 +191,42 @@ define('select2/results',[
|
||||
return s.id.toString();
|
||||
});
|
||||
|
||||
self.$results.find('.option.selected').removeClass('selected');
|
||||
|
||||
var $options = self.$results.find('.option');
|
||||
var $options = self.$results.find('.option[aria-selected]');
|
||||
|
||||
$options.each(function () {
|
||||
var $option = $(this);
|
||||
var item = $option.data('data');
|
||||
|
||||
if (item.id != null && selectedIds.indexOf(item.id.toString()) > -1) {
|
||||
$option.addClass('selected');
|
||||
$option.attr('aria-selected', 'true');
|
||||
} else {
|
||||
$option.attr('aria-selected', 'false');
|
||||
}
|
||||
});
|
||||
|
||||
var $selected = $options.filter('[aria-selected=true]');
|
||||
|
||||
// Check if there are any selected options
|
||||
if ($selected.length > 0) {
|
||||
// If there are selected options, highlight the first
|
||||
$selected.first().trigger('mouseenter');
|
||||
} else {
|
||||
// If there are no selected options, highlight the first option
|
||||
// in the dropdown
|
||||
$options.first().trigger('mouseenter');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Results.prototype.option = function (data) {
|
||||
var $option = $(
|
||||
'<li class="option highlightable selectable"></li>'
|
||||
'<li class="option" role="option" aria-selected="false"></li>'
|
||||
);
|
||||
|
||||
if (data.children) {
|
||||
$option.addClass('group').removeClass('highlightable selectable');
|
||||
$option
|
||||
.addClass('group')
|
||||
.removeAttr('aria-selected');
|
||||
|
||||
var $label = $('<strong class="group-label"></strong>');
|
||||
$label.html(data.text);
|
||||
@ -238,11 +252,13 @@ define('select2/results',[
|
||||
}
|
||||
|
||||
if (data.disabled) {
|
||||
$option.removeClass('selectable highlightable').addClass('disabled');
|
||||
$option
|
||||
.removeAttr('aria-selected')
|
||||
.attr('aria-disabled', 'true');
|
||||
}
|
||||
|
||||
if (data.id == null) {
|
||||
$option.removeClass('selectable highlightable');
|
||||
$option.removeClass('aria-selected');
|
||||
}
|
||||
|
||||
$option.data('data', data);
|
||||
@ -274,11 +290,40 @@ define('select2/results',[
|
||||
self.setClasses();
|
||||
});
|
||||
|
||||
this.$results.on('mouseup', '.option.selectable', function (evt) {
|
||||
container.on('open', function () {
|
||||
// When the dropdown is open, aria-expended="true"
|
||||
self.$results.attr('aria-expanded', 'true');
|
||||
|
||||
self.setClasses();
|
||||
});
|
||||
|
||||
container.on('close', function () {
|
||||
// When the dropdown is closed, aria-expended="false"
|
||||
self.$results.attr('aria-expanded', 'false');
|
||||
});
|
||||
|
||||
container.on('results:select', function () {
|
||||
var $highlighted = self.$results.find('.highlighted');
|
||||
|
||||
var data = $highlighted.data('data');
|
||||
|
||||
if ($highlighted.attr('aria-selected') == 'true') {
|
||||
self.trigger('unselected', {
|
||||
data: data
|
||||
});
|
||||
} else {
|
||||
self.trigger('selected', {
|
||||
data: data
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.$results.on('mouseup', '.option[aria-selected]', function (evt) {
|
||||
var $this = $(this);
|
||||
|
||||
var data = $this.data('data');
|
||||
if ($this.hasClass('selected')) {
|
||||
|
||||
if ($this.attr('aria-selected') === 'true') {
|
||||
self.trigger('unselected', {
|
||||
originalEvent: evt,
|
||||
data: data
|
||||
@ -293,7 +338,7 @@ define('select2/results',[
|
||||
});
|
||||
});
|
||||
|
||||
this.$results.on('mouseenter', '.option.highlightable', function (evt) {
|
||||
this.$results.on('mouseenter', '.option[aria-selected]', function (evt) {
|
||||
self.$results.find('.option.highlighted').removeClass('highlighted');
|
||||
$(this).addClass('highlighted');
|
||||
});
|
||||
@ -337,10 +382,51 @@ define('select2/selection/base',[
|
||||
return BaseSelection;
|
||||
});
|
||||
|
||||
define('select2/keys',[
|
||||
|
||||
], function () {
|
||||
var KEYS = {
|
||||
BACKSPACE: 8,
|
||||
TAB: 9,
|
||||
ENTER: 13,
|
||||
SHIFT: 16,
|
||||
CTRL: 17,
|
||||
ALT: 18,
|
||||
ESC: 27,
|
||||
SPACE: 32,
|
||||
PAGE_UP: 33,
|
||||
PAGE_DOWN: 34,
|
||||
END: 35,
|
||||
HOME: 36,
|
||||
LEFT: 37,
|
||||
UP: 38,
|
||||
RIGHT: 39,
|
||||
DOWN: 40,
|
||||
DELETE: 46,
|
||||
|
||||
isArrow: function (k) {
|
||||
k = k.which ? k.which : k;
|
||||
|
||||
switch (k) {
|
||||
case KEY.LEFT:
|
||||
case KEY.RIGHT:
|
||||
case KEY.UP:
|
||||
case KEY.DOWN:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
return KEYS;
|
||||
});
|
||||
|
||||
define('select2/selection/single',[
|
||||
'./base',
|
||||
'../utils'
|
||||
], function (BaseSelection, Utils) {
|
||||
'../utils',
|
||||
'../keys'
|
||||
], function (BaseSelection, Utils, KEYS) {
|
||||
function SingleSelection () {
|
||||
SingleSelection.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
@ -349,11 +435,13 @@ define('select2/selection/single',[
|
||||
|
||||
SingleSelection.prototype.render = function () {
|
||||
var $selection = $(
|
||||
'<span class="single-select">' +
|
||||
'<span class="single-select" tabindex="0">' +
|
||||
'<span class="rendered-selection"></span>' +
|
||||
'</span>'
|
||||
);
|
||||
|
||||
$selection.attr('title', this.$element.attr('title'));
|
||||
|
||||
this.$selection = $selection;
|
||||
|
||||
return $selection;
|
||||
@ -375,6 +463,28 @@ define('select2/selection/single',[
|
||||
});
|
||||
});
|
||||
|
||||
this.$selection.on('focus', function (evt) {
|
||||
// User focuses on the container
|
||||
});
|
||||
|
||||
this.$selection.on('blur', function (evt) {
|
||||
// User exits the container
|
||||
});
|
||||
|
||||
this.$selection.on('keyup', function (evt) {
|
||||
var key = evt.which;
|
||||
|
||||
if (container.isOpen()) {
|
||||
if (key == KEYS.ENTER) {
|
||||
self.trigger('results:select');
|
||||
}
|
||||
} else {
|
||||
if (key == KEYS.ENTER || key == KEYS.SPACE) {
|
||||
self.trigger('open');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
container.on('selection:update', function (params) {
|
||||
self.update(params.data);
|
||||
});
|
||||
@ -468,7 +578,7 @@ define('select2/selection/multiple',[
|
||||
MultipleSelection.prototype.selectionContainer = function () {
|
||||
var $container = $(
|
||||
'<li class="choice">' +
|
||||
'<span class="remove">×</span>' +
|
||||
'<span class="remove" role="presentation">×</span>' +
|
||||
'</li>'
|
||||
);
|
||||
|
||||
@ -898,7 +1008,7 @@ define('select2/dropdown/search',[
|
||||
|
||||
var $search = $(
|
||||
'<span class="search">' +
|
||||
'<input type="search" name="search" />' +
|
||||
'<input type="search" name="search" tabindex="-1" role="textbox" />' +
|
||||
'</span>'
|
||||
);
|
||||
|
||||
@ -921,6 +1031,14 @@ define('select2/dropdown/search',[
|
||||
});
|
||||
});
|
||||
|
||||
container.on('open', function () {
|
||||
self.$search.attr('tabindex', 0);
|
||||
});
|
||||
|
||||
container.on('close', function () {
|
||||
self.$search.attr('tabindex', -1);
|
||||
});
|
||||
|
||||
container.on('results:all', function (params) {
|
||||
if (params.query.term == null || params.query.term === '') {
|
||||
var showSearch = self.showSearch(params);
|
||||
@ -1108,10 +1226,20 @@ define('select2/core',[
|
||||
});
|
||||
});
|
||||
|
||||
this.selection.on('open', function () {
|
||||
self.trigger('open');
|
||||
});
|
||||
this.selection.on('close', function () {
|
||||
self.trigger('close');
|
||||
});
|
||||
this.selection.on('toggle', function () {
|
||||
self.toggleDropdown();
|
||||
});
|
||||
|
||||
this.selection.on('results:select', function () {
|
||||
self.trigger('results:select');
|
||||
});
|
||||
|
||||
this.selection.on('unselected', function (params) {
|
||||
self.trigger('unselect', params);
|
||||
|
||||
@ -1160,18 +1288,23 @@ define('select2/core',[
|
||||
// Hide the original select
|
||||
|
||||
$element.hide();
|
||||
$element.attr('tabindex', '-1');
|
||||
};
|
||||
|
||||
Utils.Extend(Select2, Utils.Observable);
|
||||
|
||||
Select2.prototype.toggleDropdown = function () {
|
||||
if (this.$container.hasClass('open')) {
|
||||
if (this.isOpen()) {
|
||||
this.trigger('close');
|
||||
} else {
|
||||
this.trigger('open');
|
||||
}
|
||||
};
|
||||
|
||||
Select2.prototype.isOpen = function () {
|
||||
return this.$container.hasClass('open');
|
||||
};
|
||||
|
||||
Select2.prototype.render = function () {
|
||||
var $container = $(
|
||||
'<span class="select2 select2-container select2-theme-default">' +
|
||||
|
169
dist/js/select2.amd.js
vendored
169
dist/js/select2.amd.js
vendored
@ -151,7 +151,7 @@ define('select2/results',[
|
||||
|
||||
Results.prototype.render = function () {
|
||||
var $results = $(
|
||||
'<ul class="options"></ul>'
|
||||
'<ul class="options" role="listbox"></ul>'
|
||||
);
|
||||
|
||||
this.$results = $results;
|
||||
@ -191,28 +191,42 @@ define('select2/results',[
|
||||
return s.id.toString();
|
||||
});
|
||||
|
||||
self.$results.find('.option.selected').removeClass('selected');
|
||||
|
||||
var $options = self.$results.find('.option');
|
||||
var $options = self.$results.find('.option[aria-selected]');
|
||||
|
||||
$options.each(function () {
|
||||
var $option = $(this);
|
||||
var item = $option.data('data');
|
||||
|
||||
if (item.id != null && selectedIds.indexOf(item.id.toString()) > -1) {
|
||||
$option.addClass('selected');
|
||||
$option.attr('aria-selected', 'true');
|
||||
} else {
|
||||
$option.attr('aria-selected', 'false');
|
||||
}
|
||||
});
|
||||
|
||||
var $selected = $options.filter('[aria-selected=true]');
|
||||
|
||||
// Check if there are any selected options
|
||||
if ($selected.length > 0) {
|
||||
// If there are selected options, highlight the first
|
||||
$selected.first().trigger('mouseenter');
|
||||
} else {
|
||||
// If there are no selected options, highlight the first option
|
||||
// in the dropdown
|
||||
$options.first().trigger('mouseenter');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Results.prototype.option = function (data) {
|
||||
var $option = $(
|
||||
'<li class="option highlightable selectable"></li>'
|
||||
'<li class="option" role="option" aria-selected="false"></li>'
|
||||
);
|
||||
|
||||
if (data.children) {
|
||||
$option.addClass('group').removeClass('highlightable selectable');
|
||||
$option
|
||||
.addClass('group')
|
||||
.removeAttr('aria-selected');
|
||||
|
||||
var $label = $('<strong class="group-label"></strong>');
|
||||
$label.html(data.text);
|
||||
@ -238,11 +252,13 @@ define('select2/results',[
|
||||
}
|
||||
|
||||
if (data.disabled) {
|
||||
$option.removeClass('selectable highlightable').addClass('disabled');
|
||||
$option
|
||||
.removeAttr('aria-selected')
|
||||
.attr('aria-disabled', 'true');
|
||||
}
|
||||
|
||||
if (data.id == null) {
|
||||
$option.removeClass('selectable highlightable');
|
||||
$option.removeClass('aria-selected');
|
||||
}
|
||||
|
||||
$option.data('data', data);
|
||||
@ -274,11 +290,40 @@ define('select2/results',[
|
||||
self.setClasses();
|
||||
});
|
||||
|
||||
this.$results.on('mouseup', '.option.selectable', function (evt) {
|
||||
container.on('open', function () {
|
||||
// When the dropdown is open, aria-expended="true"
|
||||
self.$results.attr('aria-expanded', 'true');
|
||||
|
||||
self.setClasses();
|
||||
});
|
||||
|
||||
container.on('close', function () {
|
||||
// When the dropdown is closed, aria-expended="false"
|
||||
self.$results.attr('aria-expanded', 'false');
|
||||
});
|
||||
|
||||
container.on('results:select', function () {
|
||||
var $highlighted = self.$results.find('.highlighted');
|
||||
|
||||
var data = $highlighted.data('data');
|
||||
|
||||
if ($highlighted.attr('aria-selected') == 'true') {
|
||||
self.trigger('unselected', {
|
||||
data: data
|
||||
});
|
||||
} else {
|
||||
self.trigger('selected', {
|
||||
data: data
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.$results.on('mouseup', '.option[aria-selected]', function (evt) {
|
||||
var $this = $(this);
|
||||
|
||||
var data = $this.data('data');
|
||||
if ($this.hasClass('selected')) {
|
||||
|
||||
if ($this.attr('aria-selected') === 'true') {
|
||||
self.trigger('unselected', {
|
||||
originalEvent: evt,
|
||||
data: data
|
||||
@ -293,7 +338,7 @@ define('select2/results',[
|
||||
});
|
||||
});
|
||||
|
||||
this.$results.on('mouseenter', '.option.highlightable', function (evt) {
|
||||
this.$results.on('mouseenter', '.option[aria-selected]', function (evt) {
|
||||
self.$results.find('.option.highlighted').removeClass('highlighted');
|
||||
$(this).addClass('highlighted');
|
||||
});
|
||||
@ -337,10 +382,51 @@ define('select2/selection/base',[
|
||||
return BaseSelection;
|
||||
});
|
||||
|
||||
define('select2/keys',[
|
||||
|
||||
], function () {
|
||||
var KEYS = {
|
||||
BACKSPACE: 8,
|
||||
TAB: 9,
|
||||
ENTER: 13,
|
||||
SHIFT: 16,
|
||||
CTRL: 17,
|
||||
ALT: 18,
|
||||
ESC: 27,
|
||||
SPACE: 32,
|
||||
PAGE_UP: 33,
|
||||
PAGE_DOWN: 34,
|
||||
END: 35,
|
||||
HOME: 36,
|
||||
LEFT: 37,
|
||||
UP: 38,
|
||||
RIGHT: 39,
|
||||
DOWN: 40,
|
||||
DELETE: 46,
|
||||
|
||||
isArrow: function (k) {
|
||||
k = k.which ? k.which : k;
|
||||
|
||||
switch (k) {
|
||||
case KEY.LEFT:
|
||||
case KEY.RIGHT:
|
||||
case KEY.UP:
|
||||
case KEY.DOWN:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
return KEYS;
|
||||
});
|
||||
|
||||
define('select2/selection/single',[
|
||||
'./base',
|
||||
'../utils'
|
||||
], function (BaseSelection, Utils) {
|
||||
'../utils',
|
||||
'../keys'
|
||||
], function (BaseSelection, Utils, KEYS) {
|
||||
function SingleSelection () {
|
||||
SingleSelection.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
@ -349,11 +435,13 @@ define('select2/selection/single',[
|
||||
|
||||
SingleSelection.prototype.render = function () {
|
||||
var $selection = $(
|
||||
'<span class="single-select">' +
|
||||
'<span class="single-select" tabindex="0">' +
|
||||
'<span class="rendered-selection"></span>' +
|
||||
'</span>'
|
||||
);
|
||||
|
||||
$selection.attr('title', this.$element.attr('title'));
|
||||
|
||||
this.$selection = $selection;
|
||||
|
||||
return $selection;
|
||||
@ -375,6 +463,28 @@ define('select2/selection/single',[
|
||||
});
|
||||
});
|
||||
|
||||
this.$selection.on('focus', function (evt) {
|
||||
// User focuses on the container
|
||||
});
|
||||
|
||||
this.$selection.on('blur', function (evt) {
|
||||
// User exits the container
|
||||
});
|
||||
|
||||
this.$selection.on('keyup', function (evt) {
|
||||
var key = evt.which;
|
||||
|
||||
if (container.isOpen()) {
|
||||
if (key == KEYS.ENTER) {
|
||||
self.trigger('results:select');
|
||||
}
|
||||
} else {
|
||||
if (key == KEYS.ENTER || key == KEYS.SPACE) {
|
||||
self.trigger('open');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
container.on('selection:update', function (params) {
|
||||
self.update(params.data);
|
||||
});
|
||||
@ -468,7 +578,7 @@ define('select2/selection/multiple',[
|
||||
MultipleSelection.prototype.selectionContainer = function () {
|
||||
var $container = $(
|
||||
'<li class="choice">' +
|
||||
'<span class="remove">×</span>' +
|
||||
'<span class="remove" role="presentation">×</span>' +
|
||||
'</li>'
|
||||
);
|
||||
|
||||
@ -898,7 +1008,7 @@ define('select2/dropdown/search',[
|
||||
|
||||
var $search = $(
|
||||
'<span class="search">' +
|
||||
'<input type="search" name="search" />' +
|
||||
'<input type="search" name="search" tabindex="-1" role="textbox" />' +
|
||||
'</span>'
|
||||
);
|
||||
|
||||
@ -921,6 +1031,14 @@ define('select2/dropdown/search',[
|
||||
});
|
||||
});
|
||||
|
||||
container.on('open', function () {
|
||||
self.$search.attr('tabindex', 0);
|
||||
});
|
||||
|
||||
container.on('close', function () {
|
||||
self.$search.attr('tabindex', -1);
|
||||
});
|
||||
|
||||
container.on('results:all', function (params) {
|
||||
if (params.query.term == null || params.query.term === '') {
|
||||
var showSearch = self.showSearch(params);
|
||||
@ -1108,10 +1226,20 @@ define('select2/core',[
|
||||
});
|
||||
});
|
||||
|
||||
this.selection.on('open', function () {
|
||||
self.trigger('open');
|
||||
});
|
||||
this.selection.on('close', function () {
|
||||
self.trigger('close');
|
||||
});
|
||||
this.selection.on('toggle', function () {
|
||||
self.toggleDropdown();
|
||||
});
|
||||
|
||||
this.selection.on('results:select', function () {
|
||||
self.trigger('results:select');
|
||||
});
|
||||
|
||||
this.selection.on('unselected', function (params) {
|
||||
self.trigger('unselect', params);
|
||||
|
||||
@ -1160,18 +1288,23 @@ define('select2/core',[
|
||||
// Hide the original select
|
||||
|
||||
$element.hide();
|
||||
$element.attr('tabindex', '-1');
|
||||
};
|
||||
|
||||
Utils.Extend(Select2, Utils.Observable);
|
||||
|
||||
Select2.prototype.toggleDropdown = function () {
|
||||
if (this.$container.hasClass('open')) {
|
||||
if (this.isOpen()) {
|
||||
this.trigger('close');
|
||||
} else {
|
||||
this.trigger('open');
|
||||
}
|
||||
};
|
||||
|
||||
Select2.prototype.isOpen = function () {
|
||||
return this.$container.hasClass('open');
|
||||
};
|
||||
|
||||
Select2.prototype.render = function () {
|
||||
var $container = $(
|
||||
'<span class="select2 select2-container select2-theme-default">' +
|
||||
|
169
dist/js/select2.full.js
vendored
169
dist/js/select2.full.js
vendored
@ -9689,7 +9689,7 @@ define('select2/results',[
|
||||
|
||||
Results.prototype.render = function () {
|
||||
var $results = $(
|
||||
'<ul class="options"></ul>'
|
||||
'<ul class="options" role="listbox"></ul>'
|
||||
);
|
||||
|
||||
this.$results = $results;
|
||||
@ -9729,28 +9729,42 @@ define('select2/results',[
|
||||
return s.id.toString();
|
||||
});
|
||||
|
||||
self.$results.find('.option.selected').removeClass('selected');
|
||||
|
||||
var $options = self.$results.find('.option');
|
||||
var $options = self.$results.find('.option[aria-selected]');
|
||||
|
||||
$options.each(function () {
|
||||
var $option = $(this);
|
||||
var item = $option.data('data');
|
||||
|
||||
if (item.id != null && selectedIds.indexOf(item.id.toString()) > -1) {
|
||||
$option.addClass('selected');
|
||||
$option.attr('aria-selected', 'true');
|
||||
} else {
|
||||
$option.attr('aria-selected', 'false');
|
||||
}
|
||||
});
|
||||
|
||||
var $selected = $options.filter('[aria-selected=true]');
|
||||
|
||||
// Check if there are any selected options
|
||||
if ($selected.length > 0) {
|
||||
// If there are selected options, highlight the first
|
||||
$selected.first().trigger('mouseenter');
|
||||
} else {
|
||||
// If there are no selected options, highlight the first option
|
||||
// in the dropdown
|
||||
$options.first().trigger('mouseenter');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Results.prototype.option = function (data) {
|
||||
var $option = $(
|
||||
'<li class="option highlightable selectable"></li>'
|
||||
'<li class="option" role="option" aria-selected="false"></li>'
|
||||
);
|
||||
|
||||
if (data.children) {
|
||||
$option.addClass('group').removeClass('highlightable selectable');
|
||||
$option
|
||||
.addClass('group')
|
||||
.removeAttr('aria-selected');
|
||||
|
||||
var $label = $('<strong class="group-label"></strong>');
|
||||
$label.html(data.text);
|
||||
@ -9776,11 +9790,13 @@ define('select2/results',[
|
||||
}
|
||||
|
||||
if (data.disabled) {
|
||||
$option.removeClass('selectable highlightable').addClass('disabled');
|
||||
$option
|
||||
.removeAttr('aria-selected')
|
||||
.attr('aria-disabled', 'true');
|
||||
}
|
||||
|
||||
if (data.id == null) {
|
||||
$option.removeClass('selectable highlightable');
|
||||
$option.removeClass('aria-selected');
|
||||
}
|
||||
|
||||
$option.data('data', data);
|
||||
@ -9812,11 +9828,40 @@ define('select2/results',[
|
||||
self.setClasses();
|
||||
});
|
||||
|
||||
this.$results.on('mouseup', '.option.selectable', function (evt) {
|
||||
container.on('open', function () {
|
||||
// When the dropdown is open, aria-expended="true"
|
||||
self.$results.attr('aria-expanded', 'true');
|
||||
|
||||
self.setClasses();
|
||||
});
|
||||
|
||||
container.on('close', function () {
|
||||
// When the dropdown is closed, aria-expended="false"
|
||||
self.$results.attr('aria-expanded', 'false');
|
||||
});
|
||||
|
||||
container.on('results:select', function () {
|
||||
var $highlighted = self.$results.find('.highlighted');
|
||||
|
||||
var data = $highlighted.data('data');
|
||||
|
||||
if ($highlighted.attr('aria-selected') == 'true') {
|
||||
self.trigger('unselected', {
|
||||
data: data
|
||||
});
|
||||
} else {
|
||||
self.trigger('selected', {
|
||||
data: data
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.$results.on('mouseup', '.option[aria-selected]', function (evt) {
|
||||
var $this = $(this);
|
||||
|
||||
var data = $this.data('data');
|
||||
if ($this.hasClass('selected')) {
|
||||
|
||||
if ($this.attr('aria-selected') === 'true') {
|
||||
self.trigger('unselected', {
|
||||
originalEvent: evt,
|
||||
data: data
|
||||
@ -9831,7 +9876,7 @@ define('select2/results',[
|
||||
});
|
||||
});
|
||||
|
||||
this.$results.on('mouseenter', '.option.highlightable', function (evt) {
|
||||
this.$results.on('mouseenter', '.option[aria-selected]', function (evt) {
|
||||
self.$results.find('.option.highlighted').removeClass('highlighted');
|
||||
$(this).addClass('highlighted');
|
||||
});
|
||||
@ -9875,10 +9920,51 @@ define('select2/selection/base',[
|
||||
return BaseSelection;
|
||||
});
|
||||
|
||||
define('select2/keys',[
|
||||
|
||||
], function () {
|
||||
var KEYS = {
|
||||
BACKSPACE: 8,
|
||||
TAB: 9,
|
||||
ENTER: 13,
|
||||
SHIFT: 16,
|
||||
CTRL: 17,
|
||||
ALT: 18,
|
||||
ESC: 27,
|
||||
SPACE: 32,
|
||||
PAGE_UP: 33,
|
||||
PAGE_DOWN: 34,
|
||||
END: 35,
|
||||
HOME: 36,
|
||||
LEFT: 37,
|
||||
UP: 38,
|
||||
RIGHT: 39,
|
||||
DOWN: 40,
|
||||
DELETE: 46,
|
||||
|
||||
isArrow: function (k) {
|
||||
k = k.which ? k.which : k;
|
||||
|
||||
switch (k) {
|
||||
case KEY.LEFT:
|
||||
case KEY.RIGHT:
|
||||
case KEY.UP:
|
||||
case KEY.DOWN:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
return KEYS;
|
||||
});
|
||||
|
||||
define('select2/selection/single',[
|
||||
'./base',
|
||||
'../utils'
|
||||
], function (BaseSelection, Utils) {
|
||||
'../utils',
|
||||
'../keys'
|
||||
], function (BaseSelection, Utils, KEYS) {
|
||||
function SingleSelection () {
|
||||
SingleSelection.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
@ -9887,11 +9973,13 @@ define('select2/selection/single',[
|
||||
|
||||
SingleSelection.prototype.render = function () {
|
||||
var $selection = $(
|
||||
'<span class="single-select">' +
|
||||
'<span class="single-select" tabindex="0">' +
|
||||
'<span class="rendered-selection"></span>' +
|
||||
'</span>'
|
||||
);
|
||||
|
||||
$selection.attr('title', this.$element.attr('title'));
|
||||
|
||||
this.$selection = $selection;
|
||||
|
||||
return $selection;
|
||||
@ -9913,6 +10001,28 @@ define('select2/selection/single',[
|
||||
});
|
||||
});
|
||||
|
||||
this.$selection.on('focus', function (evt) {
|
||||
// User focuses on the container
|
||||
});
|
||||
|
||||
this.$selection.on('blur', function (evt) {
|
||||
// User exits the container
|
||||
});
|
||||
|
||||
this.$selection.on('keyup', function (evt) {
|
||||
var key = evt.which;
|
||||
|
||||
if (container.isOpen()) {
|
||||
if (key == KEYS.ENTER) {
|
||||
self.trigger('results:select');
|
||||
}
|
||||
} else {
|
||||
if (key == KEYS.ENTER || key == KEYS.SPACE) {
|
||||
self.trigger('open');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
container.on('selection:update', function (params) {
|
||||
self.update(params.data);
|
||||
});
|
||||
@ -10006,7 +10116,7 @@ define('select2/selection/multiple',[
|
||||
MultipleSelection.prototype.selectionContainer = function () {
|
||||
var $container = $(
|
||||
'<li class="choice">' +
|
||||
'<span class="remove">×</span>' +
|
||||
'<span class="remove" role="presentation">×</span>' +
|
||||
'</li>'
|
||||
);
|
||||
|
||||
@ -10436,7 +10546,7 @@ define('select2/dropdown/search',[
|
||||
|
||||
var $search = $(
|
||||
'<span class="search">' +
|
||||
'<input type="search" name="search" />' +
|
||||
'<input type="search" name="search" tabindex="-1" role="textbox" />' +
|
||||
'</span>'
|
||||
);
|
||||
|
||||
@ -10459,6 +10569,14 @@ define('select2/dropdown/search',[
|
||||
});
|
||||
});
|
||||
|
||||
container.on('open', function () {
|
||||
self.$search.attr('tabindex', 0);
|
||||
});
|
||||
|
||||
container.on('close', function () {
|
||||
self.$search.attr('tabindex', -1);
|
||||
});
|
||||
|
||||
container.on('results:all', function (params) {
|
||||
if (params.query.term == null || params.query.term === '') {
|
||||
var showSearch = self.showSearch(params);
|
||||
@ -10646,10 +10764,20 @@ define('select2/core',[
|
||||
});
|
||||
});
|
||||
|
||||
this.selection.on('open', function () {
|
||||
self.trigger('open');
|
||||
});
|
||||
this.selection.on('close', function () {
|
||||
self.trigger('close');
|
||||
});
|
||||
this.selection.on('toggle', function () {
|
||||
self.toggleDropdown();
|
||||
});
|
||||
|
||||
this.selection.on('results:select', function () {
|
||||
self.trigger('results:select');
|
||||
});
|
||||
|
||||
this.selection.on('unselected', function (params) {
|
||||
self.trigger('unselect', params);
|
||||
|
||||
@ -10698,18 +10826,23 @@ define('select2/core',[
|
||||
// Hide the original select
|
||||
|
||||
$element.hide();
|
||||
$element.attr('tabindex', '-1');
|
||||
};
|
||||
|
||||
Utils.Extend(Select2, Utils.Observable);
|
||||
|
||||
Select2.prototype.toggleDropdown = function () {
|
||||
if (this.$container.hasClass('open')) {
|
||||
if (this.isOpen()) {
|
||||
this.trigger('close');
|
||||
} else {
|
||||
this.trigger('open');
|
||||
}
|
||||
};
|
||||
|
||||
Select2.prototype.isOpen = function () {
|
||||
return this.$container.hasClass('open');
|
||||
};
|
||||
|
||||
Select2.prototype.render = function () {
|
||||
var $container = $(
|
||||
'<span class="select2 select2-container select2-theme-default">' +
|
||||
|
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
169
dist/js/select2.js
vendored
169
dist/js/select2.js
vendored
@ -580,7 +580,7 @@ define('select2/results',[
|
||||
|
||||
Results.prototype.render = function () {
|
||||
var $results = $(
|
||||
'<ul class="options"></ul>'
|
||||
'<ul class="options" role="listbox"></ul>'
|
||||
);
|
||||
|
||||
this.$results = $results;
|
||||
@ -620,28 +620,42 @@ define('select2/results',[
|
||||
return s.id.toString();
|
||||
});
|
||||
|
||||
self.$results.find('.option.selected').removeClass('selected');
|
||||
|
||||
var $options = self.$results.find('.option');
|
||||
var $options = self.$results.find('.option[aria-selected]');
|
||||
|
||||
$options.each(function () {
|
||||
var $option = $(this);
|
||||
var item = $option.data('data');
|
||||
|
||||
if (item.id != null && selectedIds.indexOf(item.id.toString()) > -1) {
|
||||
$option.addClass('selected');
|
||||
$option.attr('aria-selected', 'true');
|
||||
} else {
|
||||
$option.attr('aria-selected', 'false');
|
||||
}
|
||||
});
|
||||
|
||||
var $selected = $options.filter('[aria-selected=true]');
|
||||
|
||||
// Check if there are any selected options
|
||||
if ($selected.length > 0) {
|
||||
// If there are selected options, highlight the first
|
||||
$selected.first().trigger('mouseenter');
|
||||
} else {
|
||||
// If there are no selected options, highlight the first option
|
||||
// in the dropdown
|
||||
$options.first().trigger('mouseenter');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Results.prototype.option = function (data) {
|
||||
var $option = $(
|
||||
'<li class="option highlightable selectable"></li>'
|
||||
'<li class="option" role="option" aria-selected="false"></li>'
|
||||
);
|
||||
|
||||
if (data.children) {
|
||||
$option.addClass('group').removeClass('highlightable selectable');
|
||||
$option
|
||||
.addClass('group')
|
||||
.removeAttr('aria-selected');
|
||||
|
||||
var $label = $('<strong class="group-label"></strong>');
|
||||
$label.html(data.text);
|
||||
@ -667,11 +681,13 @@ define('select2/results',[
|
||||
}
|
||||
|
||||
if (data.disabled) {
|
||||
$option.removeClass('selectable highlightable').addClass('disabled');
|
||||
$option
|
||||
.removeAttr('aria-selected')
|
||||
.attr('aria-disabled', 'true');
|
||||
}
|
||||
|
||||
if (data.id == null) {
|
||||
$option.removeClass('selectable highlightable');
|
||||
$option.removeClass('aria-selected');
|
||||
}
|
||||
|
||||
$option.data('data', data);
|
||||
@ -703,11 +719,40 @@ define('select2/results',[
|
||||
self.setClasses();
|
||||
});
|
||||
|
||||
this.$results.on('mouseup', '.option.selectable', function (evt) {
|
||||
container.on('open', function () {
|
||||
// When the dropdown is open, aria-expended="true"
|
||||
self.$results.attr('aria-expanded', 'true');
|
||||
|
||||
self.setClasses();
|
||||
});
|
||||
|
||||
container.on('close', function () {
|
||||
// When the dropdown is closed, aria-expended="false"
|
||||
self.$results.attr('aria-expanded', 'false');
|
||||
});
|
||||
|
||||
container.on('results:select', function () {
|
||||
var $highlighted = self.$results.find('.highlighted');
|
||||
|
||||
var data = $highlighted.data('data');
|
||||
|
||||
if ($highlighted.attr('aria-selected') == 'true') {
|
||||
self.trigger('unselected', {
|
||||
data: data
|
||||
});
|
||||
} else {
|
||||
self.trigger('selected', {
|
||||
data: data
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.$results.on('mouseup', '.option[aria-selected]', function (evt) {
|
||||
var $this = $(this);
|
||||
|
||||
var data = $this.data('data');
|
||||
if ($this.hasClass('selected')) {
|
||||
|
||||
if ($this.attr('aria-selected') === 'true') {
|
||||
self.trigger('unselected', {
|
||||
originalEvent: evt,
|
||||
data: data
|
||||
@ -722,7 +767,7 @@ define('select2/results',[
|
||||
});
|
||||
});
|
||||
|
||||
this.$results.on('mouseenter', '.option.highlightable', function (evt) {
|
||||
this.$results.on('mouseenter', '.option[aria-selected]', function (evt) {
|
||||
self.$results.find('.option.highlighted').removeClass('highlighted');
|
||||
$(this).addClass('highlighted');
|
||||
});
|
||||
@ -766,10 +811,51 @@ define('select2/selection/base',[
|
||||
return BaseSelection;
|
||||
});
|
||||
|
||||
define('select2/keys',[
|
||||
|
||||
], function () {
|
||||
var KEYS = {
|
||||
BACKSPACE: 8,
|
||||
TAB: 9,
|
||||
ENTER: 13,
|
||||
SHIFT: 16,
|
||||
CTRL: 17,
|
||||
ALT: 18,
|
||||
ESC: 27,
|
||||
SPACE: 32,
|
||||
PAGE_UP: 33,
|
||||
PAGE_DOWN: 34,
|
||||
END: 35,
|
||||
HOME: 36,
|
||||
LEFT: 37,
|
||||
UP: 38,
|
||||
RIGHT: 39,
|
||||
DOWN: 40,
|
||||
DELETE: 46,
|
||||
|
||||
isArrow: function (k) {
|
||||
k = k.which ? k.which : k;
|
||||
|
||||
switch (k) {
|
||||
case KEY.LEFT:
|
||||
case KEY.RIGHT:
|
||||
case KEY.UP:
|
||||
case KEY.DOWN:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
return KEYS;
|
||||
});
|
||||
|
||||
define('select2/selection/single',[
|
||||
'./base',
|
||||
'../utils'
|
||||
], function (BaseSelection, Utils) {
|
||||
'../utils',
|
||||
'../keys'
|
||||
], function (BaseSelection, Utils, KEYS) {
|
||||
function SingleSelection () {
|
||||
SingleSelection.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
@ -778,11 +864,13 @@ define('select2/selection/single',[
|
||||
|
||||
SingleSelection.prototype.render = function () {
|
||||
var $selection = $(
|
||||
'<span class="single-select">' +
|
||||
'<span class="single-select" tabindex="0">' +
|
||||
'<span class="rendered-selection"></span>' +
|
||||
'</span>'
|
||||
);
|
||||
|
||||
$selection.attr('title', this.$element.attr('title'));
|
||||
|
||||
this.$selection = $selection;
|
||||
|
||||
return $selection;
|
||||
@ -804,6 +892,28 @@ define('select2/selection/single',[
|
||||
});
|
||||
});
|
||||
|
||||
this.$selection.on('focus', function (evt) {
|
||||
// User focuses on the container
|
||||
});
|
||||
|
||||
this.$selection.on('blur', function (evt) {
|
||||
// User exits the container
|
||||
});
|
||||
|
||||
this.$selection.on('keyup', function (evt) {
|
||||
var key = evt.which;
|
||||
|
||||
if (container.isOpen()) {
|
||||
if (key == KEYS.ENTER) {
|
||||
self.trigger('results:select');
|
||||
}
|
||||
} else {
|
||||
if (key == KEYS.ENTER || key == KEYS.SPACE) {
|
||||
self.trigger('open');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
container.on('selection:update', function (params) {
|
||||
self.update(params.data);
|
||||
});
|
||||
@ -897,7 +1007,7 @@ define('select2/selection/multiple',[
|
||||
MultipleSelection.prototype.selectionContainer = function () {
|
||||
var $container = $(
|
||||
'<li class="choice">' +
|
||||
'<span class="remove">×</span>' +
|
||||
'<span class="remove" role="presentation">×</span>' +
|
||||
'</li>'
|
||||
);
|
||||
|
||||
@ -1327,7 +1437,7 @@ define('select2/dropdown/search',[
|
||||
|
||||
var $search = $(
|
||||
'<span class="search">' +
|
||||
'<input type="search" name="search" />' +
|
||||
'<input type="search" name="search" tabindex="-1" role="textbox" />' +
|
||||
'</span>'
|
||||
);
|
||||
|
||||
@ -1350,6 +1460,14 @@ define('select2/dropdown/search',[
|
||||
});
|
||||
});
|
||||
|
||||
container.on('open', function () {
|
||||
self.$search.attr('tabindex', 0);
|
||||
});
|
||||
|
||||
container.on('close', function () {
|
||||
self.$search.attr('tabindex', -1);
|
||||
});
|
||||
|
||||
container.on('results:all', function (params) {
|
||||
if (params.query.term == null || params.query.term === '') {
|
||||
var showSearch = self.showSearch(params);
|
||||
@ -1537,10 +1655,20 @@ define('select2/core',[
|
||||
});
|
||||
});
|
||||
|
||||
this.selection.on('open', function () {
|
||||
self.trigger('open');
|
||||
});
|
||||
this.selection.on('close', function () {
|
||||
self.trigger('close');
|
||||
});
|
||||
this.selection.on('toggle', function () {
|
||||
self.toggleDropdown();
|
||||
});
|
||||
|
||||
this.selection.on('results:select', function () {
|
||||
self.trigger('results:select');
|
||||
});
|
||||
|
||||
this.selection.on('unselected', function (params) {
|
||||
self.trigger('unselect', params);
|
||||
|
||||
@ -1589,18 +1717,23 @@ define('select2/core',[
|
||||
// Hide the original select
|
||||
|
||||
$element.hide();
|
||||
$element.attr('tabindex', '-1');
|
||||
};
|
||||
|
||||
Utils.Extend(Select2, Utils.Observable);
|
||||
|
||||
Select2.prototype.toggleDropdown = function () {
|
||||
if (this.$container.hasClass('open')) {
|
||||
if (this.isOpen()) {
|
||||
this.trigger('close');
|
||||
} else {
|
||||
this.trigger('open');
|
||||
}
|
||||
};
|
||||
|
||||
Select2.prototype.isOpen = function () {
|
||||
return this.$container.hasClass('open');
|
||||
};
|
||||
|
||||
Select2.prototype.render = function () {
|
||||
var $container = $(
|
||||
'<span class="select2 select2-container select2-theme-default">' +
|
||||
|
2
dist/js/select2.min.js
vendored
2
dist/js/select2.min.js
vendored
File diff suppressed because one or more lines are too long
@ -48,6 +48,10 @@ $(document).ready(function() {
|
||||
<div class="col-md-4">
|
||||
<h1>Multiple select boxes</h1>
|
||||
|
||||
<p>
|
||||
<select class="js-states" multiple="multiple"></select>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Select2 also supports multi-value select boxes. The select below is declared with the <code>multiple</code> attribute.
|
||||
</p>
|
||||
|
17
src/js/select2/core.js
vendored
17
src/js/select2/core.js
vendored
@ -68,10 +68,20 @@ define([
|
||||
});
|
||||
});
|
||||
|
||||
this.selection.on('open', function () {
|
||||
self.trigger('open');
|
||||
});
|
||||
this.selection.on('close', function () {
|
||||
self.trigger('close');
|
||||
});
|
||||
this.selection.on('toggle', function () {
|
||||
self.toggleDropdown();
|
||||
});
|
||||
|
||||
this.selection.on('results:select', function () {
|
||||
self.trigger('results:select');
|
||||
});
|
||||
|
||||
this.selection.on('unselected', function (params) {
|
||||
self.trigger('unselect', params);
|
||||
|
||||
@ -120,18 +130,23 @@ define([
|
||||
// Hide the original select
|
||||
|
||||
$element.hide();
|
||||
$element.attr('tabindex', '-1');
|
||||
};
|
||||
|
||||
Utils.Extend(Select2, Utils.Observable);
|
||||
|
||||
Select2.prototype.toggleDropdown = function () {
|
||||
if (this.$container.hasClass('open')) {
|
||||
if (this.isOpen()) {
|
||||
this.trigger('close');
|
||||
} else {
|
||||
this.trigger('open');
|
||||
}
|
||||
};
|
||||
|
||||
Select2.prototype.isOpen = function () {
|
||||
return this.$container.hasClass('open');
|
||||
};
|
||||
|
||||
Select2.prototype.render = function () {
|
||||
var $container = $(
|
||||
'<span class="select2 select2-container select2-theme-default">' +
|
||||
|
10
src/js/select2/dropdown/search.js
vendored
10
src/js/select2/dropdown/search.js
vendored
@ -8,7 +8,7 @@ define([
|
||||
|
||||
var $search = $(
|
||||
'<span class="search">' +
|
||||
'<input type="search" name="search" />' +
|
||||
'<input type="search" name="search" tabindex="-1" role="textbox" />' +
|
||||
'</span>'
|
||||
);
|
||||
|
||||
@ -31,6 +31,14 @@ define([
|
||||
});
|
||||
});
|
||||
|
||||
container.on('open', function () {
|
||||
self.$search.attr('tabindex', 0);
|
||||
});
|
||||
|
||||
container.on('close', function () {
|
||||
self.$search.attr('tabindex', -1);
|
||||
});
|
||||
|
||||
container.on('results:all', function (params) {
|
||||
if (params.query.term == null || params.query.term === '') {
|
||||
var showSearch = self.showSearch(params);
|
||||
|
39
src/js/select2/keys.js
vendored
Normal file
39
src/js/select2/keys.js
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
define([
|
||||
|
||||
], function () {
|
||||
var KEYS = {
|
||||
BACKSPACE: 8,
|
||||
TAB: 9,
|
||||
ENTER: 13,
|
||||
SHIFT: 16,
|
||||
CTRL: 17,
|
||||
ALT: 18,
|
||||
ESC: 27,
|
||||
SPACE: 32,
|
||||
PAGE_UP: 33,
|
||||
PAGE_DOWN: 34,
|
||||
END: 35,
|
||||
HOME: 36,
|
||||
LEFT: 37,
|
||||
UP: 38,
|
||||
RIGHT: 39,
|
||||
DOWN: 40,
|
||||
DELETE: 46,
|
||||
|
||||
isArrow: function (k) {
|
||||
k = k.which ? k.which : k;
|
||||
|
||||
switch (k) {
|
||||
case KEY.LEFT:
|
||||
case KEY.RIGHT:
|
||||
case KEY.UP:
|
||||
case KEY.DOWN:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
return KEYS;
|
||||
});
|
69
src/js/select2/results.js
vendored
69
src/js/select2/results.js
vendored
@ -12,7 +12,7 @@ define([
|
||||
|
||||
Results.prototype.render = function () {
|
||||
var $results = $(
|
||||
'<ul class="options"></ul>'
|
||||
'<ul class="options" role="listbox"></ul>'
|
||||
);
|
||||
|
||||
this.$results = $results;
|
||||
@ -52,28 +52,42 @@ define([
|
||||
return s.id.toString();
|
||||
});
|
||||
|
||||
self.$results.find('.option.selected').removeClass('selected');
|
||||
|
||||
var $options = self.$results.find('.option');
|
||||
var $options = self.$results.find('.option[aria-selected]');
|
||||
|
||||
$options.each(function () {
|
||||
var $option = $(this);
|
||||
var item = $option.data('data');
|
||||
|
||||
if (item.id != null && selectedIds.indexOf(item.id.toString()) > -1) {
|
||||
$option.addClass('selected');
|
||||
$option.attr('aria-selected', 'true');
|
||||
} else {
|
||||
$option.attr('aria-selected', 'false');
|
||||
}
|
||||
});
|
||||
|
||||
var $selected = $options.filter('[aria-selected=true]');
|
||||
|
||||
// Check if there are any selected options
|
||||
if ($selected.length > 0) {
|
||||
// If there are selected options, highlight the first
|
||||
$selected.first().trigger('mouseenter');
|
||||
} else {
|
||||
// If there are no selected options, highlight the first option
|
||||
// in the dropdown
|
||||
$options.first().trigger('mouseenter');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Results.prototype.option = function (data) {
|
||||
var $option = $(
|
||||
'<li class="option highlightable selectable"></li>'
|
||||
'<li class="option" role="option" aria-selected="false"></li>'
|
||||
);
|
||||
|
||||
if (data.children) {
|
||||
$option.addClass('group').removeClass('highlightable selectable');
|
||||
$option
|
||||
.addClass('group')
|
||||
.removeAttr('aria-selected');
|
||||
|
||||
var $label = $('<strong class="group-label"></strong>');
|
||||
$label.html(data.text);
|
||||
@ -99,11 +113,13 @@ define([
|
||||
}
|
||||
|
||||
if (data.disabled) {
|
||||
$option.removeClass('selectable highlightable').addClass('disabled');
|
||||
$option
|
||||
.removeAttr('aria-selected')
|
||||
.attr('aria-disabled', 'true');
|
||||
}
|
||||
|
||||
if (data.id == null) {
|
||||
$option.removeClass('selectable highlightable');
|
||||
$option.removeClass('aria-selected');
|
||||
}
|
||||
|
||||
$option.data('data', data);
|
||||
@ -135,11 +151,40 @@ define([
|
||||
self.setClasses();
|
||||
});
|
||||
|
||||
this.$results.on('mouseup', '.option.selectable', function (evt) {
|
||||
container.on('open', function () {
|
||||
// When the dropdown is open, aria-expended="true"
|
||||
self.$results.attr('aria-expanded', 'true');
|
||||
|
||||
self.setClasses();
|
||||
});
|
||||
|
||||
container.on('close', function () {
|
||||
// When the dropdown is closed, aria-expended="false"
|
||||
self.$results.attr('aria-expanded', 'false');
|
||||
});
|
||||
|
||||
container.on('results:select', function () {
|
||||
var $highlighted = self.$results.find('.highlighted');
|
||||
|
||||
var data = $highlighted.data('data');
|
||||
|
||||
if ($highlighted.attr('aria-selected') == 'true') {
|
||||
self.trigger('unselected', {
|
||||
data: data
|
||||
});
|
||||
} else {
|
||||
self.trigger('selected', {
|
||||
data: data
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.$results.on('mouseup', '.option[aria-selected]', function (evt) {
|
||||
var $this = $(this);
|
||||
|
||||
var data = $this.data('data');
|
||||
if ($this.hasClass('selected')) {
|
||||
|
||||
if ($this.attr('aria-selected') === 'true') {
|
||||
self.trigger('unselected', {
|
||||
originalEvent: evt,
|
||||
data: data
|
||||
@ -154,7 +199,7 @@ define([
|
||||
});
|
||||
});
|
||||
|
||||
this.$results.on('mouseenter', '.option.highlightable', function (evt) {
|
||||
this.$results.on('mouseenter', '.option[aria-selected]', function (evt) {
|
||||
self.$results.find('.option.highlighted').removeClass('highlighted');
|
||||
$(this).addClass('highlighted');
|
||||
});
|
||||
|
2
src/js/select2/selection/multiple.js
vendored
2
src/js/select2/selection/multiple.js
vendored
@ -58,7 +58,7 @@ define([
|
||||
MultipleSelection.prototype.selectionContainer = function () {
|
||||
var $container = $(
|
||||
'<li class="choice">' +
|
||||
'<span class="remove">×</span>' +
|
||||
'<span class="remove" role="presentation">×</span>' +
|
||||
'</li>'
|
||||
);
|
||||
|
||||
|
31
src/js/select2/selection/single.js
vendored
31
src/js/select2/selection/single.js
vendored
@ -1,7 +1,8 @@
|
||||
define([
|
||||
'./base',
|
||||
'../utils'
|
||||
], function (BaseSelection, Utils) {
|
||||
'../utils',
|
||||
'../keys'
|
||||
], function (BaseSelection, Utils, KEYS) {
|
||||
function SingleSelection () {
|
||||
SingleSelection.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
@ -10,11 +11,13 @@ define([
|
||||
|
||||
SingleSelection.prototype.render = function () {
|
||||
var $selection = $(
|
||||
'<span class="single-select">' +
|
||||
'<span class="single-select" tabindex="0">' +
|
||||
'<span class="rendered-selection"></span>' +
|
||||
'</span>'
|
||||
);
|
||||
|
||||
$selection.attr('title', this.$element.attr('title'));
|
||||
|
||||
this.$selection = $selection;
|
||||
|
||||
return $selection;
|
||||
@ -36,6 +39,28 @@ define([
|
||||
});
|
||||
});
|
||||
|
||||
this.$selection.on('focus', function (evt) {
|
||||
// User focuses on the container
|
||||
});
|
||||
|
||||
this.$selection.on('blur', function (evt) {
|
||||
// User exits the container
|
||||
});
|
||||
|
||||
this.$selection.on('keyup', function (evt) {
|
||||
var key = evt.which;
|
||||
|
||||
if (container.isOpen()) {
|
||||
if (key == KEYS.ENTER) {
|
||||
self.trigger('results:select');
|
||||
}
|
||||
} else {
|
||||
if (key == KEYS.ENTER || key == KEYS.SPACE) {
|
||||
self.trigger('open');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
container.on('selection:update', function (params) {
|
||||
self.update(params.data);
|
||||
});
|
||||
|
@ -36,11 +36,14 @@
|
||||
padding: 0;
|
||||
|
||||
.option {
|
||||
cursor: pointer;
|
||||
padding: 6px;
|
||||
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
|
||||
&[aria-selected] {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,15 +93,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
&[aria-disabled=true] {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
&[aria-selected=true] {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
&.highlightable.highlighted {
|
||||
&[aria-selected].highlighted {
|
||||
background-color: #5897fb;
|
||||
color: white;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user