157 lines
5.0 KiB
JavaScript
157 lines
5.0 KiB
JavaScript
/* global CodeMirror loadScript editors showHelp */
|
|
'use strict';
|
|
|
|
window.initColorpicker = () => {
|
|
initOverlayHooks();
|
|
onDOMready().then(() => {
|
|
$('#colorpicker-settings').onclick = configureColorpicker;
|
|
});
|
|
const scripts = [
|
|
'/vendor-overwrites/colorpicker/colorpicker.css',
|
|
'/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);
|
|
|
|
function colorpickerOnDemand(id, enabled) {
|
|
return loadScript(enabled && scripts)
|
|
.then(() => setColorpickerOption(id, enabled));
|
|
}
|
|
|
|
function setColorpickerOption(id, enabled) {
|
|
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', defaults.colorpicker));
|
|
}
|
|
|
|
function registerHotkey(id, hotkey) {
|
|
CodeMirror.commands.colorpicker = invokeColorpicker;
|
|
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 (key === 'Enter' || key === 'Esc') {
|
|
$('#help-popup .dismiss').onclick();
|
|
return;
|
|
} else if (/^(Space|(Shift-)?(Esc|Tab|[!-~])|(Shift-?|Ctrl-?|Alt-?|Cmd-?)*)$/.test(key)) {
|
|
this.setCustomValidity('Not allowed');
|
|
} else {
|
|
this.setCustomValidity('');
|
|
prefs.set('editor.colorpicker.hotkey', key);
|
|
}
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
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();
|
|
}
|
|
|
|
function initOverlayHooks() {
|
|
const COLORVIEW_DISABLED_SUFFIX = ' colorview-disabled';
|
|
const originalAddOverlay = CodeMirror.prototype.addOverlay;
|
|
CodeMirror.prototype.addOverlay = addOverlayHook;
|
|
|
|
function addOverlayHook(overlay) {
|
|
if (overlay === (this.state.matchHighlighter || {}).overlay) {
|
|
if (overlay.token !== tokenHook) {
|
|
overlay.stylusColorpickerHelper = {
|
|
token: overlay.token,
|
|
};
|
|
overlay.token = tokenHook;
|
|
}
|
|
}
|
|
originalAddOverlay.apply(this, arguments);
|
|
}
|
|
|
|
function tokenHook(stream) {
|
|
const style = this.stylusColorpickerHelper.token.call(this, stream);
|
|
if (style === 'matchhighlight') {
|
|
return tokenHookForHighlighter.call(this, stream, style);
|
|
} else {
|
|
return style;
|
|
}
|
|
}
|
|
|
|
function tokenHookForHighlighter(stream, style) {
|
|
const {start, pos, lineOracle: {baseTokens}} = stream;
|
|
if (!baseTokens) {
|
|
return style;
|
|
}
|
|
for (let prev = 0, i = 1; i < baseTokens.length; i += 2) {
|
|
const end = baseTokens[i];
|
|
if (prev < start && start < end) {
|
|
const base = baseTokens[i + 1];
|
|
if (base && base.includes('colorview')) {
|
|
return style + COLORVIEW_DISABLED_SUFFIX;
|
|
}
|
|
} else if (end > pos) {
|
|
break;
|
|
}
|
|
prev = end;
|
|
}
|
|
return style;
|
|
}
|
|
}
|
|
};
|