diff --git a/chrome/content/zotero/elements/colorPicker.js b/chrome/content/zotero/elements/colorPicker.js index cf6e8faf21..63dd809e27 100644 --- a/chrome/content/zotero/elements/colorPicker.js +++ b/chrome/content/zotero/elements/colorPicker.js @@ -67,6 +67,38 @@ set colors(colors) { 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: 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() { return this.getAttribute('cols') || 3; @@ -75,6 +107,10 @@ set cols(cols) { this.setAttribute('cols', cols); } + + get rows() { + return Math.ceil(this.colors.length / this.cols); + } get tileWidth() { return this.getAttribute('tileWidth') || 24; @@ -102,13 +138,78 @@ init() { 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', () => { - grid.style.gridTemplateColumns = `repeat(${this.cols}, ${this.tileWidth}px)`; - grid.style.gridAutoRows = `${this.tileHeight}px`; - panel.openPopup(button, 'after_start', 0, 0, false, false); + this.openPopup(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') { 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') { this.querySelector('.button').disabled = !!newVal; } diff --git a/chrome/content/zotero/tagColorChooser.js b/chrome/content/zotero/tagColorChooser.js index 77cfe8580f..d6834a9474 100644 --- a/chrome/content/zotero/tagColorChooser.js +++ b/chrome/content/zotero/tagColorChooser.js @@ -52,15 +52,6 @@ var Zotero_Tag_Color_Chooser = new function() { var colorPicker = document.getElementById('color-picker'); 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'); maxTags.value = Zotero.getString('tagColorChooser.maxTags', Zotero.Tags.MAX_COLORED_TAGS); diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties index c67561bfbc..d6b5607167 100644 --- a/chrome/locale/en-US/zotero/zotero.properties +++ b/chrome/locale/en-US/zotero/zotero.properties @@ -97,13 +97,16 @@ general.insert = Insert general.username = Username general.password = Password -general.yellow = Yellow general.red = Red +general.orange = Orange +general.yellow = Yellow general.green = Green +general.teal = Teal general.blue = Blue general.purple = Purple general.magenta = Magenta -general.orange = Orange +general.violet = Violet +general.maroon = Maroon general.gray = Gray general.operationInProgress = A Zotero operation is currently in progress. diff --git a/scss/elements/_colorPicker.scss b/scss/elements/_colorPicker.scss index d0eab36525..89dab0c56b 100644 --- a/scss/elements/_colorPicker.scss +++ b/scss/elements/_colorPicker.scss @@ -1,5 +1,5 @@ color-picker { - button { + .button { width: 38px; height: 24px; appearance: none; @@ -25,7 +25,8 @@ color-picker { gap: 2px; } - .grid-tile:hover { + .grid-tile, .grid-tile:hover { + appearance: none; border: 0; }