| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- /* global $ $create getEventKeyName messageBoxProxy moveFocus */// dom.js
- /* global CodeMirror */
- /* global editor */
- /* global prefs */
- /* global t */// localization.js
- 'use strict';
- const helpPopup = {
- show(title = '', body) {
- const div = $('#help-popup');
- const contents = $('.contents', div);
- div.className = '';
- contents.textContent = '';
- if (body) {
- contents.appendChild(typeof body === 'string' ? t.HTML(body) : body);
- }
- $('.title', div).textContent = title;
- $('.dismiss', div).onclick = helpPopup.close;
- window.on('keydown', helpPopup.close, true);
- // reset any inline styles
- div.style = 'display: block';
- helpPopup.originalFocus = document.activeElement;
- return div;
- },
- close(event) {
- const canClose =
- !event ||
- event.type === 'click' || (
- getEventKeyName(event) === 'Escape' &&
- !$('.CodeMirror-hints, #message-box') && (
- !document.activeElement ||
- !document.activeElement.closest('#search-replace-dialog') &&
- document.activeElement.matches(':not(input), .can-close-on-esc')
- )
- );
- const div = $('#help-popup');
- if (!canClose || !div) {
- return;
- }
- if (event && div.codebox && !div.codebox.options.readOnly && !div.codebox.isClean()) {
- setTimeout(async () => {
- const ok = await messageBoxProxy.confirm(t('confirmDiscardChanges'));
- return ok && helpPopup.close();
- });
- return;
- }
- if (div.contains(document.activeElement) && helpPopup.originalFocus) {
- helpPopup.originalFocus.focus();
- }
- const contents = $('.contents', div);
- div.style.display = '';
- contents.textContent = '';
- window.off('keydown', helpPopup.close, true);
- window.dispatchEvent(new Event('closeHelp'));
- },
- };
- // reroute handling to nearest editor when keypress resolves to one of these commands
- const rerouteHotkeys = {
- commands: [
- 'beautify',
- 'colorpicker',
- 'find',
- 'findNext',
- 'findPrev',
- 'jumpToLine',
- 'nextEditor',
- 'prevEditor',
- 'replace',
- 'replaceAll',
- 'save',
- 'toggleEditorFocus',
- 'toggleStyle',
- ],
- toggle(enable) {
- document[enable ? 'on' : 'off']('keydown', rerouteHotkeys.handler);
- },
- handler(event) {
- const keyName = CodeMirror.keyName(event);
- if (!keyName) {
- return;
- }
- const rerouteCommand = name => {
- if (rerouteHotkeys.commands.includes(name)) {
- CodeMirror.commands[name](editor.closestVisible(event.target));
- return true;
- }
- };
- if (CodeMirror.lookupKey(keyName, CodeMirror.defaults.keyMap, rerouteCommand) === 'handled' ||
- CodeMirror.lookupKey(keyName, CodeMirror.defaults.extraKeys, rerouteCommand) === 'handled') {
- event.preventDefault();
- event.stopPropagation();
- }
- },
- };
- function clipString(str, limit = 100) {
- return str.length <= limit ? str : str.substr(0, limit) + '...';
- }
- /* exported createHotkeyInput */
- function createHotkeyInput(prefId, {buttons = true, onDone}) {
- const RX_ERR = new RegExp('^(' + [
- /Space/,
- /(Shift-)?./, // a single character
- /(?=.)(Shift-?|Ctrl-?|Control-?|Alt-?|Meta-?)*(Escape|Tab|Page(Up|Down)|Arrow(Up|Down|Left|Right)|Home|End)?/,
- ].map(r => r.source || r).join('|') + ')$', 'i');
- const initialValue = prefs.get(prefId);
- const input = $create('input', {
- spellcheck: false,
- onpaste: e => onkeydown(e, e.clipboardData.getData('text')),
- onkeydown,
- });
- buttons = buttons && [
- ['confirmOK', 'Enter'],
- ['undo', initialValue],
- ['genericResetLabel', ''],
- ].map(([label, val]) =>
- $create('button', {onclick: e => onkeydown(e, val)}, t(label)));
- const [btnOk, btnUndo, btnReset] = buttons || [];
- onkeydown(null, initialValue);
- return buttons
- ? $create('fragment', [input, $create('.buttons', buttons)])
- : input;
- function onkeydown(e, key) {
- let newValue;
- if (e && e.type === 'keydown') {
- key = getEventKeyName(e);
- }
- switch (e && key) {
- case 'Tab':
- case 'Shift-Tab':
- return;
- case 'BackSpace':
- case 'Delete':
- newValue = '';
- break;
- case 'Enter':
- if (input.checkValidity() && onDone) onDone();
- break;
- case 'Escape':
- if (onDone) onDone();
- break;
- default:
- newValue = key.replace(/\b.$/, c => c.toUpperCase());
- }
- if (newValue != null) {
- const error = RX_ERR.test(newValue) ? t('genericError') : '';
- if (e && !error) prefs.set(prefId, newValue);
- input.setCustomValidity(error);
- input.value = newValue;
- input.focus();
- if (buttons) {
- btnOk.disabled = Boolean(error);
- btnUndo.disabled = newValue === initialValue;
- btnReset.disabled = !newValue;
- }
- }
- if (e) {
- e.preventDefault();
- e.stopPropagation();
- }
- }
- }
- /* exported showCodeMirrorPopup */
- function showCodeMirrorPopup(title, html, options) {
- const popup = helpPopup.show(title, html);
- popup.classList.add('big');
- let cm = popup.codebox = CodeMirror($('.contents', popup), Object.assign({
- mode: 'css',
- lineNumbers: true,
- lineWrapping: prefs.get('editor.lineWrapping'),
- foldGutter: true,
- gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'],
- matchBrackets: true,
- styleActiveLine: true,
- theme: prefs.get('editor.theme'),
- keyMap: prefs.get('editor.keyMap'),
- }, options));
- cm.focus();
- document.documentElement.style.pointerEvents = 'none';
- popup.style.pointerEvents = 'auto';
- const onKeyDown = event => {
- if (event.key === 'Tab' && !event.ctrlKey && !event.altKey && !event.metaKey) {
- const search = $('#search-replace-dialog');
- const area = search && search.contains(document.activeElement) ? search : popup;
- moveFocus(area, event.shiftKey ? -1 : 1);
- event.preventDefault();
- }
- };
- window.on('keydown', onKeyDown, true);
- window.on('closeHelp', () => {
- window.off('keydown', onKeyDown, true);
- document.documentElement.style.removeProperty('pointer-events');
- cm = popup.codebox = null;
- }, {once: true});
- return popup;
- }
- /* exported trimCommentLabel */
- function trimCommentLabel(str, limit = 1000) {
- // stripping /*** foo ***/ to foo
- return clipString(str.replace(/^[!-/:;=\s]*|[-#$&(+,./:;<=>\s*]*$/g, ''), limit);
- }
|