diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 603b3174..fd77a11a 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -40,6 +40,14 @@ "message": "Applies to", "description": "Label for 'applies to' fields on the edit/add screen" }, + "appliesLineWidgetLabel": { + "message": "Display 'Applies to' info", + "description": "Label for the checkbox to display applies-to information in the single editor" + }, + "appliesLineWidgetWarning": { + "message": "Does not work with minified CSS", + "description": "A warning that applies-to information won't show properly with minified CSS" + }, "appliesRegexpOption": { "message": "URLs matching the regexp", "description": "Option to make the style apply to the entered string as a regular expression" diff --git a/edit/source-editor.js b/edit/source-editor.js index c441a3c5..6aacd0fc 100644 --- a/edit/source-editor.js +++ b/edit/source-editor.js @@ -43,15 +43,72 @@ function createSourceEditor(style) { function initAppliesToReport(cm) { const DELAY = 500; - let widgets = []; - let timer; - let fromLine = null; - let toLine = null; - let style = getComputedStyle(cm.getGutterElement()); + let widgets = [], timer, fromLine, toLine, style, isInit; + const optionEl = buildOption(); - update(); + $('#options').insertBefore(optionEl, $('#options > .option.aligned')); - cm.on('change', (cm, {from, to}) => { + if (prefs.get('editor.appliesToLineWidget')) { + init(); + } + + prefs.subscribe(['editor.appliesToLineWidget'], (key, value) => { + if (!isInit && value) { + init(); + } else if (isInit && !value) { + uninit(); + } + optionEl.checked = value; + }); + + optionEl.addEventListener('change', e => { + prefs.set('editor.appliesToLineWidget', e.target.checked); + }); + + function buildOption() { + return $element({className: 'option', appendChild: [ + $element({ + tag: 'input', + type: 'checkbox', + id: 'editor.appliesToLineWidget', + checked: prefs.get('editor.appliesToLineWidget') + }), + $element({ + tag: 'label', + htmlFor: 'editor.appliesToLineWidget', + textContent: ' ' + t('appliesLineWidgetLabel'), + title: t('appliesLineWidgetWarning') + }) + ]}); + } + + function init() { + isInit = true; + + style = getComputedStyle(cm.getGutterElement()); + fromLine = null; + toLine = null; + + cm.on('change', onChange); + cm.on('optionChange', onOptionChange); + + // is it possible to avoid flickering? + window.addEventListener('load', updateStyle); + + update(); + } + + function uninit() { + isInit = false; + + widgets.forEach(w => w.clear()); + widgets.length = 0; + cm.off('change', onChange); + cm.off('optionChange', onOptionChange); + window.removeEventListener('load', updateStyle); + } + + function onChange(cm, {from, to}) { if (fromLine === null || toLine === null) { fromLine = from.line; toLine = to.line; @@ -61,16 +118,13 @@ function createSourceEditor(style) { } clearTimeout(timer); timer = setTimeout(update, DELAY); - }); + } - cm.on('optionChange', (cm, option) => { + function onOptionChange(cm, option) { if (option === 'theme') { updateStyle(); } - }); - - // is it possible to avoid flickering? - window.addEventListener('load', updateStyle); + } function update() { cm.operation(doUpdate); diff --git a/js/prefs.js b/js/prefs.js index 7938a475..9e2e1c3a 100644 --- a/js/prefs.js +++ b/js/prefs.js @@ -51,6 +51,8 @@ var prefs = new function Prefs() { 'editor.autocompleteOnTyping': false, // show autocomplete dropdown on typing a word token 'editor.contextDelete': contextDeleteMissing(), // "Delete" item in context menu + 'editor.appliesToLineWidget': true, // show applies-to line widget on the editor + 'iconset': 0, // 0 = dark-themed icon // 1 = light-themed icon