add colorpicker hotkey config icon [default: none]
* uses the last submitted color by default * doesn't insert the default color until a change or the Enter key * fix a few bugs in colorpicker introduced in the rewrite
This commit is contained in:
parent
352846c8b4
commit
b99391887d
|
@ -193,6 +193,11 @@
|
||||||
<div class="option">
|
<div class="option">
|
||||||
<input id="editor.colorpicker" type="checkbox">
|
<input id="editor.colorpicker" type="checkbox">
|
||||||
<label for="editor.colorpicker" i18n-text="cm_colorpicker"></label>
|
<label for="editor.colorpicker" i18n-text="cm_colorpicker"></label>
|
||||||
|
<span class="svg-inline-wrapper" i18n-title="shortcutsNote">
|
||||||
|
<svg id="colorpicker-settings" class="svg-icon settings">
|
||||||
|
<use xlink:href="#svg-icon-settings"/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="option aligned">
|
<div class="option aligned">
|
||||||
<label id="tabSize-label" for="editor.tabSize" i18n-text="cm_tabSize"></label>
|
<label id="tabSize-label" for="editor.tabSize" i18n-text="cm_tabSize"></label>
|
||||||
|
|
96
edit/edit.js
96
edit/edit.js
|
@ -1457,6 +1457,7 @@ function initHooks() {
|
||||||
$('#sections-help').addEventListener('click', showSectionHelp, false);
|
$('#sections-help').addEventListener('click', showSectionHelp, false);
|
||||||
$('#keyMap-help').addEventListener('click', showKeyMapHelp, false);
|
$('#keyMap-help').addEventListener('click', showKeyMapHelp, false);
|
||||||
$('#cancel-button').addEventListener('click', goBackToManage);
|
$('#cancel-button').addEventListener('click', goBackToManage);
|
||||||
|
$('#colorpicker-settings').addEventListener('click', configureColorpicker);
|
||||||
|
|
||||||
setupOptionsExpand();
|
setupOptionsExpand();
|
||||||
initLint();
|
initLint();
|
||||||
|
@ -1872,8 +1873,8 @@ function showHelp(title, body) {
|
||||||
// avoid chaining on multiple showHelp() calls
|
// avoid chaining on multiple showHelp() calls
|
||||||
$('.dismiss', div).onclick = closeHelp;
|
$('.dismiss', div).onclick = closeHelp;
|
||||||
}
|
}
|
||||||
|
// reset any inline styles
|
||||||
div.style.display = 'block';
|
div.style = 'display: block';
|
||||||
return div;
|
return div;
|
||||||
|
|
||||||
function closeHelp(e) {
|
function closeHelp(e) {
|
||||||
|
@ -2078,6 +2079,7 @@ function onColorpickerReady() {
|
||||||
'/vendor-overwrites/colorpicker/colorpicker.js',
|
'/vendor-overwrites/colorpicker/colorpicker.js',
|
||||||
'/vendor-overwrites/colorpicker/colorview.js',
|
'/vendor-overwrites/colorpicker/colorview.js',
|
||||||
];
|
];
|
||||||
|
prefs.subscribe(['editor.colorpicker.hotkey'], registerHotkey);
|
||||||
prefs.subscribe(['editor.colorpicker'], colorpickerOnDemand);
|
prefs.subscribe(['editor.colorpicker'], colorpickerOnDemand);
|
||||||
return prefs.get('editor.colorpicker') && colorpickerOnDemand(null, true);
|
return prefs.get('editor.colorpicker') && colorpickerOnDemand(null, true);
|
||||||
|
|
||||||
|
@ -2087,21 +2089,83 @@ function onColorpickerReady() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setColorpickerOption(id, enabled) {
|
function setColorpickerOption(id, enabled) {
|
||||||
CodeMirror.defaults.colorpicker = enabled && {
|
const defaults = CodeMirror.defaults;
|
||||||
forceUpdate: editors.length > 0,
|
const keyName = prefs.get('editor.colorpicker.hotkey');
|
||||||
tooltip: t('colorpickerTooltip'),
|
delete defaults.extraKeys[keyName];
|
||||||
popupOptions: {
|
defaults.colorpicker = enabled;
|
||||||
tooltipForSwitcher: t('colorpickerSwitchFormatTooltip'),
|
if (enabled) {
|
||||||
hexUppercase: prefs.get('editor.colorpicker.hexUppercase'),
|
if (keyName) {
|
||||||
hideDelay: 5000,
|
CodeMirror.commands.colorpicker = invokeColorpicker;
|
||||||
embedderCallback: state => {
|
defaults.extraKeys[keyName] = 'colorpicker';
|
||||||
if (state && state.hexUppercase !== prefs.get('editor.colorpicker.hexUppercase')) {
|
}
|
||||||
prefs.set('editor.colorpicker.hexUppercase', state.hexUppercase);
|
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
|
// 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();
|
||||||
|
}
|
||||||
|
|
|
@ -60,6 +60,10 @@ var prefs = new function Prefs() {
|
||||||
'editor.colorpicker': true,
|
'editor.colorpicker': true,
|
||||||
// #DEAD or #beef
|
// #DEAD or #beef
|
||||||
'editor.colorpicker.hexUppercase': false,
|
'editor.colorpicker.hexUppercase': false,
|
||||||
|
// default hotkey
|
||||||
|
'editor.colorpicker.hotkey': '',
|
||||||
|
// last color
|
||||||
|
'editor.colorpicker.color': '',
|
||||||
|
|
||||||
'iconset': 0, // 0 = dark-themed icon
|
'iconset': 0, // 0 = dark-themed icon
|
||||||
// 1 = light-themed icon
|
// 1 = light-themed icon
|
||||||
|
|
|
@ -203,7 +203,7 @@ CodeMirror.defineExtension('colorpicker', function () {
|
||||||
options = PUBLIC_API.options = opt;
|
options = PUBLIC_API.options = opt;
|
||||||
prevFocusedElement = document.activeElement;
|
prevFocusedElement = document.activeElement;
|
||||||
userActivity = 0;
|
userActivity = 0;
|
||||||
lastOutputColor = opt.color;
|
lastOutputColor = opt.color || '';
|
||||||
$formatChangeButton.title = opt.tooltipForSwitcher || '';
|
$formatChangeButton.title = opt.tooltipForSwitcher || '';
|
||||||
opt.hideDelay = Math.max(0, opt.hideDelay) || 2000;
|
opt.hideDelay = Math.max(0, opt.hideDelay) || 2000;
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ CodeMirror.defineExtension('colorpicker', function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateInput(el) {
|
function validateInput(el) {
|
||||||
const isAlpha = el.type === 'text';
|
const isAlpha = el === $inputs[currentFormat][3];
|
||||||
let isValid = (isAlpha || el.value.trim()) && el.checkValidity();
|
let isValid = (isAlpha || el.value.trim()) && el.checkValidity();
|
||||||
if (!isAlpha && !isValid && currentFormat === 'rgb') {
|
if (!isAlpha && !isValid && currentFormat === 'rgb') {
|
||||||
isValid = parseAs(el, parseInt);
|
isValid = parseAs(el, parseInt);
|
||||||
|
@ -352,8 +352,9 @@ CodeMirror.defineExtension('colorpicker', function () {
|
||||||
//endregion
|
//endregion
|
||||||
//region State-to-DOM
|
//region State-to-DOM
|
||||||
|
|
||||||
function setFromColor(color = '#FF0000') {
|
function setFromColor(color) {
|
||||||
color = typeof color === 'string' ? stringToColor(color) : color;
|
color = typeof color === 'string' ? stringToColor(color) : color;
|
||||||
|
color = color || stringToColor('#f00');
|
||||||
const newHSV = color.type === 'hsl' ? HSLtoHSV(color) : RGBtoHSV(color);
|
const newHSV = color.type === 'hsl' ? HSLtoHSV(color) : RGBtoHSV(color);
|
||||||
if (Object.keys(newHSV).every(k => Math.abs(newHSV[k] - HSV[k]) < 1e-3)) {
|
if (Object.keys(newHSV).every(k => Math.abs(newHSV[k] - HSV[k]) < 1e-3)) {
|
||||||
return;
|
return;
|
||||||
|
@ -440,7 +441,7 @@ CodeMirror.defineExtension('colorpicker', function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSaturationMouseUp() {
|
function onSaturationMouseUp(event) {
|
||||||
if (event.button === 0) {
|
if (event.button === 0) {
|
||||||
dragging.saturation = false;
|
dragging.saturation = false;
|
||||||
releaseMouse();
|
releaseMouse();
|
||||||
|
@ -454,7 +455,7 @@ CodeMirror.defineExtension('colorpicker', function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onOpacityKnobMouseDown() {
|
function onOpacityKnobMouseDown(event) {
|
||||||
if (event.button === 0) {
|
if (event.button === 0) {
|
||||||
dragging.opacity = true;
|
dragging.opacity = true;
|
||||||
captureMouse();
|
captureMouse();
|
||||||
|
@ -517,6 +518,7 @@ CodeMirror.defineExtension('colorpicker', function () {
|
||||||
if (!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
|
if (!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
|
||||||
switch (e.which) {
|
switch (e.which) {
|
||||||
case 13:
|
case 13:
|
||||||
|
setFromInputs();
|
||||||
colorpickerCallback();
|
colorpickerCallback();
|
||||||
// fallthrough to 27
|
// fallthrough to 27
|
||||||
case 27:
|
case 27:
|
||||||
|
@ -647,7 +649,6 @@ CodeMirror.defineExtension('colorpicker', function () {
|
||||||
str.match(/(..)/g).map(c => parseInt(c, 16));
|
str.match(/(..)/g).map(c => parseInt(c, 16));
|
||||||
return {type: 'hex', r, g, b, a: a === 255 ? undefined : a / 255};
|
return {type: 'hex', r, g, b, a: a === 255 ? undefined : a / 255};
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function RGBtoHSV({r, g, b, a}) {
|
function RGBtoHSV({r, g, b, a}) {
|
||||||
|
|
|
@ -400,10 +400,11 @@
|
||||||
openPopup(color) {
|
openPopup(color) {
|
||||||
let {line, ch} = this.cm.getCursor();
|
let {line, ch} = this.cm.getCursor();
|
||||||
const lineText = this.cm.getLine(line);
|
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 lineCache = this.cm.state.colorpicker.cache.get(lineText);
|
||||||
const data = {line, ch, color, isShortCut: true};
|
const data = {line, ch, colorValue: color, isShortCut: true};
|
||||||
for (const [start, {color, colorValue}] of lineCache && lineCache.entries() || []) {
|
for (const [start, {color, colorValue = color}] of lineCache && lineCache.entries() || []) {
|
||||||
if (start <= ch && ch <= start + color.length) {
|
if (start <= ch && ch <= start + color.length) {
|
||||||
Object.assign(data, {ch: start, color, colorValue});
|
Object.assign(data, {ch: start, color, colorValue});
|
||||||
break;
|
break;
|
||||||
|
@ -419,7 +420,7 @@
|
||||||
top,
|
top,
|
||||||
left,
|
left,
|
||||||
cm: this.cm,
|
cm: this.cm,
|
||||||
color: data.colorValue || data.color || '#fff',
|
color: data.colorValue || data.color,
|
||||||
prevColor: data.color || '',
|
prevColor: data.color || '',
|
||||||
isShortCut: false,
|
isShortCut: false,
|
||||||
callback: ColorMarker.popupOnChange,
|
callback: ColorMarker.popupOnChange,
|
||||||
|
@ -437,8 +438,8 @@
|
||||||
const {cm, line, ch, embedderCallback} = this;
|
const {cm, line, ch, embedderCallback} = this;
|
||||||
const to = {line, ch: ch + this.prevColor.length};
|
const to = {line, ch: ch + this.prevColor.length};
|
||||||
if (cm.getRange(this, to) !== newColor) {
|
if (cm.getRange(this, to) !== newColor) {
|
||||||
this.prevColor = newColor;
|
|
||||||
cm.replaceRange(newColor, this, to, '*colorpicker');
|
cm.replaceRange(newColor, this, to, '*colorpicker');
|
||||||
|
this.prevColor = newColor;
|
||||||
}
|
}
|
||||||
if (typeof embedderCallback === 'function') {
|
if (typeof embedderCallback === 'function') {
|
||||||
embedderCallback(this);
|
embedderCallback(this);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user