diff --git a/.eslintrc b/.eslintrc
index 0d866fff..bcfa68e3 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -51,6 +51,7 @@ globals:
tWordBreak: false
# dom.js
onDOMready: false
+ onDOMscriptReady: false
scrollElementIntoView: false
enforceInputRange: false
animateElement: false
diff --git a/edit.html b/edit.html
index c1966108..476c571d 100644
--- a/edit.html
+++ b/edit.html
@@ -33,6 +33,7 @@
+
@@ -67,8 +68,11 @@
+
+
+
+
-
diff --git a/edit/codemirror-default.js b/edit/codemirror-default.js
index e68d9f35..3a619cc3 100644
--- a/edit/codemirror-default.js
+++ b/edit/codemirror-default.js
@@ -25,12 +25,12 @@
styleActiveLine: true,
theme: 'default',
keyMap: prefs.get('editor.keyMap'),
- extraKeys: {
+ extraKeys: Object.assign(CodeMirror.defaults.extraKeys || {}, {
// independent of current keyMap
'Alt-Enter': 'toggleStyle',
'Alt-PageDown': 'nextEditor',
'Alt-PageUp': 'prevEditor'
- },
+ }),
maxHighlightLength: 100e3,
};
diff --git a/edit/codemirror-editing-hooks.js b/edit/codemirror-editing-hooks.js
index 7cb66a69..5f2d16c0 100644
--- a/edit/codemirror-editing-hooks.js
+++ b/edit/codemirror-editing-hooks.js
@@ -5,8 +5,7 @@ global save toggleStyle setupAutocomplete makeSectionVisible getSectionForChild
*/
'use strict';
-addEventListener('init:allDone', function _() {
- removeEventListener('init:allDone', _);
+onDOMscriptReady('/codemirror.js').then(() => {
CodeMirror.defaults.lint = linterConfig.getForCodeMirror();
@@ -48,11 +47,16 @@ addEventListener('init:allDone', function _() {
// cm.state.search for last used 'find'
let searchState;
- // N.B. the event listener should be registered before setupLivePrefs()
- $('#options').addEventListener('change', onOptionElementChanged);
- buildOptionsElements();
- setupLivePrefs();
- rerouteHotkeys(true);
+ onDOMready().then(() => {
+ prefs.subscribe(['editor.keyMap'], showKeyInSaveButtonTooltip);
+ showKeyInSaveButtonTooltip();
+
+ // N.B. the event listener should be registered before setupLivePrefs()
+ $('#options').addEventListener('change', onOptionElementChanged);
+ buildOptionsElements();
+
+ rerouteHotkeys(true);
+ });
return;
@@ -679,4 +683,23 @@ addEventListener('init:allDone', function _() {
});
});
}
+
+ function showKeyInSaveButtonTooltip(prefName, value) {
+ $('#save-button').title = findKeyForCommand('save', value);
+ }
+
+ function findKeyForCommand(command, mapName = CodeMirror.defaults.keyMap) {
+ const map = CodeMirror.keyMap[mapName];
+ let key = Object.keys(map).find(k => map[k] === command);
+ if (key) {
+ return key;
+ }
+ for (const ft of Array.isArray(map.fallthrough) ? map.fallthrough : [map.fallthrough]) {
+ key = ft && findKeyForCommand(command, ft);
+ if (key) {
+ return key;
+ }
+ }
+ return '';
+ }
});
diff --git a/edit/colorpicker-helper.js b/edit/colorpicker-helper.js
index ef53452a..03714092 100644
--- a/edit/colorpicker-helper.js
+++ b/edit/colorpicker-helper.js
@@ -1,34 +1,23 @@
/* global CodeMirror loadScript editors showHelp */
'use strict';
-// eslint-disable-next-line no-var
-var initColorpicker = () => {
+onDOMscriptReady('/colorview.js').then(() => {
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));
- }
+ prefs.subscribe(['editor.colorpicker'], setColorpickerOption);
+ setColorpickerOption(null, prefs.get('editor.colorpicker'));
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 = defaults.extraKeys || {};
defaults.extraKeys[keyName] = 'colorpicker';
}
defaults.colorpicker = {
@@ -45,6 +34,11 @@ var initColorpicker = () => {
},
},
};
+ } else {
+ CodeMirror.modeExtensions.css.unregisterColorviewHooks();
+ if (defaults.extraKeys) {
+ delete defaults.extraKeys[keyName];
+ }
}
// on page load runs before CodeMirror.setOption is defined
editors.forEach(cm => cm.setOption('colorpicker', defaults.colorpicker));
@@ -162,4 +156,4 @@ var initColorpicker = () => {
return style;
}
}
-};
+});
diff --git a/edit/edit.js b/edit/edit.js
index a050e2fe..873841a3 100644
--- a/edit/edit.js
+++ b/edit/edit.js
@@ -3,8 +3,6 @@ global CodeMirror parserlib loadScript
global CSSLint initLint linterConfig updateLintReport renderLintReport updateLinter
global mozParser createSourceEditor
global closeCurrentTab regExpTester messageBox
-global initColorpicker
-global initCollapsibles
global setupCodeMirror
global beautify
global initWithSectionStyle addSections removeSection getSectionsHashes
@@ -17,8 +15,6 @@ let dirty = {};
// array of all CodeMirror instances
const editors = [];
let saveSizeOnClose;
-// use browser history back when 'back to manage' is clicked
-let useHistoryBack;
// direct & reverse mapping of @-moz-document keywords and internal property names
const propertyToCss = {urls: 'url', urlPrefixes: 'url-prefix', domains: 'domain', regexps: 'regexp'};
@@ -35,14 +31,25 @@ Promise.all([
initStyleData(),
onDOMready(),
])
-.then(([style]) => Promise.all([
- style,
- initColorpicker(),
- initCollapsibles(),
- initHooksCommon(),
- dispatchEvent(new Event('init:allDone')),
-]))
-.then(createEditor);
+.then(([style]) => {
+ setupLivePrefs();
+
+ const usercss = isUsercss(style);
+ $('#heading').textContent = t(styleId ? 'editStyleHeading' : 'addStyleTitle');
+ $('#name').placeholder = t(usercss ? 'usercssEditorNamePlaceholder' : 'styleMissingName');
+ $('#name').title = usercss ? t('usercssReplaceTemplateName') : '';
+
+ $('#beautify').onclick = beautify;
+ $('#lint').addEventListener('scroll', hideLintHeaderOnScroll, {passive: true});
+ window.addEventListener('resize', () => debounce(rememberWindowSize, 100));
+
+ if (usercss) {
+ editor = createSourceEditor(style);
+ } else {
+ initWithSectionStyle({style});
+ document.addEventListener('wheel', scrollEntirePageOnCtrlShift);
+ }
+});
function preinit() {
// make querySelectorAll enumeration code readable
@@ -103,7 +110,18 @@ function preinit() {
getOwnTab().then(tab => {
const ownTabId = tab.id;
- useHistoryBack = sessionStorageHash('manageStylesHistory').value[ownTabId] === location.href;
+
+ // use browser history back when 'back to manage' is clicked
+ if (sessionStorageHash('manageStylesHistory').value[ownTabId] === location.href) {
+ onDOMready().then(() => {
+ $('#cancel-button').onclick = event => {
+ event.stopPropagation();
+ event.preventDefault();
+ history.back();
+ };
+ });
+ }
+ // no windows on android
if (!chrome.windows) {
return;
}
@@ -130,20 +148,6 @@ function preinit() {
});
}
-function createEditor([style]) {
- const usercss = isUsercss(style);
- $('#heading').textContent = t(styleId ? 'editStyleHeading' : 'addStyleTitle');
- $('#name').placeholder = t(usercss ? 'usercssEditorNamePlaceholder' : 'styleMissingName');
- $('#name').title = usercss ? t('usercssReplaceTemplateName') : '';
- $('#lint').addEventListener('scroll', hideLintHeaderOnScroll, {passive: true});
- if (usercss) {
- editor = createSourceEditor(style);
- } else {
- initWithSectionStyle({style});
- document.addEventListener('wheel', scrollEntirePageOnCtrlShift);
- }
-}
-
function onRuntimeMessage(request) {
switch (request.method) {
case 'styleUpdated':
@@ -270,40 +274,6 @@ function initHooks() {
}
// common for usercss and classic
-function initHooksCommon() {
- $('#cancel-button').addEventListener('click', goBackToManage);
- $('#beautify').addEventListener('click', beautify);
-
- prefs.subscribe(['editor.keyMap'], showKeyInSaveButtonTooltip);
- showKeyInSaveButtonTooltip();
-
- window.addEventListener('resize', () => debounce(rememberWindowSize, 100));
-
- function goBackToManage(event) {
- if (useHistoryBack) {
- event.stopPropagation();
- event.preventDefault();
- history.back();
- }
- }
- function showKeyInSaveButtonTooltip(prefName, value) {
- $('#save-button').title = findKeyForCommand('save', value);
- }
- function findKeyForCommand(command, mapName = CodeMirror.defaults.keyMap) {
- const map = CodeMirror.keyMap[mapName];
- let key = Object.keys(map).find(k => map[k] === command);
- if (key) {
- return key;
- }
- for (const ft of Array.isArray(map.fallthrough) ? map.fallthrough : [map.fallthrough]) {
- key = ft && findKeyForCommand(command, ft);
- if (key) {
- return key;
- }
- }
- return '';
- }
-}
function onChange(event) {
const node = event.target;
diff --git a/js/dom.js b/js/dom.js
index c9a6246f..fc0abbbe 100644
--- a/js/dom.js
+++ b/js/dom.js
@@ -55,6 +55,7 @@ $$.remove = (selector, base = document) => {
onDOMready().then(() => {
$.remove('#firefox-transitions-bug-suppressor');
+ initCollapsibles();
});
if (!chrome.app && chrome.windows) {
@@ -278,9 +279,13 @@ function $createLink(href = '', content) {
}
+// makes with [data-pref] save/restore their state
function initCollapsibles({bindClickOn = 'h2'} = {}) {
const prefMap = {};
const elements = $$('details[data-pref]');
+ if (!elements.length) {
+ return;
+ }
for (const el of elements) {
const key = el.dataset.pref;
diff --git a/js/script-loader.js b/js/script-loader.js
index 35d0ecde..8352bb38 100644
--- a/js/script-loader.js
+++ b/js/script-loader.js
@@ -44,3 +44,60 @@ var loadScript = (() => {
return Promise.all(files.map(f => (typeof f === 'string' ? inject(f) : f)));
};
})();
+
+
+(() => {
+ let subscribers, observer;
+ // natively declared