commit
8f10fc291e
|
@ -1,5 +0,0 @@
|
||||||
<html>
|
|
||||||
<script src="storage.js"></script>
|
|
||||||
<script src="messaging.js"></script>
|
|
||||||
<script src="background.js"></script>
|
|
||||||
</html>
|
|
|
@ -54,7 +54,9 @@ chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
|
||||||
case "getStyles":
|
case "getStyles":
|
||||||
var styles = getStyles(request, sendResponse);
|
var styles = getStyles(request, sendResponse);
|
||||||
// check if this is a main content frame style enumeration
|
// check if this is a main content frame style enumeration
|
||||||
if (request.matchUrl && !request.id && sender && sender.tab && sender.frameId == 0) {
|
if (request.matchUrl && !request.id
|
||||||
|
&& sender && sender.tab && sender.frameId == 0
|
||||||
|
&& sender.tab.url == request.matchUrl) {
|
||||||
updateIcon(sender.tab, styles);
|
updateIcon(sender.tab, styles);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -88,7 +90,7 @@ chrome.commands.onCommand.addListener(function(command) {
|
||||||
break;
|
break;
|
||||||
case "styleDisableAll":
|
case "styleDisableAll":
|
||||||
disableAllStylesToggle();
|
disableAllStylesToggle();
|
||||||
chrome.contextMenus.update("disableAll", {checked: prefs.getPref("disableAll")});
|
chrome.contextMenus.update("disableAll", {checked: prefs.get("disableAll")});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -98,11 +100,11 @@ chrome.commands.onCommand.addListener(function(command) {
|
||||||
runTryCatch(function() {
|
runTryCatch(function() {
|
||||||
chrome.contextMenus.create({
|
chrome.contextMenus.create({
|
||||||
id: "show-badge", title: chrome.i18n.getMessage("menuShowBadge"),
|
id: "show-badge", title: chrome.i18n.getMessage("menuShowBadge"),
|
||||||
type: "checkbox", contexts: ["browser_action"], checked: prefs.getPref("show-badge")
|
type: "checkbox", contexts: ["browser_action"], checked: prefs.get("show-badge")
|
||||||
}, function() { var clearError = chrome.runtime.lastError });
|
}, function() { var clearError = chrome.runtime.lastError });
|
||||||
chrome.contextMenus.create({
|
chrome.contextMenus.create({
|
||||||
id: "disableAll", title: chrome.i18n.getMessage("disableAllStyles"),
|
id: "disableAll", title: chrome.i18n.getMessage("disableAllStyles"),
|
||||||
type: "checkbox", contexts: ["browser_action"], checked: prefs.getPref("disableAll")
|
type: "checkbox", contexts: ["browser_action"], checked: prefs.get("disableAll")
|
||||||
}, function() { var clearError = chrome.runtime.lastError });
|
}, function() { var clearError = chrome.runtime.lastError });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -110,16 +112,15 @@ chrome.contextMenus.onClicked.addListener(function(info, tab) {
|
||||||
if (info.menuItemId == "disableAll") {
|
if (info.menuItemId == "disableAll") {
|
||||||
disableAllStylesToggle(info.checked);
|
disableAllStylesToggle(info.checked);
|
||||||
} else {
|
} else {
|
||||||
prefs.setPref(info.menuItemId, info.checked);
|
prefs.set(info.menuItemId, info.checked);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function disableAllStylesToggle(newState) {
|
function disableAllStylesToggle(newState) {
|
||||||
if (newState === undefined || newState === null) {
|
if (newState === undefined || newState === null) {
|
||||||
newState = !prefs.getPref("disableAll");
|
newState = !prefs.get("disableAll");
|
||||||
}
|
}
|
||||||
prefs.setPref("disableAll", newState);
|
prefs.set("disableAll", newState);
|
||||||
notifyAllTabs({method: "styleDisableAll", disableAll: newState});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStyles(options, callback) {
|
function getStyles(options, callback) {
|
||||||
|
@ -132,7 +133,7 @@ function getStyles(options, callback) {
|
||||||
var asHash = "asHash" in options ? options.asHash : false;
|
var asHash = "asHash" in options ? options.asHash : false;
|
||||||
|
|
||||||
var callCallback = function() {
|
var callCallback = function() {
|
||||||
var styles = asHash ? {disableAll: prefs.getPref("disableAll", false)} : [];
|
var styles = asHash ? {disableAll: prefs.get("disableAll", false)} : [];
|
||||||
cachedStyles.forEach(function(style) {
|
cachedStyles.forEach(function(style) {
|
||||||
if (enabled != null && fixBoolean(style.enabled) != enabled) {
|
if (enabled != null && fixBoolean(style.enabled) != enabled) {
|
||||||
return;
|
return;
|
||||||
|
@ -243,6 +244,10 @@ function sectionAppliesToUrl(section, url) {
|
||||||
if (url.indexOf("http") != 0 && url.indexOf("file") != 0 && url.indexOf("chrome-extension") != 0 && url.indexOf("ftp") != 0) {
|
if (url.indexOf("http") != 0 && url.indexOf("file") != 0 && url.indexOf("chrome-extension") != 0 && url.indexOf("ftp") != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// other extensions can't be styled
|
||||||
|
if (url.indexOf("chrome-extension") == 0 && url.indexOf(chrome.extension.getURL("")) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (!section.urls && !section.domains && !section.urlPrefixes && !section.regexps) {
|
if (!section.urls && !section.domains && !section.urlPrefixes && !section.regexps) {
|
||||||
//console.log(section.id + " is global");
|
//console.log(section.id + " is global");
|
||||||
return true;
|
return true;
|
||||||
|
@ -401,7 +406,7 @@ chrome.tabs.onAttached.addListener(function(tabId, data) {
|
||||||
if (tabData.url.indexOf(editFullUrl) == 0) {
|
if (tabData.url.indexOf(editFullUrl) == 0) {
|
||||||
chrome.windows.get(tabData.windowId, {populate: true}, function(win) {
|
chrome.windows.get(tabData.windowId, {populate: true}, function(win) {
|
||||||
// If there's only one tab in this window, it's been dragged to new window
|
// If there's only one tab in this window, it's been dragged to new window
|
||||||
prefs.setPref('openEditInWindow', win.tabs.length == 1);
|
prefs.set("openEditInWindow", win.tabs.length == 1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
64
edit.js
64
edit.js
|
@ -11,7 +11,7 @@ var propertyToCss = {urls: "url", urlPrefixes: "url-prefix", domains: "domain",
|
||||||
var CssToProperty = {"url": "urls", "url-prefix": "urlPrefixes", "domain": "domains", "regexp": "regexps"};
|
var CssToProperty = {"url": "urls", "url-prefix": "urlPrefixes", "domain": "domains", "regexp": "regexps"};
|
||||||
|
|
||||||
// make querySelectorAll enumeration code readable
|
// make querySelectorAll enumeration code readable
|
||||||
["forEach", "some", "indexOf"].forEach(function(method) {
|
["forEach", "some", "indexOf", "map"].forEach(function(method) {
|
||||||
NodeList.prototype[method]= Array.prototype[method];
|
NodeList.prototype[method]= Array.prototype[method];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -125,26 +125,23 @@ function initCodeMirror() {
|
||||||
var isWindowsOS = navigator.appVersion.indexOf("Windows") > 0;
|
var isWindowsOS = navigator.appVersion.indexOf("Windows") > 0;
|
||||||
|
|
||||||
// default option values
|
// default option values
|
||||||
var userOptions = prefs.getPref("editor.options");
|
shallowMerge(CM.defaults, {
|
||||||
var stylishOptions = {
|
|
||||||
mode: 'css',
|
mode: 'css',
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
lineWrapping: true,
|
lineWrapping: true,
|
||||||
foldGutter: true,
|
foldGutter: true,
|
||||||
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter", "CodeMirror-lint-markers"],
|
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter", "CodeMirror-lint-markers"],
|
||||||
matchBrackets: true,
|
matchBrackets: true,
|
||||||
lint: {getAnnotations: CodeMirror.lint.css, delay: prefs.getPref("editor.lintDelay")},
|
lint: {getAnnotations: CodeMirror.lint.css, delay: prefs.get("editor.lintDelay")},
|
||||||
lintReportDelay: prefs.getPref("editor.lintReportDelay"),
|
lintReportDelay: prefs.get("editor.lintReportDelay"),
|
||||||
styleActiveLine: true,
|
styleActiveLine: true,
|
||||||
theme: "default",
|
theme: "default",
|
||||||
keyMap: prefs.getPref("editor.keyMap"),
|
keyMap: prefs.get("editor.keyMap"),
|
||||||
extraKeys: { // independent of current keyMap
|
extraKeys: { // independent of current keyMap
|
||||||
"Alt-PageDown": "nextEditor",
|
"Alt-PageDown": "nextEditor",
|
||||||
"Alt-PageUp": "prevEditor"
|
"Alt-PageUp": "prevEditor"
|
||||||
}
|
}
|
||||||
}
|
}, prefs.get("editor.options"));
|
||||||
shallowMerge(stylishOptions, CM.defaults);
|
|
||||||
shallowMerge(userOptions, CM.defaults);
|
|
||||||
|
|
||||||
// additional commands
|
// additional commands
|
||||||
CM.commands.jumpToLine = jumpToLine;
|
CM.commands.jumpToLine = jumpToLine;
|
||||||
|
@ -158,11 +155,9 @@ function initCodeMirror() {
|
||||||
// "basic" keymap only has basic keys by design, so we skip it
|
// "basic" keymap only has basic keys by design, so we skip it
|
||||||
|
|
||||||
var extraKeysCommands = {};
|
var extraKeysCommands = {};
|
||||||
if (userOptions && typeof userOptions.extraKeys == "object") {
|
Object.keys(CM.defaults.extraKeys).forEach(function(key) {
|
||||||
Object.keys(userOptions.extraKeys).forEach(function(key) {
|
extraKeysCommands[CM.defaults.extraKeys[key]] = true;
|
||||||
extraKeysCommands[userOptions.extraKeys[key]] = true;
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
if (!extraKeysCommands.jumpToLine) {
|
if (!extraKeysCommands.jumpToLine) {
|
||||||
CM.keyMap.sublime["Ctrl-G"] = "jumpToLine";
|
CM.keyMap.sublime["Ctrl-G"] = "jumpToLine";
|
||||||
CM.keyMap.emacsy["Ctrl-G"] = "jumpToLine";
|
CM.keyMap.emacsy["Ctrl-G"] = "jumpToLine";
|
||||||
|
@ -224,8 +219,8 @@ function initCodeMirror() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// preload the theme so that CodeMirror can calculate its metrics in DOMContentLoaded->loadPrefs()
|
// preload the theme so that CodeMirror can calculate its metrics in DOMContentLoaded->setupLivePrefs()
|
||||||
var theme = prefs.getPref("editor.theme");
|
var theme = prefs.get("editor.theme");
|
||||||
document.getElementById("cm-theme").href = theme == "default" ? "" : "codemirror/theme/" + theme + ".css";
|
document.getElementById("cm-theme").href = theme == "default" ? "" : "codemirror/theme/" + theme + ".css";
|
||||||
|
|
||||||
// initialize global editor controls
|
// initialize global editor controls
|
||||||
|
@ -246,12 +241,11 @@ function initCodeMirror() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
document.getElementById("editor.keyMap").innerHTML = optionsHtmlFromArray(Object.keys(CM.keyMap).sort());
|
document.getElementById("editor.keyMap").innerHTML = optionsHtmlFromArray(Object.keys(CM.keyMap).sort());
|
||||||
var controlPrefs = {};
|
|
||||||
document.querySelectorAll("#options *[data-option][id^='editor.']").forEach(function(option) {
|
|
||||||
controlPrefs[option.id] = CM.defaults[option.dataset.option];
|
|
||||||
});
|
|
||||||
document.getElementById("options").addEventListener("change", acmeEventListener, false);
|
document.getElementById("options").addEventListener("change", acmeEventListener, false);
|
||||||
loadPrefs(controlPrefs);
|
setupLivePrefs(
|
||||||
|
document.querySelectorAll("#options *[data-option][id^='editor.']")
|
||||||
|
.map(function(option) { return option.id })
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
hotkeyRerouter.setState(true);
|
hotkeyRerouter.setState(true);
|
||||||
|
@ -276,8 +270,8 @@ function acmeEventListener(event) {
|
||||||
// use non-localized "default" internally
|
// use non-localized "default" internally
|
||||||
if (!value || value == "default" || value == t("defaultTheme")) {
|
if (!value || value == "default" || value == t("defaultTheme")) {
|
||||||
value = "default";
|
value = "default";
|
||||||
if (prefs.getPref(el.id) != value) {
|
if (prefs.get(el.id) != value) {
|
||||||
prefs.setPref(el.id, value);
|
prefs.set(el.id, value);
|
||||||
}
|
}
|
||||||
themeLink.href = "";
|
themeLink.href = "";
|
||||||
el.selectedIndex = 0;
|
el.selectedIndex = 0;
|
||||||
|
@ -400,7 +394,7 @@ document.addEventListener("wheel", function(event) {
|
||||||
|
|
||||||
chrome.tabs.query({currentWindow: true}, function(tabs) {
|
chrome.tabs.query({currentWindow: true}, function(tabs) {
|
||||||
var windowId = tabs[0].windowId;
|
var windowId = tabs[0].windowId;
|
||||||
if (prefs.getPref("openEditInWindow")) {
|
if (prefs.get("openEditInWindow")) {
|
||||||
if (tabs.length == 1 && window.history.length == 1) {
|
if (tabs.length == 1 && window.history.length == 1) {
|
||||||
chrome.windows.getAll(function(windows) {
|
chrome.windows.getAll(function(windows) {
|
||||||
if (windows.length > 1) {
|
if (windows.length > 1) {
|
||||||
|
@ -434,7 +428,7 @@ function goBackToManage(event) {
|
||||||
|
|
||||||
window.onbeforeunload = function() {
|
window.onbeforeunload = function() {
|
||||||
if (saveSizeOnClose) {
|
if (saveSizeOnClose) {
|
||||||
prefs.setPref("windowPosition", {
|
prefs.set("windowPosition", {
|
||||||
left: screenLeft,
|
left: screenLeft,
|
||||||
top: screenTop,
|
top: screenTop,
|
||||||
width: outerWidth,
|
width: outerWidth,
|
||||||
|
@ -994,9 +988,9 @@ function beautify(event) {
|
||||||
script.onload = doBeautify;
|
script.onload = doBeautify;
|
||||||
}
|
}
|
||||||
function doBeautify() {
|
function doBeautify() {
|
||||||
var tabs = prefs.getPref("editor.indentWithTabs");
|
var tabs = prefs.get("editor.indentWithTabs");
|
||||||
var options = prefs.getPref("editor.beautify");
|
var options = prefs.get("editor.beautify");
|
||||||
options.indent_size = tabs ? 1 : prefs.getPref("editor.tabSize");
|
options.indent_size = tabs ? 1 : prefs.get("editor.tabSize");
|
||||||
options.indent_char = tabs ? "\t" : " ";
|
options.indent_char = tabs ? "\t" : " ";
|
||||||
|
|
||||||
var section = getSectionForChild(event.target);
|
var section = getSectionForChild(event.target);
|
||||||
|
@ -1045,7 +1039,7 @@ function beautify(event) {
|
||||||
document.querySelector(".beautify-options").addEventListener("change", function(event) {
|
document.querySelector(".beautify-options").addEventListener("change", function(event) {
|
||||||
var value = event.target.selectedIndex > 0;
|
var value = event.target.selectedIndex > 0;
|
||||||
options[event.target.dataset.option] = value;
|
options[event.target.dataset.option] = value;
|
||||||
prefs.setPref("editor.beautify", options);
|
prefs.set("editor.beautify", options);
|
||||||
event.target.parentNode.setAttribute("newline", value.toString());
|
event.target.parentNode.setAttribute("newline", value.toString());
|
||||||
doBeautify();
|
doBeautify();
|
||||||
});
|
});
|
||||||
|
@ -1120,7 +1114,7 @@ function initWithStyle(style) {
|
||||||
function add() {
|
function add() {
|
||||||
var sectionDiv = addSection(null, queue.shift());
|
var sectionDiv = addSection(null, queue.shift());
|
||||||
maximizeCodeHeight(sectionDiv, !queue.length);
|
maximizeCodeHeight(sectionDiv, !queue.length);
|
||||||
updateLintReport(getCodeMirrorForSection(sectionDiv), prefs.getPref("editor.lintDelay"));
|
updateLintReport(getCodeMirrorForSection(sectionDiv), prefs.get("editor.lintDelay"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1472,12 +1466,12 @@ function showToMozillaHelp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function showKeyMapHelp() {
|
function showKeyMapHelp() {
|
||||||
var keyMap = mergeKeyMaps({}, prefs.getPref("editor.keyMap"), CodeMirror.defaults.extraKeys);
|
var keyMap = mergeKeyMaps({}, prefs.get("editor.keyMap"), CodeMirror.defaults.extraKeys);
|
||||||
var keyMapSorted = Object.keys(keyMap)
|
var keyMapSorted = Object.keys(keyMap)
|
||||||
.map(function(key) { return {key: key, cmd: keyMap[key]} })
|
.map(function(key) { return {key: key, cmd: keyMap[key]} })
|
||||||
.concat([{key: "Shift-Ctrl-Wheel", cmd: "scrollWindow"}])
|
.concat([{key: "Shift-Ctrl-Wheel", cmd: "scrollWindow"}])
|
||||||
.sort(function(a, b) { return a.cmd < b.cmd || (a.cmd == b.cmd && a.key < b.key) ? -1 : 1 });
|
.sort(function(a, b) { return a.cmd < b.cmd || (a.cmd == b.cmd && a.key < b.key) ? -1 : 1 });
|
||||||
showHelp(t("cm_keyMap") + ": " + prefs.getPref("editor.keyMap"),
|
showHelp(t("cm_keyMap") + ": " + prefs.get("editor.keyMap"),
|
||||||
'<table class="keymap-list">' +
|
'<table class="keymap-list">' +
|
||||||
'<thead><tr><th><input placeholder="' + t("helpKeyMapHotkey") + '" type="search"></th>' +
|
'<thead><tr><th><input placeholder="' + t("helpKeyMapHotkey") + '" type="search"></th>' +
|
||||||
'<th><input placeholder="' + t("helpKeyMapCommand") + '" type="search"></th></tr></thead>' +
|
'<th><input placeholder="' + t("helpKeyMapCommand") + '" type="search"></th></tr></thead>' +
|
||||||
|
@ -1585,7 +1579,7 @@ function showCodeMirrorPopup(title, html, options) {
|
||||||
var popup = showHelp(title, html);
|
var popup = showHelp(title, html);
|
||||||
popup.classList.add("big");
|
popup.classList.add("big");
|
||||||
|
|
||||||
popup.codebox = CodeMirror(popup.querySelector(".contents"), shallowMerge(options, {
|
popup.codebox = CodeMirror(popup.querySelector(".contents"), shallowMerge({
|
||||||
mode: "css",
|
mode: "css",
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
lineWrapping: true,
|
lineWrapping: true,
|
||||||
|
@ -1594,9 +1588,9 @@ function showCodeMirrorPopup(title, html, options) {
|
||||||
matchBrackets: true,
|
matchBrackets: true,
|
||||||
lint: {getAnnotations: CodeMirror.lint.css, delay: 0},
|
lint: {getAnnotations: CodeMirror.lint.css, delay: 0},
|
||||||
styleActiveLine: true,
|
styleActiveLine: true,
|
||||||
theme: prefs.getPref("editor.theme"),
|
theme: prefs.get("editor.theme"),
|
||||||
keyMap: prefs.getPref("editor.keyMap")
|
keyMap: prefs.get("editor.keyMap")
|
||||||
}));
|
}, options));
|
||||||
popup.codebox.focus();
|
popup.codebox.focus();
|
||||||
popup.codebox.on("focus", function() { hotkeyRerouter.setState(false) });
|
popup.codebox.on("focus", function() { hotkeyRerouter.setState(false) });
|
||||||
popup.codebox.on("blur", function() { hotkeyRerouter.setState(true) });
|
popup.codebox.on("blur", function() { hotkeyRerouter.setState(true) });
|
||||||
|
|
14
manage.js
14
manage.js
|
@ -110,7 +110,7 @@ function createStyleElement(style) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
if (openWindow || openBackgroundTab || openForegroundTab) {
|
if (openWindow || openBackgroundTab || openForegroundTab) {
|
||||||
if (openWindow) {
|
if (openWindow) {
|
||||||
var options = prefs.getPref('windowPosition', {});
|
var options = prefs.get("windowPosition");
|
||||||
options.url = url;
|
options.url = url;
|
||||||
chrome.windows.create(options);
|
chrome.windows.create(options);
|
||||||
} else {
|
} else {
|
||||||
|
@ -475,12 +475,12 @@ document.addEventListener("DOMContentLoaded", function() {
|
||||||
document.getElementById("search").addEventListener("input", searchStyles);
|
document.getElementById("search").addEventListener("input", searchStyles);
|
||||||
searchStyles(true); // re-apply filtering on history Back
|
searchStyles(true); // re-apply filtering on history Back
|
||||||
|
|
||||||
loadPrefs({
|
setupLivePrefs([
|
||||||
"manage.onlyEnabled": false,
|
"manage.onlyEnabled",
|
||||||
"manage.onlyEdited": false,
|
"manage.onlyEdited",
|
||||||
"show-badge": true,
|
"show-badge",
|
||||||
"popup.stylesFirst": true
|
"popup.stylesFirst"
|
||||||
});
|
]);
|
||||||
initFilter("enabled-only", document.getElementById("manage.onlyEnabled"));
|
initFilter("enabled-only", document.getElementById("manage.onlyEnabled"));
|
||||||
initFilter("edited-only", document.getElementById("manage.onlyEdited"));
|
initFilter("edited-only", document.getElementById("manage.onlyEdited"));
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,11 +13,12 @@
|
||||||
"tabs",
|
"tabs",
|
||||||
"webNavigation",
|
"webNavigation",
|
||||||
"contextMenus",
|
"contextMenus",
|
||||||
|
"storage",
|
||||||
"http://userstyles.org/",
|
"http://userstyles.org/",
|
||||||
"https://userstyles.org/"
|
"https://userstyles.org/"
|
||||||
],
|
],
|
||||||
"background": {
|
"background": {
|
||||||
"page": "background.html"
|
"scripts": ["messaging.js", "storage.js", "background.js"]
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
"openManage": {
|
"openManage": {
|
||||||
|
|
17
messaging.js
17
messaging.js
|
@ -8,11 +8,7 @@ function notifyAllTabs(request) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// notify all open popups
|
// notify all open popups
|
||||||
// use a shallow copy since the original `request` is still being processed
|
var reqPopup = shallowMerge({}, request, {method: "updatePopup", reason: request.method});
|
||||||
var reqPopup = {};
|
|
||||||
for (var k in request) reqPopup[k] = request[k];
|
|
||||||
reqPopup.reason = request.method;
|
|
||||||
reqPopup.method = "updatePopup";
|
|
||||||
chrome.extension.sendMessage(reqPopup);
|
chrome.extension.sendMessage(reqPopup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,15 +44,20 @@ function updateIcon(tab, styles) {
|
||||||
});
|
});
|
||||||
|
|
||||||
function stylesReceived(styles) {
|
function stylesReceived(styles) {
|
||||||
var disableAll = "disableAll" in styles ? styles.disableAll : prefs.getPref("disableAll");
|
var disableAll = "disableAll" in styles ? styles.disableAll : prefs.get("disableAll");
|
||||||
var postfix = styles.length == 0 || disableAll ? "w" : "";
|
var postfix = styles.length == 0 || disableAll ? "w" : "";
|
||||||
chrome.browserAction.setIcon({
|
chrome.browserAction.setIcon({
|
||||||
path: {19: "19" + postfix + ".png", 38: "38" + postfix + ".png"},
|
path: {19: "19" + postfix + ".png", 38: "38" + postfix + ".png"},
|
||||||
tabId: tab.id
|
tabId: tab.id
|
||||||
});
|
}, function() {
|
||||||
var t = prefs.getPref("show-badge") && styles.length ? ("" + styles.length) : "";
|
// if the tab was just closed an error may occur,
|
||||||
|
// e.g. 'windowPosition' pref updated in edit.js::window.onbeforeunload
|
||||||
|
if (!chrome.runtime.lastError) {
|
||||||
|
var t = prefs.get("show-badge") && styles.length ? ("" + styles.length) : "";
|
||||||
chrome.browserAction.setBadgeText({text: t, tabId: tab.id});
|
chrome.browserAction.setBadgeText({text: t, tabId: tab.id});
|
||||||
chrome.browserAction.setBadgeBackgroundColor({color: disableAll ? "#aaa" : [0, 0, 0, 0]});
|
chrome.browserAction.setBadgeBackgroundColor({color: disableAll ? "#aaa" : [0, 0, 0, 0]});
|
||||||
|
}
|
||||||
|
});
|
||||||
//console.log("Tab " + tab.id + " (" + tab.url + ") badge text set to '" + t + "'.");
|
//console.log("Tab " + tab.id + " (" + tab.url + ") badge text set to '" + t + "'.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
30
popup.js
30
popup.js
|
@ -3,7 +3,7 @@ writeStyleTemplate.className = "write-style-link";
|
||||||
|
|
||||||
var installed = document.getElementById("installed");
|
var installed = document.getElementById("installed");
|
||||||
|
|
||||||
if (!prefs.getPref("popup.stylesFirst")) {
|
if (!prefs.get("popup.stylesFirst")) {
|
||||||
document.body.insertBefore(document.querySelector("body > .actions"), installed);
|
document.body.insertBefore(document.querySelector("body > .actions"), installed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,14 +29,14 @@ function updatePopUp(url) {
|
||||||
var urlLink = writeStyleTemplate.cloneNode(true);
|
var urlLink = writeStyleTemplate.cloneNode(true);
|
||||||
urlLink.href = "edit.html?url-prefix=" + encodeURIComponent(url);
|
urlLink.href = "edit.html?url-prefix=" + encodeURIComponent(url);
|
||||||
urlLink.appendChild(document.createTextNode( // switchable; default="this URL"
|
urlLink.appendChild(document.createTextNode( // switchable; default="this URL"
|
||||||
!prefs.getPref("popup.breadcrumbs.usePath")
|
!prefs.get("popup.breadcrumbs.usePath")
|
||||||
? t("writeStyleForURL").replace(/ /g, "\u00a0")
|
? t("writeStyleForURL").replace(/ /g, "\u00a0")
|
||||||
: /\/\/[^/]+\/(.*)/.exec(url)[1]
|
: /\/\/[^/]+\/(.*)/.exec(url)[1]
|
||||||
));
|
));
|
||||||
urlLink.title = "url-prefix(\"$\")".replace("$", url);
|
urlLink.title = "url-prefix(\"$\")".replace("$", url);
|
||||||
writeStyleLinks.push(urlLink);
|
writeStyleLinks.push(urlLink);
|
||||||
document.querySelector("#write-style").appendChild(urlLink)
|
document.querySelector("#write-style").appendChild(urlLink)
|
||||||
if (prefs.getPref("popup.breadcrumbs")) { // switchable; default=enabled
|
if (prefs.get("popup.breadcrumbs")) { // switchable; default=enabled
|
||||||
urlLink.addEventListener("mouseenter", function(event) { this.parentNode.classList.add("url()") }, false);
|
urlLink.addEventListener("mouseenter", function(event) { this.parentNode.classList.add("url()") }, false);
|
||||||
urlLink.addEventListener("focus", function(event) { this.parentNode.classList.add("url()") }, false);
|
urlLink.addEventListener("focus", function(event) { this.parentNode.classList.add("url()") }, false);
|
||||||
urlLink.addEventListener("mouseleave", function(event) { this.parentNode.classList.remove("url()") }, false);
|
urlLink.addEventListener("mouseleave", function(event) { this.parentNode.classList.remove("url()") }, false);
|
||||||
|
@ -63,7 +63,7 @@ function updatePopUp(url) {
|
||||||
link.addEventListener("click", openLinkInTabOrWindow, false);
|
link.addEventListener("click", openLinkInTabOrWindow, false);
|
||||||
container.appendChild(link);
|
container.appendChild(link);
|
||||||
});
|
});
|
||||||
if (prefs.getPref("popup.breadcrumbs")) {
|
if (prefs.get("popup.breadcrumbs")) {
|
||||||
container.classList.add("breadcrumbs");
|
container.classList.add("breadcrumbs");
|
||||||
container.appendChild(container.removeChild(container.firstChild));
|
container.appendChild(container.removeChild(container.firstChild));
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ function updatePopUp(url) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function showStyles(styles) {
|
function showStyles(styles) {
|
||||||
var enabledFirst = prefs.getPref("popup.enabledFirst");
|
var enabledFirst = prefs.get("popup.enabledFirst");
|
||||||
styles.sort(function(a, b) {
|
styles.sort(function(a, b) {
|
||||||
if (enabledFirst && a.enabled !== b.enabled) return !(a.enabled < b.enabled) ? -1 : 1;
|
if (enabledFirst && a.enabled !== b.enabled) return !(a.enabled < b.enabled) ? -1 : 1;
|
||||||
return a.name.localeCompare(b.name);
|
return a.name.localeCompare(b.name);
|
||||||
|
@ -146,9 +146,9 @@ function getId(event) {
|
||||||
|
|
||||||
function openLinkInTabOrWindow(event) {
|
function openLinkInTabOrWindow(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (prefs.getPref('openEditInWindow', false)) {
|
if (prefs.get("openEditInWindow", false)) {
|
||||||
var options = {url: event.target.href}
|
var options = {url: event.target.href}
|
||||||
var wp = prefs.getPref('windowPosition', {});
|
var wp = prefs.get("windowPosition", {});
|
||||||
for (var k in wp) options[k] = wp[k];
|
for (var k in wp) options[k] = wp[k];
|
||||||
chrome.windows.create(options);
|
chrome.windows.create(options);
|
||||||
} else {
|
} else {
|
||||||
|
@ -185,10 +185,6 @@ function handleDelete(id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDisableAll(disableAll) {
|
|
||||||
installed.classList.toggle("disabled", disableAll);
|
|
||||||
}
|
|
||||||
|
|
||||||
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
|
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
|
||||||
if (request.method == "updatePopup") {
|
if (request.method == "updatePopup") {
|
||||||
switch (request.reason) {
|
switch (request.reason) {
|
||||||
|
@ -199,12 +195,6 @@ chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
|
||||||
case "styleDeleted":
|
case "styleDeleted":
|
||||||
handleDelete(request.id);
|
handleDelete(request.id);
|
||||||
break;
|
break;
|
||||||
case "prefChanged":
|
|
||||||
if (request.prefName == "disableAll") {
|
|
||||||
document.getElementById("disableAll").checked = request.value;
|
|
||||||
handleDisableAll(request.value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -213,9 +203,7 @@ chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
|
||||||
document.getElementById(id).addEventListener("click", openLink, false);
|
document.getElementById(id).addEventListener("click", openLink, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
loadPrefs({"disableAll": false});
|
|
||||||
handleDisableAll(prefs.getPref("disableAll"));
|
|
||||||
document.getElementById("disableAll").addEventListener("change", function(event) {
|
document.getElementById("disableAll").addEventListener("change", function(event) {
|
||||||
notifyAllTabs({method: "styleDisableAll", disableAll: event.target.checked});
|
installed.classList.toggle("disabled", prefs.get("disableAll"));
|
||||||
handleDisableAll(event.target.checked);
|
|
||||||
});
|
});
|
||||||
|
setupLivePrefs(["disableAll"]);
|
||||||
|
|
205
storage.js
205
storage.js
|
@ -136,30 +136,33 @@ function isCheckbox(el) {
|
||||||
return el.nodeName.toLowerCase() == "input" && "checkbox" == el.type.toLowerCase();
|
return el.nodeName.toLowerCase() == "input" && "checkbox" == el.type.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
function changePref(event) {
|
// Accepts an array of pref names (values are fetched via prefs.get)
|
||||||
var el = event.target;
|
// and establishes a two-way connection between the document elements and the actual prefs
|
||||||
prefs.setPref(el.id, isCheckbox(el) ? el.checked : el.value);
|
function setupLivePrefs(IDs) {
|
||||||
|
var localIDs = {};
|
||||||
|
IDs.forEach(function(id) {
|
||||||
|
localIDs[id] = true;
|
||||||
|
updateElement(id).addEventListener("change", function() {
|
||||||
|
prefs.set(this.id, isCheckbox(this) ? this.checked : this.value);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
chrome.extension.onMessage.addListener(function(request) {
|
||||||
|
if (request.prefName in localIDs) {
|
||||||
|
updateElement(request.prefName);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
// Accepts a hash of pref name to default value
|
function updateElement(id) {
|
||||||
function loadPrefs(prefs) {
|
|
||||||
for (var id in prefs) {
|
|
||||||
var value = this.prefs.getPref(id, prefs[id]);
|
|
||||||
var el = document.getElementById(id);
|
var el = document.getElementById(id);
|
||||||
if (isCheckbox(el)) {
|
el[isCheckbox(el) ? "checked" : "value"] = prefs.get(id);
|
||||||
el.checked = value;
|
|
||||||
} else {
|
|
||||||
el.value = value;
|
|
||||||
}
|
|
||||||
el.dispatchEvent(new Event("change", {bubbles: true, cancelable: true}));
|
el.dispatchEvent(new Event("change", {bubbles: true, cancelable: true}));
|
||||||
el.addEventListener("change", changePref);
|
return el;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var prefs = {
|
var prefs = chrome.extension.getBackgroundPage().prefs || new function Prefs() {
|
||||||
// NB: localStorage["not_key"] is undefined, localStorage.getItem("not_key") is null
|
var me = this;
|
||||||
|
|
||||||
// defaults
|
var defaults = {
|
||||||
"openEditInWindow": false, // new editor opens in a own browser window
|
"openEditInWindow": false, // new editor opens in a own browser window
|
||||||
"windowPosition": {}, // detached window position
|
"windowPosition": {}, // detached window position
|
||||||
"show-badge": true, // display text on popup menu icon
|
"show-badge": true, // display text on popup menu icon
|
||||||
|
@ -191,41 +194,112 @@ var prefs = {
|
||||||
},
|
},
|
||||||
"editor.lintDelay": 500, // lint gutter marker update delay, ms
|
"editor.lintDelay": 500, // lint gutter marker update delay, ms
|
||||||
"editor.lintReportDelay": 4500, // lint report update delay, ms
|
"editor.lintReportDelay": 4500, // lint report update delay, ms
|
||||||
|
};
|
||||||
|
var values = deepCopy(defaults);
|
||||||
|
|
||||||
NO_DEFAULT_PREFERENCE: "No default preference for '%s'",
|
var syncTimeout; // see broadcast() function below
|
||||||
UNHANDLED_DATA_TYPE: "Default '%s' is of type '%s' - what should be done with it?",
|
|
||||||
|
|
||||||
getPref: function(key, defaultValue) {
|
Object.defineProperty(this, "readOnlyValues", {value: {}});
|
||||||
// Returns localStorage[key], defaultValue, this[key], or undefined
|
|
||||||
// as type of defaultValue, this[key], or localStorage[key]
|
Prefs.prototype.get = function(key, defaultValue) {
|
||||||
var value = localStorage[key];
|
if (key in values) {
|
||||||
if (value === undefined) {
|
return values[key];
|
||||||
return defaultValue === undefined ? shallowCopy(this[key]) : defaultValue;
|
|
||||||
}
|
}
|
||||||
switch (typeof (defaultValue === undefined ? this[key] : defaultValue)) {
|
if (defaultValue !== undefined) {
|
||||||
case "boolean": return value.toLowerCase() === "true";
|
return defaultValue;
|
||||||
case "number": return Number(value);
|
|
||||||
case "object": return JSON.parse(value);
|
|
||||||
case "string": break;
|
|
||||||
case "undefined": console.warn(this.NO_DEFAULT_PREFERENCE, key); break;
|
|
||||||
default: console.error(UNHANDLED_DATA_TYPE, key, typeof defaultValue);
|
|
||||||
}
|
}
|
||||||
return value;
|
if (key in defaults) {
|
||||||
},
|
return defaults[key];
|
||||||
setPref: function(key, value) {
|
|
||||||
var oldValue = localStorage[key];
|
|
||||||
if (value === undefined || equal(value, this[key])) {
|
|
||||||
delete localStorage[key];
|
|
||||||
} else {
|
|
||||||
localStorage[key] = typeof value == "string" ? value : JSON.stringify(value);
|
|
||||||
}
|
}
|
||||||
if (!equal(value, oldValue === undefined ? this[key] : oldValue)) {
|
console.warn("No default preference for '%s'", key);
|
||||||
|
};
|
||||||
|
|
||||||
|
Prefs.prototype.getAll = function(key) {
|
||||||
|
return deepCopy(values);
|
||||||
|
};
|
||||||
|
|
||||||
|
Prefs.prototype.set = function(key, value, options) {
|
||||||
|
var oldValue = deepCopy(values[key]);
|
||||||
|
values[key] = value;
|
||||||
|
defineReadonlyProperty(this.readOnlyValues, key, value);
|
||||||
|
if ((!options || !options.noBroadcast) && !equal(value, oldValue)) {
|
||||||
|
me.broadcast(key, value, options);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Prefs.prototype.remove = function(key) { me.set(key, undefined) };
|
||||||
|
|
||||||
|
Prefs.prototype.broadcast = function(key, value, options) {
|
||||||
var message = {method: "prefChanged", prefName: key, value: value};
|
var message = {method: "prefChanged", prefName: key, value: value};
|
||||||
notifyAllTabs(message);
|
notifyAllTabs(message);
|
||||||
chrome.extension.sendMessage(message);
|
chrome.extension.sendMessage(message);
|
||||||
|
if (key == "disableAll") {
|
||||||
|
notifyAllTabs({method: "styleDisableAll", disableAll: value});
|
||||||
|
}
|
||||||
|
if (!options || !options.noSync) {
|
||||||
|
clearTimeout(syncTimeout);
|
||||||
|
syncTimeout = setTimeout(function() {
|
||||||
|
chrome.storage.sync.set({"settings": values});
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(defaults).forEach(function(key) {
|
||||||
|
me.set(key, defaults[key], {noBroadcast: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
chrome.storage.sync.get("settings", function(result) {
|
||||||
|
var synced = result.settings;
|
||||||
|
for (var key in defaults) {
|
||||||
|
if (synced && (key in synced)) {
|
||||||
|
me.set(key, synced[key], {noSync: true});
|
||||||
|
} else {
|
||||||
|
var value = tryMigrating(key);
|
||||||
|
if (value !== undefined) {
|
||||||
|
me.set(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
chrome.storage.onChanged.addListener(function(changes, area) {
|
||||||
|
if (area == "sync" && "settings" in changes) {
|
||||||
|
var synced = changes.settings.newValue;
|
||||||
|
if (synced) {
|
||||||
|
for (key in defaults) {
|
||||||
|
if (key in synced) {
|
||||||
|
me.set(key, synced[key], {noSync: true});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// user manually deleted our settings, we'll recreate them
|
||||||
|
chrome.storage.sync.set({"settings": values});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function tryMigrating(key) {
|
||||||
|
if (!(key in localStorage)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
var value = localStorage[key];
|
||||||
|
delete localStorage[key];
|
||||||
|
localStorage["DEPRECATED: " + key] = value;
|
||||||
|
switch (typeof defaults[key]) {
|
||||||
|
case "boolean":
|
||||||
|
return value.toLowerCase() === "true";
|
||||||
|
case "number":
|
||||||
|
return Number(value);
|
||||||
|
case "object":
|
||||||
|
try {
|
||||||
|
return JSON.parse(value);
|
||||||
|
} catch(e) {
|
||||||
|
console.log("Cannot migrate from localStorage %s = '%s': %o", key, value, e);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
removePref: function(key) { setPref(key, undefined) }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function getCodeMirrorThemes(callback) {
|
function getCodeMirrorThemes(callback) {
|
||||||
|
@ -261,17 +335,42 @@ function sessionStorageHash(name) {
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
function shallowCopy(obj) {
|
function deepCopy(obj) {
|
||||||
return typeof obj == "object" ? shallowMerge(obj, {}) : obj;
|
if (!obj || typeof obj != "object") {
|
||||||
|
return obj;
|
||||||
|
} else {
|
||||||
|
var emptyCopy = Object.create(Object.getPrototypeOf(obj));
|
||||||
|
return deepMerge(emptyCopy, obj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function shallowMerge(from, to) {
|
function deepMerge(target, obj1 /* plus any number of object arguments */) {
|
||||||
if (typeof from == "object" && typeof to == "object") {
|
for (var i = 1; i < arguments.length; i++) {
|
||||||
for (var k in from) {
|
var obj = arguments[i];
|
||||||
to[k] = from[k];
|
for (var k in obj) {
|
||||||
|
// hasOwnProperty checking is not needed for our non-OOP stuff
|
||||||
|
var value = obj[k];
|
||||||
|
if (!value || typeof value != "object") {
|
||||||
|
target[k] = value;
|
||||||
|
} else if (k in target) {
|
||||||
|
deepMerge(target[k], value);
|
||||||
|
} else {
|
||||||
|
target[k] = deepCopy(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return to;
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
function shallowMerge(target, obj1 /* plus any number of object arguments */) {
|
||||||
|
for (var i = 1; i < arguments.length; i++) {
|
||||||
|
var obj = arguments[i];
|
||||||
|
for (var k in obj) {
|
||||||
|
target[k] = obj[k];
|
||||||
|
// hasOwnProperty checking is not needed for our non-OOP stuff
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
function equal(a, b) {
|
function equal(a, b) {
|
||||||
|
@ -288,3 +387,9 @@ function equal(a, b) {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function defineReadonlyProperty(obj, key, value) {
|
||||||
|
var copy = deepCopy(value);
|
||||||
|
Object.freeze(copy);
|
||||||
|
Object.defineProperty(obj, key, {value: copy, configurable: true})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user