Commit 3dcc515f authored by Rebecca Blundell's avatar Rebecca Blundell Committed by Robert Lyon

Bug 1840108: Customisations to select2 4.09

Adding in changes made as per the select2 README.Mahara
and adding commit details to the README where that was helpful in finding
the changes.

behatnotneeded

Change-Id: I8579ba86d303ecc3b1d5ec50fb9e53972c8c2ff9
parent 52e5dffc
......@@ -8,22 +8,32 @@ Select2 is a jQuery-based replacement for <select> browser elements. It turns th
interactive widgets, supports searching, ajax, and infinite scrolling of results.
Changes:
* Copy the dist/js/select2.full.min.js to js/select2/
* Copy the dist/js/select2.full.js to js/select2/
* Copy the dist/js/i18n/* directory to js/select2/i18n/
* Copy the src/scss/* files to theme/raw/sass/lib/select2/
* Added styling to decrease size of text in the menus
* Added a 'readonly' status to an option to hide the 'x' (stop it being removable)
* Accessibility improvements
These are changes to select2.full.js as follows:
* Accessibility improvements (commit 81f826e7673503ebd86e89076ca971571744d1c8)
* Modify the AJAX data adapter and search box so that items are read out when moving up and
down through them with the keyboard
* Link select2 instances to the label(s) of the original <select>
* Allow removing tags with the keyboard
* Hide original <select> completely instead of leaving it accessible to screen readers
* Keep focus position when loading more elements with infinite scrolling
* Add label to "Remove tag" button
* Make "Remove tag" button work with the keyboard
* Adding the 'aria-hidden="true"' to presentation icons
* Adding ability to remove tag via 'enter' key if one is focused on the 'x' of a tag
*
* set background for exclude tags (commit 1f9bbefe1ddbada754591eb0503a4f5d628fe4ab)
* user profile picture in select2 styling (commit 1bdfef8ca2056a17ce14268970be9f969d6d6930)
* Adding the 'aria-hidden="true"' to presentation icons (commit 4ac89c31a719a9f63be6555c4d1a094fd2b09d0e)
* Adding ability to remove tag via 'enter' key if one is focused on the 'x' of a tag (commit 5ec92cddcf24fca18fdb1b24707216a5ea24bde8)
* Add label to "Remove tag" button (look for the MultipleSelection.prototype.selectionContainer function and the call to it. Worked in 18.04 and hopefully fixed in 19.10)
There are several files including custom styling for select2 in the Mahara codebase which override the 3rd party styling. There are also changes to the provided scss files. These changes look like they are being made already, so I haven't done this. (Just leaving it because it was in the Readme before and probably should be tested for.):
* Added styling to decrease size of text in the menus
* Added a 'readonly' status to an option to hide the 'x' (stop it being removable)
_multiple.scss y
* set background for exclude tags
(commit 1f9bbefe1ddbada754591eb0503a4f5d628fe4ab)
_dropdown.scss
* user profile picture in select2 styling
(commit 1bdfef8ca2056a17ce14268970be9f969d6d6930)
......@@ -877,8 +877,9 @@ S2.define('select2/results',[
this.clear();
this.hideLoading();
var messageId = this.data.generateResultId({ id: this.$results.attr('id') }, {});
var $message = $(
'<li role="alert" aria-live="assertive"' +
'<li id="' +messageId + '" role="alert" aria-live="assertive"' +
' class="select2-results__option"></li>'
);
......@@ -893,6 +894,7 @@ S2.define('select2/results',[
$message[0].className += ' select2-results__message';
this.$results.append($message);
this.trigger('results:speak', { id: messageId});
};
Results.prototype.hideMessages = function () {
......@@ -1023,6 +1025,7 @@ S2.define('select2/results',[
if ((data.element != null && matches.call(data.element, ':disabled')) ||
(data.element == null && data.disabled)) {
delete attrs['aria-selected'];
attrs['aria-disabled'] = 'true';
}
......@@ -1043,6 +1046,13 @@ S2.define('select2/results',[
attrs['aria-label'] = data.text;
delete attrs['aria-selected'];
}
if (data.element) {
$element = $(data.element);
if ($element.hasClass('readonly')) {
var currentclass = option.getAttribute('class');
option.setAttribute('class', 'readonly ' + currentclass);
}
}
for (var attr in attrs) {
var val = attrs[attr];
......@@ -1104,10 +1114,12 @@ S2.define('select2/results',[
});
container.on('results:append', function (params) {
var previousIndex = self.$results
.find('.select2-results__option[aria-selected]').length - 1;
self.append(params.data);
if (container.isOpen()) {
self.setClasses();
self.setClasses(previousIndex);
}
});
......@@ -1290,10 +1302,12 @@ S2.define('select2/results',[
if ($this.attr('aria-selected') === 'true') {
if (self.options.get('multiple')) {
self.trigger('unselect', {
originalEvent: evt,
data: data
});
if (!$this.hasClass('readonly')) {
self.trigger('unselect', {
originalEvent: evt,
data: data
});
}
} else {
self.trigger('close', {});
}
......@@ -1318,6 +1332,9 @@ S2.define('select2/results',[
data: data,
element: $(this)
});
self.trigger('results:speak', {
id: $(this).attr('id')
});
});
};
......@@ -1418,7 +1435,8 @@ S2.define('select2/selection/base',[
BaseSelection.prototype.render = function () {
var $selection = $(
'<span class="select2-selection" role="combobox" ' +
' aria-haspopup="true" aria-expanded="false">' +
' aria-haspopup="true" aria-expanded="false" aria-labelledby="' +
this.options.labels.join(' ') + '">' +
'</span>'
);
......@@ -1462,9 +1480,9 @@ S2.define('select2/selection/base',[
}
});
container.on('results:focus', function (params) {
self.$selection.attr('aria-activedescendant', params.data._resultId);
});
// container.on('results:focus', function (params) {
// self.$selection.attr('aria-activedescendant', params.data._resultId);
// });
container.on('selection:update', function (params) {
self.update(params.data);
......@@ -1578,8 +1596,8 @@ S2.define('select2/selection/single',[
$selection.html(
'<span class="select2-selection__rendered"></span>' +
'<span class="select2-selection__arrow" role="presentation">' +
'<b role="presentation"></b>' +
'<span class="select2-selection__arrow" role="presentation" aria-hidden="true">' +
'<b role="presentation" aria-hidden="true"></b>' +
'</span>'
);
......@@ -1710,18 +1728,22 @@ S2.define('select2/selection/multiple',[
return;
}
var $remove = $(this);
var $selection = $remove.parent();
var data = Utils.GetData($selection[0], 'data');
self.trigger('unselect', {
var $remove = $(evt.target).closest('.select2-selection__choice__remove');
if ($remove.length) {
var $selection = $remove.parent();
var data = Utils.GetData($selection[0], 'data');
self.trigger('unselect', {
originalEvent: evt,
data: data
});
}
);
else {
self.trigger('toggle', {
originalEvent: evt
});
};
});
};
MultipleSelection.prototype.clear = function () {
var $rendered = this.$selection.find('.select2-selection__rendered');
......@@ -1736,12 +1758,22 @@ S2.define('select2/selection/multiple',[
return escapeMarkup(template(data, container));
};
MultipleSelection.prototype.selectionContainer = function () {
MultipleSelection.prototype.selectionContainer = function (selection, readonly) {
if (readonly) {
state = 'readonly';
button = '';
}
else {
state = 'remove';
button = '<button class="select2-hidden-accessible">' +
get_string_ajax('element.select.remove', 'pieforms', selection.text || selection.title) +
'</button>&times;';
}
var $container = $(
'<li class="select2-selection__choice">' +
'<span class="select2-selection__choice__remove" role="presentation">' +
'&times;' +
'</span>' +
'<span class="select2-selection__choice__' + state + '"role="presentation">' + button + '</span>' +
'</li>'
);
......@@ -1760,7 +1792,9 @@ S2.define('select2/selection/multiple',[
for (var d = 0; d < data.length; d++) {
var selection = data[d];
var $selection = this.selectionContainer();
var readonly = $(selection.element).hasClass('readonly');
var $selection = this.selectionContainer(selection, readonly);
var formatted = this.display(selection, $selection);
$selection.append(formatted);
......@@ -2009,6 +2043,11 @@ S2.define('select2/selection/search',[
self.$search.trigger('focus');
});
container.on('results:speak', function (params) {
self.$search.attr('aria-activedescendant', params.id);
});
container.on('results:focus', function (params) {
if (params.data._resultId) {
self.$search.attr('aria-activedescendant', params.data._resultId);
......@@ -3602,6 +3641,10 @@ S2.define('select2/data/ajax',[
function request () {
var $request = options.transport(options, function (data) {
var results = self.processResults(data, params);
var items = results.results;
for (var i = 0; i < items.length; i++) {
items[i] = self._normalizeItem(items[i]);
}
if (self.options.get('debug') && window.console && console.error) {
// Check to make sure that the response included a `results` key.
......@@ -5319,6 +5362,7 @@ S2.define('select2/core',[
if (Utils.GetData($element[0], 'select2') != null) {
Utils.GetData($element[0], 'select2').destroy();
}
var self = this;
this.$element = $element;
......@@ -5328,6 +5372,10 @@ S2.define('select2/core',[
this.options = new Options(options, $element);
if (this.options.labels == null) {
this.options.labels = this._findOriginalLabels();
}
Select2.__super__.constructor.call(this);
// Set up the tabindex
......@@ -5388,8 +5436,9 @@ S2.define('select2/core',[
});
// Hide the original select
$element.addClass('select2-hidden-accessible');
$element.attr('aria-hidden', 'true');
// $element.addClass('select2-hidden-accessible');
$element.hide();
// $element.attr('aria-hidden', 'true');
// Synchronize any monitored attributes
this._syncAttributes();
......@@ -5401,6 +5450,22 @@ S2.define('select2/core',[
};
Utils.Extend(Select2, Utils.Observable);
Select2.prototype._findOriginalLabels = function() {
var self = this;
var id = this.$element.attr('id');
if (id) {
return jQuery.map($('label[for="' + id + '"]'), function(el, i) {
if (!$(el).attr('id')) {
$(el).attr('id', self.id + '-label-' + i);
}
return $(el).attr('id');
});
}
else {
return [];
}
}
Select2.prototype._generateId = function ($element) {
var id = '';
......@@ -5664,7 +5729,18 @@ S2.define('select2/core',[
}
} else {
if (key === KEYS.ENTER || key === KEYS.SPACE ||
(key === KEYS.DOWN && evt.altKey)) {
(key === KEYS.DOWN && evt.altKey) &&
$(evt.target).hasClass('select2-selection')) {
var $remove = $(evt.target).closest('.select2-selection__choice__remove');
if ($remove.length) {
var $selection = $remove.parent();
var data = $selection.data('data');
self.trigger('unselect', {
originalEvent: evt,
data: data
});
}
self.open();
evt.preventDefault();
......
......@@ -13,7 +13,7 @@
width: 100%;
z-index: 1051;
z-index: 999;
}
.select2-results {
......@@ -27,10 +27,20 @@
}
.select2-results__option {
padding: 6px;
padding: 4px;
user-select: none;
-webkit-user-select: none;
overflow: auto;
img {
margin-right: 4px;
display: block;
float: left;
}
span {
line-height: 1;
vertical-align: text-top;
}
&[aria-selected] {
cursor: pointer;
......
......@@ -16,6 +16,9 @@
text-overflow: ellipsis;
white-space: nowrap;
}
.tagexcluded {
background: #ffd9d9 !important;
}
}
.select2-search--inline {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment