fx-compat: Make color picker CE accessible via keyboard and VoiceOver (#2933)
This commit is contained in:
parent
ffdfc73d47
commit
0a94e8fdf0
4 changed files with 114 additions and 32 deletions
|
@ -67,6 +67,38 @@
|
||||||
set colors(colors) {
|
set colors(colors) {
|
||||||
this.setAttribute('colors', colors.join(','));
|
this.setAttribute('colors', colors.join(','));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get colorLabels() {
|
||||||
|
if (this.hasAttribute('color-labels')) {
|
||||||
|
return this.getAttribute('color-labels').split(',').map((label) => {
|
||||||
|
let localized;
|
||||||
|
try {
|
||||||
|
localized = Zotero.getString(label);
|
||||||
|
}
|
||||||
|
catch (e) {}
|
||||||
|
if (!localized || localized == label) {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return localized;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (this.hasAttribute('colors')) {
|
||||||
|
Zotero.debug('WARNING: <color-picker> CE: Set color-labels when setting colors');
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
'general.red', 'general.orange', 'general.gray',
|
||||||
|
'general.green', 'general.teal', 'general.blue',
|
||||||
|
'general.purple', 'general.violet', 'general.maroon'
|
||||||
|
].map(label => Zotero.getString(label));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set colorLabels(colorLabels) {
|
||||||
|
this.setAttribute('color-labels', colorLabels.join(','));
|
||||||
|
}
|
||||||
|
|
||||||
get cols() {
|
get cols() {
|
||||||
return this.getAttribute('cols') || 3;
|
return this.getAttribute('cols') || 3;
|
||||||
|
@ -75,6 +107,10 @@
|
||||||
set cols(cols) {
|
set cols(cols) {
|
||||||
this.setAttribute('cols', cols);
|
this.setAttribute('cols', cols);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get rows() {
|
||||||
|
return Math.ceil(this.colors.length / this.cols);
|
||||||
|
}
|
||||||
|
|
||||||
get tileWidth() {
|
get tileWidth() {
|
||||||
return this.getAttribute('tileWidth') || 24;
|
return this.getAttribute('tileWidth') || 24;
|
||||||
|
@ -102,13 +138,78 @@
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
let button = this.querySelector('.button');
|
let button = this.querySelector('.button');
|
||||||
let panel = this.querySelector('.panel');
|
|
||||||
let grid = this.querySelector('.grid');
|
button.addEventListener('keydown', (event) => {
|
||||||
|
if (event.key == ' ' || event.key == 'Enter' || event.key == 'ArrowDown') {
|
||||||
|
event.preventDefault();
|
||||||
|
this.openPopup(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
button.addEventListener('click', () => {
|
button.addEventListener('click', () => {
|
||||||
grid.style.gridTemplateColumns = `repeat(${this.cols}, ${this.tileWidth}px)`;
|
this.openPopup(false);
|
||||||
grid.style.gridAutoRows = `${this.tileHeight}px`;
|
});
|
||||||
panel.openPopup(button, 'after_start', 0, 0, false, false);
|
}
|
||||||
|
|
||||||
|
openPopup(focus = false) {
|
||||||
|
this.buildGrid();
|
||||||
|
|
||||||
|
let button = this.querySelector('.button');
|
||||||
|
let panel = this.querySelector('.panel');
|
||||||
|
let grid = this.querySelector('.grid');
|
||||||
|
grid.style.gridTemplateColumns = `repeat(${this.cols}, ${this.tileWidth}px)`;
|
||||||
|
grid.style.gridAutoRows = `${this.tileHeight}px`;
|
||||||
|
|
||||||
|
if (focus) {
|
||||||
|
panel.addEventListener('popupshown', () => {
|
||||||
|
grid.querySelector('.grid-tile').focus();
|
||||||
|
}, { once: true });
|
||||||
|
}
|
||||||
|
panel.openPopup(button, 'after_start', 0, 0, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
buildGrid() {
|
||||||
|
let grid = this.querySelector('.grid');
|
||||||
|
grid.innerHTML = '';
|
||||||
|
let colors = this.colors;
|
||||||
|
let colorLabels = this.colorLabels;
|
||||||
|
colors.forEach((color, i) => {
|
||||||
|
let tile = document.createElement('button');
|
||||||
|
tile.setAttribute('aria-label', colorLabels[i]);
|
||||||
|
tile.classList.add('grid-tile');
|
||||||
|
tile.style.backgroundColor = color;
|
||||||
|
|
||||||
|
tile.addEventListener('click', () => {
|
||||||
|
this.color = color;
|
||||||
|
this.querySelector('.panel').hidePopup();
|
||||||
|
});
|
||||||
|
tile.addEventListener('keydown', (event) => {
|
||||||
|
switch (event.key) {
|
||||||
|
case 'ArrowLeft':
|
||||||
|
(tile.previousElementSibling || tile.parentElement.lastElementChild).focus();
|
||||||
|
break;
|
||||||
|
case 'ArrowRight':
|
||||||
|
(tile.nextElementSibling || tile.parentElement.firstElementChild).focus();
|
||||||
|
break;
|
||||||
|
case 'ArrowUp': {
|
||||||
|
let upIndex = (Array.from(tile.parentElement.children).indexOf(tile) - this.cols)
|
||||||
|
% (this.rows * this.cols);
|
||||||
|
if (upIndex < 0) {
|
||||||
|
upIndex += this.rows * this.cols;
|
||||||
|
}
|
||||||
|
tile.parentElement.children[upIndex].focus();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'ArrowDown': {
|
||||||
|
let downIndex = (Array.from(tile.parentElement.children).indexOf(tile) + this.cols)
|
||||||
|
% (this.rows * this.cols);
|
||||||
|
tile.parentElement.children[downIndex].focus();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
grid.append(tile);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,20 +221,6 @@
|
||||||
if (attrName == 'color') {
|
if (attrName == 'color') {
|
||||||
this.querySelector('.button-tile').style.backgroundColor = newVal;
|
this.querySelector('.button-tile').style.backgroundColor = newVal;
|
||||||
}
|
}
|
||||||
else if (attrName == 'colors') {
|
|
||||||
let grid = this.querySelector('.grid');
|
|
||||||
grid.innerHTML = '';
|
|
||||||
for (let color of newVal.split(',')) {
|
|
||||||
let tile = document.createElement('div');
|
|
||||||
tile.classList.add('grid-tile');
|
|
||||||
tile.style.backgroundColor = color;
|
|
||||||
tile.addEventListener('click', () => {
|
|
||||||
this.color = color;
|
|
||||||
this.querySelector('.panel').hidePopup();
|
|
||||||
});
|
|
||||||
grid.append(tile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (attrName == 'disabled') {
|
else if (attrName == 'disabled') {
|
||||||
this.querySelector('.button').disabled = !!newVal;
|
this.querySelector('.button').disabled = !!newVal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,15 +52,6 @@ var Zotero_Tag_Color_Chooser = new function() {
|
||||||
var colorPicker = document.getElementById('color-picker');
|
var colorPicker = document.getElementById('color-picker');
|
||||||
var tagPosition = document.getElementById('tag-position');
|
var tagPosition = document.getElementById('tag-position');
|
||||||
|
|
||||||
colorPicker.setAttribute('cols', 3);
|
|
||||||
colorPicker.setAttribute('tileWidth', 24);
|
|
||||||
colorPicker.setAttribute('tileHeight', 24);
|
|
||||||
colorPicker.colors = [
|
|
||||||
'#FF6666', '#FF8C19', '#999999',
|
|
||||||
'#5FB236', '#009980', '#2EA8E5',
|
|
||||||
'#576DD9', '#A28AE5', '#A6507B'
|
|
||||||
];
|
|
||||||
|
|
||||||
var maxTags = document.getElementById('max-tags');
|
var maxTags = document.getElementById('max-tags');
|
||||||
maxTags.value = Zotero.getString('tagColorChooser.maxTags', Zotero.Tags.MAX_COLORED_TAGS);
|
maxTags.value = Zotero.getString('tagColorChooser.maxTags', Zotero.Tags.MAX_COLORED_TAGS);
|
||||||
|
|
||||||
|
|
|
@ -97,13 +97,16 @@ general.insert = Insert
|
||||||
general.username = Username
|
general.username = Username
|
||||||
general.password = Password
|
general.password = Password
|
||||||
|
|
||||||
general.yellow = Yellow
|
|
||||||
general.red = Red
|
general.red = Red
|
||||||
|
general.orange = Orange
|
||||||
|
general.yellow = Yellow
|
||||||
general.green = Green
|
general.green = Green
|
||||||
|
general.teal = Teal
|
||||||
general.blue = Blue
|
general.blue = Blue
|
||||||
general.purple = Purple
|
general.purple = Purple
|
||||||
general.magenta = Magenta
|
general.magenta = Magenta
|
||||||
general.orange = Orange
|
general.violet = Violet
|
||||||
|
general.maroon = Maroon
|
||||||
general.gray = Gray
|
general.gray = Gray
|
||||||
|
|
||||||
general.operationInProgress = A Zotero operation is currently in progress.
|
general.operationInProgress = A Zotero operation is currently in progress.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
color-picker {
|
color-picker {
|
||||||
button {
|
.button {
|
||||||
width: 38px;
|
width: 38px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
|
@ -25,7 +25,8 @@ color-picker {
|
||||||
gap: 2px;
|
gap: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-tile:hover {
|
.grid-tile, .grid-tile:hover {
|
||||||
|
appearance: none;
|
||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue