diff --git a/edit.html b/edit.html
index 984182e6..772fd162 100644
--- a/edit.html
+++ b/edit.html
@@ -193,6 +193,11 @@
+
+
+
diff --git a/edit/edit.js b/edit/edit.js
index 0775ede5..2307f395 100644
--- a/edit/edit.js
+++ b/edit/edit.js
@@ -1457,6 +1457,7 @@ function initHooks() {
$('#sections-help').addEventListener('click', showSectionHelp, false);
$('#keyMap-help').addEventListener('click', showKeyMapHelp, false);
$('#cancel-button').addEventListener('click', goBackToManage);
+ $('#colorpicker-settings').addEventListener('click', configureColorpicker);
setupOptionsExpand();
initLint();
@@ -1872,8 +1873,8 @@ function showHelp(title, body) {
// avoid chaining on multiple showHelp() calls
$('.dismiss', div).onclick = closeHelp;
}
-
- div.style.display = 'block';
+ // reset any inline styles
+ div.style = 'display: block';
return div;
function closeHelp(e) {
@@ -2078,6 +2079,7 @@ function onColorpickerReady() {
'/vendor-overwrites/colorpicker/colorpicker.js',
'/vendor-overwrites/colorpicker/colorview.js',
];
+ prefs.subscribe(['editor.colorpicker.hotkey'], registerHotkey);
prefs.subscribe(['editor.colorpicker'], colorpickerOnDemand);
return prefs.get('editor.colorpicker') && colorpickerOnDemand(null, true);
@@ -2087,21 +2089,83 @@ function onColorpickerReady() {
}
function setColorpickerOption(id, enabled) {
- CodeMirror.defaults.colorpicker = enabled && {
- forceUpdate: editors.length > 0,
- tooltip: t('colorpickerTooltip'),
- popupOptions: {
- tooltipForSwitcher: t('colorpickerSwitchFormatTooltip'),
- hexUppercase: prefs.get('editor.colorpicker.hexUppercase'),
- hideDelay: 5000,
- embedderCallback: state => {
- if (state && state.hexUppercase !== prefs.get('editor.colorpicker.hexUppercase')) {
- prefs.set('editor.colorpicker.hexUppercase', state.hexUppercase);
- }
+ const defaults = CodeMirror.defaults;
+ const keyName = prefs.get('editor.colorpicker.hotkey');
+ delete defaults.extraKeys[keyName];
+ defaults.colorpicker = enabled;
+ if (enabled) {
+ if (keyName) {
+ CodeMirror.commands.colorpicker = invokeColorpicker;
+ defaults.extraKeys[keyName] = 'colorpicker';
+ }
+ defaults.colorpicker = {
+ forceUpdate: editors.length > 0,
+ tooltip: t('colorpickerTooltip'),
+ popupOptions: {
+ tooltipForSwitcher: t('colorpickerSwitchFormatTooltip'),
+ hexUppercase: prefs.get('editor.colorpicker.hexUppercase'),
+ hideDelay: 5000,
+ embedderCallback: state => {
+ ['hexUppercase', 'color']
+ .filter(name => state[name] !== prefs.get('editor.colorpicker.' + name))
+ .forEach(name => prefs.set('editor.colorpicker.' + name, state[name]));
+ },
},
- },
- };
+ };
+ }
// on page load runs before CodeMirror.setOption is defined
- editors.forEach(cm => cm.setOption('colorpicker', CodeMirror.defaults.colorpicker));
+ editors.forEach(cm => cm.setOption('colorpicker', defaults.colorpicker));
+ }
+
+ function registerHotkey(id, hotkey) {
+ const extraKeys = CodeMirror.defaults.extraKeys;
+ for (const key in extraKeys) {
+ if (extraKeys[key] === 'colorpicker') {
+ delete extraKeys[key];
+ break;
+ }
+ }
+ if (hotkey) {
+ extraKeys[hotkey] = 'colorpicker';
+ }
+ }
+
+ function invokeColorpicker(cm) {
+ cm.state.colorpicker.openPopup(prefs.get('editor.colorpicker.color'));
}
}
+
+function configureColorpicker() {
+ const input = $element({
+ tag: 'input',
+ type: 'search',
+ spellcheck: false,
+ value: prefs.get('editor.colorpicker.hotkey'),
+ onkeydown(event) {
+ const key = CodeMirror.keyName(event);
+ // ignore: [Shift?] characters, modifiers-only, [Shift?] Esc, Enter, [Shift?] Tab
+ if (/^(Enter|(Shift-)?(Esc|Tab|[!-~])|(Shift-?|Ctrl-?|Alt-?|Cmd-?)*)$/.test(key)) {
+ return;
+ }
+ event.preventDefault();
+ event.stopPropagation();
+ prefs.set('editor.colorpicker.hotkey', key);
+ this.value = key;
+ },
+ oninput() {
+ // fired on pressing "x" to clear the field
+ prefs.set('editor.colorpicker.hotkey', '');
+ },
+ onpaste(event) {
+ event.preventDefault();
+ }
+ });
+ const popup = showHelp(t('helpKeyMapHotkey'), input);
+ if (this instanceof Element) {
+ const bounds = this.getBoundingClientRect();
+ popup.style.left = bounds.right + 10 + 'px';
+ popup.style.top = bounds.top - popup.clientHeight / 2 + 'px';
+ popup.style.right = 'auto';
+ }
+ input.focus();
+}
diff --git a/js/prefs.js b/js/prefs.js
index 1c93a06c..09260bbe 100644
--- a/js/prefs.js
+++ b/js/prefs.js
@@ -60,6 +60,10 @@ var prefs = new function Prefs() {
'editor.colorpicker': true,
// #DEAD or #beef
'editor.colorpicker.hexUppercase': false,
+ // default hotkey
+ 'editor.colorpicker.hotkey': '',
+ // last color
+ 'editor.colorpicker.color': '',
'iconset': 0, // 0 = dark-themed icon
// 1 = light-themed icon
diff --git a/vendor-overwrites/colorpicker/colorpicker.js b/vendor-overwrites/colorpicker/colorpicker.js
index c430d5cc..013f368f 100644
--- a/vendor-overwrites/colorpicker/colorpicker.js
+++ b/vendor-overwrites/colorpicker/colorpicker.js
@@ -203,7 +203,7 @@ CodeMirror.defineExtension('colorpicker', function () {
options = PUBLIC_API.options = opt;
prevFocusedElement = document.activeElement;
userActivity = 0;
- lastOutputColor = opt.color;
+ lastOutputColor = opt.color || '';
$formatChangeButton.title = opt.tooltipForSwitcher || '';
opt.hideDelay = Math.max(0, opt.hideDelay) || 2000;
@@ -337,7 +337,7 @@ CodeMirror.defineExtension('colorpicker', function () {
}
function validateInput(el) {
- const isAlpha = el.type === 'text';
+ const isAlpha = el === $inputs[currentFormat][3];
let isValid = (isAlpha || el.value.trim()) && el.checkValidity();
if (!isAlpha && !isValid && currentFormat === 'rgb') {
isValid = parseAs(el, parseInt);
@@ -352,8 +352,9 @@ CodeMirror.defineExtension('colorpicker', function () {
//endregion
//region State-to-DOM
- function setFromColor(color = '#FF0000') {
+ function setFromColor(color) {
color = typeof color === 'string' ? stringToColor(color) : color;
+ color = color || stringToColor('#f00');
const newHSV = color.type === 'hsl' ? HSLtoHSV(color) : RGBtoHSV(color);
if (Object.keys(newHSV).every(k => Math.abs(newHSV[k] - HSV[k]) < 1e-3)) {
return;
@@ -440,7 +441,7 @@ CodeMirror.defineExtension('colorpicker', function () {
}
}
- function onSaturationMouseUp() {
+ function onSaturationMouseUp(event) {
if (event.button === 0) {
dragging.saturation = false;
releaseMouse();
@@ -454,7 +455,7 @@ CodeMirror.defineExtension('colorpicker', function () {
}
}
- function onOpacityKnobMouseDown() {
+ function onOpacityKnobMouseDown(event) {
if (event.button === 0) {
dragging.opacity = true;
captureMouse();
@@ -517,6 +518,7 @@ CodeMirror.defineExtension('colorpicker', function () {
if (!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
switch (e.which) {
case 13:
+ setFromInputs();
colorpickerCallback();
// fallthrough to 27
case 27:
@@ -647,7 +649,6 @@ CodeMirror.defineExtension('colorpicker', function () {
str.match(/(..)/g).map(c => parseInt(c, 16));
return {type: 'hex', r, g, b, a: a === 255 ? undefined : a / 255};
}
- return;
}
function RGBtoHSV({r, g, b, a}) {
diff --git a/vendor-overwrites/colorpicker/colorview.js b/vendor-overwrites/colorpicker/colorview.js
index 3fa3c554..93c7713d 100644
--- a/vendor-overwrites/colorpicker/colorview.js
+++ b/vendor-overwrites/colorpicker/colorview.js
@@ -400,10 +400,11 @@
openPopup(color) {
let {line, ch} = this.cm.getCursor();
const lineText = this.cm.getLine(line);
- ch -= (lineText.lastIndexOf('!important', ch) >= ch - '!important'.length) ? '!important'.length : 0;
+ const atImportant = lineText.lastIndexOf('!important', ch);
+ ch -= (atImportant >= Math.max(0, ch - '!important'.length)) ? '!important'.length : 0;
const lineCache = this.cm.state.colorpicker.cache.get(lineText);
- const data = {line, ch, color, isShortCut: true};
- for (const [start, {color, colorValue}] of lineCache && lineCache.entries() || []) {
+ const data = {line, ch, colorValue: color, isShortCut: true};
+ for (const [start, {color, colorValue = color}] of lineCache && lineCache.entries() || []) {
if (start <= ch && ch <= start + color.length) {
Object.assign(data, {ch: start, color, colorValue});
break;
@@ -419,7 +420,7 @@
top,
left,
cm: this.cm,
- color: data.colorValue || data.color || '#fff',
+ color: data.colorValue || data.color,
prevColor: data.color || '',
isShortCut: false,
callback: ColorMarker.popupOnChange,
@@ -437,8 +438,8 @@
const {cm, line, ch, embedderCallback} = this;
const to = {line, ch: ch + this.prevColor.length};
if (cm.getRange(this, to) !== newColor) {
- this.prevColor = newColor;
cm.replaceRange(newColor, this, to, '*colorpicker');
+ this.prevColor = newColor;
}
if (typeof embedderCallback === 'function') {
embedderCallback(this);