fx-compat: Add color picker CE (#2682)
This commit is contained in:
parent
4dbb2d88b9
commit
4b09edfa42
11 changed files with 203 additions and 181 deletions
|
@ -1,140 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!--
|
|
||||||
An extension of the Mozilla colorpicker that allows for a custom set of colors
|
|
||||||
-->
|
|
||||||
<bindings id="colorpickerBindings"
|
|
||||||
xmlns="http://www.mozilla.org/xbl"
|
|
||||||
xmlns:xbl="http://www.mozilla.org/xbl"
|
|
||||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
|
||||||
|
|
||||||
<binding id="custom-colorpicker" extends="chrome://global/content/bindings/colorpicker.xml#colorpicker">
|
|
||||||
<resources>
|
|
||||||
<stylesheet src="chrome://zotero/skin/bindings/customcolorpicker.css"/>
|
|
||||||
</resources>
|
|
||||||
|
|
||||||
<content>
|
|
||||||
<vbox anonid="tiles" flex="1" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
|
||||||
<hbox>
|
|
||||||
<image class="colorpickertile" color="#000000"/>
|
|
||||||
</hbox>
|
|
||||||
</vbox>
|
|
||||||
</content>
|
|
||||||
|
|
||||||
<implementation implements="nsIDOMEventListener">
|
|
||||||
<constructor><![CDATA[
|
|
||||||
this.initialize();
|
|
||||||
|
|
||||||
this._colors = this.getAttribute('colors');
|
|
||||||
if (this._colors) {
|
|
||||||
this._cols = this.getAttribute('cols');
|
|
||||||
}
|
|
||||||
this.redraw();
|
|
||||||
]]></constructor>
|
|
||||||
|
|
||||||
<!-- Defaults from the Mozilla colorpicker -->
|
|
||||||
<field name="_defaultColors">
|
|
||||||
[
|
|
||||||
'L#FFFFFF','L#FFCCCC','L#FFCC99','L#FFFF99','L#FFFFCC','L#99FF99','L#99FFFF','L#CCFFFF','L#CCCCFF','L#FFCCFF',
|
|
||||||
'#CCCCCC','#FF6666','#FF9966','L#FFFF66','L#FFFF33','L#66FF99','L#33FFFF','L#66FFFF','#9999FF','#FF99FF',
|
|
||||||
'#C0C0C0','#FF0000','#FF9900','#FFCC66','L#FFFF00','L#33FF33','#66CCCC','#33CCFF','#6666CC','#CC66CC',
|
|
||||||
'#999999','#CC0000','#FF6600','#FFCC33','#FFCC00','#33CC00','#00CCCC','#3366FF','#6633FF','#CC33CC',
|
|
||||||
'#666666','#990000','#CC6600','#CC9933','#999900','#009900','#339999','#3333FF','#6600CC','#993399',
|
|
||||||
'#333333','#660000','#993300','#996633','#666600','#006600','#336666','#000099','#333399','#663366',
|
|
||||||
'#000000','#330000','#663300','#663333','#333300','#003300','#003333','#000066','#330099','#330033'
|
|
||||||
]
|
|
||||||
</field>
|
|
||||||
<field name="_defaultCols">10</field>
|
|
||||||
|
|
||||||
<property name="colors" onget="return this._colors ? this._colors : []">
|
|
||||||
<setter><![CDATA[
|
|
||||||
if (typeof val == 'string') {
|
|
||||||
val = val ? val.split(',') : null;
|
|
||||||
}
|
|
||||||
this._colors = val;
|
|
||||||
this.redraw();
|
|
||||||
]]></setter>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<property name="cols" onget="return this.getAttribute('cols')">
|
|
||||||
<setter><![CDATA[
|
|
||||||
this.setAttribute('cols', val);
|
|
||||||
this.redraw();
|
|
||||||
]]></setter>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<method name="redraw">
|
|
||||||
<body><![CDATA[
|
|
||||||
//Zotero.debug("Redrawing color picker");
|
|
||||||
|
|
||||||
var tiles = document.getAnonymousNodes(this)[0];
|
|
||||||
|
|
||||||
var cols = this.getAttribute('cols') || this._defaultCols;
|
|
||||||
var colors = this._colors.concat() || this._defaultColors.concat();
|
|
||||||
|
|
||||||
while (tiles.hasChildNodes()) {
|
|
||||||
tiles.removeChild(tiles.firstChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
var rows = Math.ceil(colors.length / cols);
|
|
||||||
|
|
||||||
var tileWidth = this.getAttribute('tileWidth');
|
|
||||||
var tileHeight = this.getAttribute('tileHeight');
|
|
||||||
|
|
||||||
for (let i=0; i<rows; i++) {
|
|
||||||
var hbox = document.createElement('hbox');
|
|
||||||
for (let j=0; j<cols; j++) {
|
|
||||||
let color = colors.shift();
|
|
||||||
if (!color) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
let light = color.charAt(0) == 'L';
|
|
||||||
color = light ? color.substr(1) : color;
|
|
||||||
|
|
||||||
let image = document.createElement('image');
|
|
||||||
image.className = 'colorpickertile' + (light ? ' cp-light' : '');
|
|
||||||
image.setAttribute('color', color);
|
|
||||||
|
|
||||||
let dataURI = "data:image/svg+xml,<svg style='background-color: "
|
|
||||||
+ encodeURIComponent(color) + "' xmlns='http://www.w3.org/2000/svg' />";
|
|
||||||
image.setAttribute('src', dataURI);
|
|
||||||
|
|
||||||
if (tileWidth) {
|
|
||||||
image.width = tileWidth;
|
|
||||||
}
|
|
||||||
if (tileHeight) {
|
|
||||||
image.height = tileHeight;
|
|
||||||
}
|
|
||||||
hbox.appendChild(image);
|
|
||||||
}
|
|
||||||
tiles.appendChild(hbox);
|
|
||||||
}
|
|
||||||
]]></body>
|
|
||||||
</method>
|
|
||||||
</implementation>
|
|
||||||
</binding>
|
|
||||||
|
|
||||||
<!-- The content of the Mozilla colorpicker-button, but with a customcolorpicker
|
|
||||||
with some extra inherited attributes instead -->
|
|
||||||
<binding id="custom-colorpicker-button" display="xul:menu"
|
|
||||||
extends="chrome://global/content/bindings/colorpicker.xml#colorpicker-button">
|
|
||||||
<resources>
|
|
||||||
<stylesheet src="chrome://zotero/skin/bindings/customcolorpicker.css"/>
|
|
||||||
</resources>
|
|
||||||
<content>
|
|
||||||
<xul:image class="colorpicker-button-colorbox" anonid="colorbox" flex="1" xbl:inherits="disabled"/>
|
|
||||||
|
|
||||||
<xul:panel class="colorpicker-button-menupopup"
|
|
||||||
anonid="colorpopup" noautofocus="true" level="top"
|
|
||||||
onmousedown="event.stopPropagation()"
|
|
||||||
onpopupshowing="this._colorPicker.onPopupShowing()"
|
|
||||||
onpopuphiding="this._colorPicker.onPopupHiding()"
|
|
||||||
onselect="this._colorPicker.pickerChange()">
|
|
||||||
<xul:customcolorpicker xbl:inherits="palettename,disabled,cols,columns,tileWidth,tileHeight" allowevents="true" anonid="colorpicker"/>
|
|
||||||
</xul:panel>
|
|
||||||
</content>
|
|
||||||
|
|
||||||
<implementation>
|
|
||||||
<property name="colors" onget="return this.mPicker.colors" onset="this.mPicker.colors = val"/>
|
|
||||||
</implementation>
|
|
||||||
</binding>
|
|
||||||
</bindings>
|
|
146
chrome/content/zotero/elements/colorPicker.js
Normal file
146
chrome/content/zotero/elements/colorPicker.js
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
/*
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
|
Copyright © 2020 Corporation for Digital Scholarship
|
||||||
|
Vienna, Virginia, USA
|
||||||
|
https://www.zotero.org
|
||||||
|
|
||||||
|
This file is part of Zotero.
|
||||||
|
|
||||||
|
Zotero is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Zotero is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
{
|
||||||
|
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
|
Services.scriptloader.loadSubScript("chrome://zotero/content/elements/base.js", this);
|
||||||
|
|
||||||
|
class ColorPicker extends XULElementBase {
|
||||||
|
stylesheets = ['chrome://global/skin/', 'chrome://zotero-platform/content/colorPicker.css'];
|
||||||
|
|
||||||
|
content = MozXULElement.parseXULToFragment(`
|
||||||
|
<vbox>
|
||||||
|
<html:button id="button">
|
||||||
|
<html:span id="button-tile"/>
|
||||||
|
</html:button>
|
||||||
|
|
||||||
|
<panel id="panel">
|
||||||
|
<html:div id="grid"/>
|
||||||
|
</panel>
|
||||||
|
</vbox>
|
||||||
|
`);
|
||||||
|
|
||||||
|
get color() {
|
||||||
|
return this.getAttribute('color') || '#000000';
|
||||||
|
}
|
||||||
|
|
||||||
|
set color(color) {
|
||||||
|
this.setAttribute('color', color);
|
||||||
|
}
|
||||||
|
|
||||||
|
get colors() {
|
||||||
|
if (this.hasAttribute('colors')) {
|
||||||
|
return this.getAttribute('colors').split(',');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return [
|
||||||
|
'#FF6666', '#FF8C19', '#999999',
|
||||||
|
'#5FB236', '#009980', '#2EA8E5',
|
||||||
|
'#576DD9', '#A28AE5', '#A6507B'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set colors(colors) {
|
||||||
|
this.setAttribute('colors', colors.join(','));
|
||||||
|
}
|
||||||
|
|
||||||
|
get cols() {
|
||||||
|
return this.getAttribute('cols') || 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
set cols(cols) {
|
||||||
|
this.setAttribute('cols', cols);
|
||||||
|
}
|
||||||
|
|
||||||
|
get tileWidth() {
|
||||||
|
return this.getAttribute('tileWidth') || 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
set tileWidth(width) {
|
||||||
|
this.setAttribute('tileWidth', width);
|
||||||
|
}
|
||||||
|
|
||||||
|
get tileHeight() {
|
||||||
|
return this.getAttribute('tileHeight') || 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
set tileHeight(height) {
|
||||||
|
this.setAttribute('tileHeight', height);
|
||||||
|
}
|
||||||
|
|
||||||
|
get disabled() {
|
||||||
|
return this.hasAttribute('disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
set disabled(disabled) {
|
||||||
|
this.toggleAttribute(disabled, !!disabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
let button = this.shadowRoot.getElementById('button');
|
||||||
|
let panel = this.shadowRoot.getElementById('panel');
|
||||||
|
let grid = this.shadowRoot.getElementById('grid');
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static get observedAttributes() {
|
||||||
|
return ['color', 'colors', 'cols', 'tileWidth', 'tileHeight'];
|
||||||
|
}
|
||||||
|
|
||||||
|
attributeChangedCallback(attrName, oldVal, newVal) {
|
||||||
|
if (attrName == 'color') {
|
||||||
|
this.shadowRoot.getElementById('button-tile').style.backgroundColor = newVal;
|
||||||
|
}
|
||||||
|
else if (attrName == 'colors') {
|
||||||
|
let grid = this.shadowRoot.getElementById('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.shadowRoot.getElementById('panel').hidePopup();
|
||||||
|
});
|
||||||
|
grid.append(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (attrName == 'disabled') {
|
||||||
|
this.shadowRoot.getElementById('button').disabled = !!newVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("color-picker", ColorPicker);
|
||||||
|
}
|
|
@ -30,6 +30,10 @@ var Zotero_Tag_Color_Chooser = new function() {
|
||||||
|
|
||||||
this.init = function () {
|
this.init = function () {
|
||||||
var dialog = document.querySelector('dialog');
|
var dialog = document.querySelector('dialog');
|
||||||
|
|
||||||
|
window.addEventListener('dialogaccept', () => Zotero_Tag_Color_Chooser.onDialogAccept());
|
||||||
|
window.addEventListener('dialogcancel', () => Zotero_Tag_Color_Chooser.onDialogCancel());
|
||||||
|
window.addEventListener('dialogextra1', () => Zotero_Tag_Color_Chooser.onDialogRemoveColor());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Set font size from pref
|
// Set font size from pref
|
||||||
|
|
|
@ -38,19 +38,22 @@
|
||||||
<dialog
|
<dialog
|
||||||
buttons="cancel,accept"
|
buttons="cancel,accept"
|
||||||
buttonlabelaccept="&zotero.tagColorChooser.setColor;"
|
buttonlabelaccept="&zotero.tagColorChooser.setColor;"
|
||||||
buttonlabelextra1="&zotero.tagColorChooser.removeColor;"
|
buttonlabelextra1="&zotero.tagColorChooser.removeColor;">
|
||||||
ondialogaccept="Zotero_Tag_Color_Chooser.onDialogAccept()"
|
|
||||||
ondialogcancel="Zotero_Tag_Color_Chooser.onDialogCancel()"
|
<script>
|
||||||
ondialogextra1="Zotero_Tag_Color_Chooser.onDialogRemoveColor()"
|
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
>
|
|
||||||
|
Services.scriptloader.loadSubScript("chrome://zotero/content/include.js", this);
|
||||||
<script src="include.js"/>
|
Services.scriptloader.loadSubScript("chrome://zotero/content/tagColorChooser.js", this);
|
||||||
<script src="tagColorChooser.js"/>
|
|
||||||
|
// Custom elements
|
||||||
|
Services.scriptloader.loadSubScript("chrome://zotero/content/elements/colorPicker.js", this);
|
||||||
|
</script>
|
||||||
|
|
||||||
<vbox id="tag-color-chooser-container">
|
<vbox id="tag-color-chooser-container">
|
||||||
<hbox align="center">
|
<hbox align="center">
|
||||||
<label value="&zotero.tagColorChooser.color;" control="color-picker"/>
|
<label value="&zotero.tagColorChooser.color;" control="color-picker"/>
|
||||||
<customcolorpicker id="color-picker" type="button" disabled="true"/>
|
<color-picker id="color-picker" disabled="true"/>
|
||||||
<separator width="20"/>
|
<separator width="20"/>
|
||||||
<label value="&zotero.tagColorChooser.position;" control="tag-position" disabled="true"/>
|
<label value="&zotero.tagColorChooser.position;" control="tag-position" disabled="true"/>
|
||||||
<menulist id="tag-position" disabled="true" sizetopopup="always"
|
<menulist id="tag-position" disabled="true" sizetopopup="always"
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
customcolorpicker[type="button"] {
|
|
||||||
width: 38px;
|
|
||||||
height: 24px;
|
|
||||||
border: 1px solid #a7a7a7;
|
|
||||||
background-color: ThreeDFace;
|
|
||||||
padding: 3px;
|
|
||||||
-moz-appearance: button-bevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
.colorpickertile[hover="true"], .cp-light[hover="true"] {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.colorpickertile[selected="true"] {
|
|
||||||
border : 1px outset #C0C0C0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.colorpickertile[hover="true"]:not([selected="true"]) {
|
|
||||||
border : 1px dotted #A7A7A7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cp-light[hover="true"]:not([selected="true"]) {
|
|
||||||
border : 1px dotted #000000;
|
|
||||||
}
|
|
|
@ -21,14 +21,6 @@ textbox[type="styled"]
|
||||||
-moz-binding: url('chrome://zotero/content/bindings/styled-textbox.xml#styled-textbox');
|
-moz-binding: url('chrome://zotero/content/bindings/styled-textbox.xml#styled-textbox');
|
||||||
}
|
}
|
||||||
|
|
||||||
customcolorpicker {
|
|
||||||
-moz-binding: url(chrome://zotero/content/bindings/customcolorpicker.xml#custom-colorpicker);
|
|
||||||
}
|
|
||||||
|
|
||||||
customcolorpicker[type=button] {
|
|
||||||
-moz-binding: url(chrome://zotero/content/bindings/customcolorpicker.xml#custom-colorpicker-button);
|
|
||||||
}
|
|
||||||
|
|
||||||
zoteromergegroup {
|
zoteromergegroup {
|
||||||
-moz-binding: url('chrome://zotero/content/bindings/merge.xml#merge-group');
|
-moz-binding: url('chrome://zotero/content/bindings/merge.xml#merge-group');
|
||||||
}
|
}
|
||||||
|
|
1
scss/_colorPicker.scss
Normal file
1
scss/_colorPicker.scss
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@import "components/colorPicker";
|
1
scss/colorPicker-mac.scss
Normal file
1
scss/colorPicker-mac.scss
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@import "colorPicker";
|
1
scss/colorPicker-unix.scss
Normal file
1
scss/colorPicker-unix.scss
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@import "colorPicker";
|
1
scss/colorPicker-win.scss
Normal file
1
scss/colorPicker-win.scss
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@import "colorPicker";
|
37
scss/components/_colorPicker.scss
Normal file
37
scss/components/_colorPicker.scss
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#button {
|
||||||
|
width: 38px;
|
||||||
|
height: 24px;
|
||||||
|
appearance: none;
|
||||||
|
border: 1px solid #a7a7a7;
|
||||||
|
background-color: white;
|
||||||
|
padding: 3px;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: #ddd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#button-tile {
|
||||||
|
display: block;
|
||||||
|
background-color: #000000;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#grid {
|
||||||
|
display: grid;
|
||||||
|
margin: 2px;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-tile:hover {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-tile[selected="true"] {
|
||||||
|
border: 1px outset #C0C0C0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-tile:hover:not([selected="true"]) {
|
||||||
|
border: 1px dotted #A7A7A7;
|
||||||
|
}
|
Loading…
Reference in a new issue