Fix linting problems and more readable code
This commit is contained in:
parent
970d48b17a
commit
560f5b666e
73
apply.js
73
apply.js
|
@ -1,3 +1,4 @@
|
||||||
|
/*jshint undef:false*/
|
||||||
var g_disableAll = false;
|
var g_disableAll = false;
|
||||||
var g_styleElements = {};
|
var g_styleElements = {};
|
||||||
var iframeObserver;
|
var iframeObserver;
|
||||||
|
@ -11,8 +12,13 @@ function requestStyles() {
|
||||||
// we'll request the styles directly to minimize delay and flicker,
|
// we'll request the styles directly to minimize delay and flicker,
|
||||||
// unless Chrome still starts up and the background page isn't fully loaded.
|
// unless Chrome still starts up and the background page isn't fully loaded.
|
||||||
// (Note: in this case the function may be invoked again from applyStyles.)
|
// (Note: in this case the function may be invoked again from applyStyles.)
|
||||||
var request = {method: "getStyles", matchUrl: location.href, enabled: true, asHash: true};
|
var request = {
|
||||||
if (location.href.indexOf(chrome.extension.getURL("")) == 0) {
|
method: "getStyles",
|
||||||
|
matchUrl: location.href,
|
||||||
|
enabled: true,
|
||||||
|
asHash: true
|
||||||
|
};
|
||||||
|
if (location.href.indexOf(chrome.extension.getURL("")) === 0) {
|
||||||
var bg = chrome.extension.getBackgroundPage();
|
var bg = chrome.extension.getBackgroundPage();
|
||||||
if (bg && bg.getStyles) {
|
if (bg && bg.getStyles) {
|
||||||
// apply styles immediately, then proceed with a normal request that will update the icon
|
// apply styles immediately, then proceed with a normal request that will update the icon
|
||||||
|
@ -22,8 +28,20 @@ function requestStyles() {
|
||||||
chrome.runtime.sendMessage(request, applyStyles);
|
chrome.runtime.sendMessage(request, applyStyles);
|
||||||
}
|
}
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
|
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
|
||||||
// Also handle special request just for the pop-up
|
// Also handle special request just for the pop-up
|
||||||
|
function styleAdded() {
|
||||||
|
if (request.style.enabled) {
|
||||||
|
chrome.runtime.sendMessage({
|
||||||
|
method: "getStyles",
|
||||||
|
matchUrl: location.href,
|
||||||
|
enabled: true,
|
||||||
|
id: request.style.id,
|
||||||
|
asHash: true
|
||||||
|
}, applyStyles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (request.method == "updatePopup" ? request.reason : request.method) {
|
switch (request.method == "updatePopup" ? request.reason : request.method) {
|
||||||
case "styleDeleted":
|
case "styleDeleted":
|
||||||
removeStyle(request.id, document);
|
removeStyle(request.id, document);
|
||||||
|
@ -31,15 +49,13 @@ chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
|
||||||
case "styleUpdated":
|
case "styleUpdated":
|
||||||
if (request.style.enabled) {
|
if (request.style.enabled) {
|
||||||
retireStyle(request.style.id);
|
retireStyle(request.style.id);
|
||||||
// fallthrough to "styleAdded"
|
styleAdded();
|
||||||
} else {
|
} else {
|
||||||
removeStyle(request.style.id, document);
|
removeStyle(request.style.id, document);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case "styleAdded":
|
case "styleAdded":
|
||||||
if (request.style.enabled) {
|
styleAdded();
|
||||||
chrome.runtime.sendMessage({method: "getStyles", matchUrl: location.href, enabled: true, id: request.style.id, asHash: true}, applyStyles);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case "styleApply":
|
case "styleApply":
|
||||||
applyStyles(request.styles);
|
applyStyles(request.styles);
|
||||||
|
@ -69,12 +85,12 @@ function disableAll(disable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function disableSheets(disable, doc) {
|
function disableSheets(disable, doc) {
|
||||||
Array.prototype.forEach.call(doc.styleSheets, function(stylesheet) {
|
Array.prototype.forEach.call(doc.styleSheets, function (stylesheet) {
|
||||||
if (stylesheet.ownerNode.classList.contains("stylish")) {
|
if (stylesheet.ownerNode.classList.contains("stylish")) {
|
||||||
stylesheet.disabled = disable;
|
stylesheet.disabled = disable;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
getDynamicIFrames(doc).forEach(function(iframe) {
|
getDynamicIFrames(doc).forEach(function (iframe) {
|
||||||
if (!disable) {
|
if (!disable) {
|
||||||
// update the IFRAME if it was created while the observer was disconnected
|
// update the IFRAME if it was created while the observer was disconnected
|
||||||
addDocumentStylesToIFrame(iframe);
|
addDocumentStylesToIFrame(iframe);
|
||||||
|
@ -90,10 +106,10 @@ function removeStyle(id, doc) {
|
||||||
if (e) {
|
if (e) {
|
||||||
e.remove();
|
e.remove();
|
||||||
}
|
}
|
||||||
if (doc == document && Object.keys(g_styleElements).length == 0) {
|
if (doc == document && Object.keys(g_styleElements).length === 0) {
|
||||||
iframeObserver.disconnect();
|
iframeObserver.disconnect();
|
||||||
}
|
}
|
||||||
getDynamicIFrames(doc).forEach(function(iframe) {
|
getDynamicIFrames(doc).forEach(function (iframe) {
|
||||||
removeStyle(id, iframe.contentDocument);
|
removeStyle(id, iframe.contentDocument);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -114,7 +130,7 @@ function retireStyle(id, doc) {
|
||||||
if (e) {
|
if (e) {
|
||||||
e.id = "stylish-" + deadID;
|
e.id = "stylish-" + deadID;
|
||||||
}
|
}
|
||||||
getDynamicIFrames(doc).forEach(function(iframe) {
|
getDynamicIFrames(doc).forEach(function (iframe) {
|
||||||
retireStyle(id, iframe.contentDocument);
|
retireStyle(id, iframe.contentDocument);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -142,14 +158,14 @@ function applyStyles(styleHash) {
|
||||||
document.head.appendChild(document.getElementById(id));
|
document.head.appendChild(document.getElementById(id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
addDocumentStylesToAllIFrames();
|
addDocumentStylesToAllIFrames();
|
||||||
iframeObserver.start();
|
iframeObserver.start();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retiredStyleIds.length) {
|
if (retiredStyleIds.length) {
|
||||||
setTimeout(function() {
|
setTimeout(function () {
|
||||||
while (retiredStyleIds.length) {
|
while (retiredStyleIds.length) {
|
||||||
removeStyle(retiredStyleIds.shift(), document);
|
removeStyle(retiredStyleIds.shift(), document);
|
||||||
}
|
}
|
||||||
|
@ -173,7 +189,7 @@ function applySections(styleId, sections) {
|
||||||
styleElement.setAttribute("id", "stylish-" + styleId);
|
styleElement.setAttribute("id", "stylish-" + styleId);
|
||||||
styleElement.setAttribute("class", "stylish");
|
styleElement.setAttribute("class", "stylish");
|
||||||
styleElement.setAttribute("type", "text/css");
|
styleElement.setAttribute("type", "text/css");
|
||||||
styleElement.appendChild(document.createTextNode(sections.map(function(section) {
|
styleElement.appendChild(document.createTextNode(sections.map(function (section) {
|
||||||
return section.code;
|
return section.code;
|
||||||
}).join("\n")));
|
}).join("\n")));
|
||||||
addStyleElement(styleElement, document);
|
addStyleElement(styleElement, document);
|
||||||
|
@ -186,7 +202,7 @@ function addStyleElement(styleElement, doc) {
|
||||||
}
|
}
|
||||||
doc.documentElement.appendChild(doc.importNode(styleElement, true))
|
doc.documentElement.appendChild(doc.importNode(styleElement, true))
|
||||||
.disabled = g_disableAll;
|
.disabled = g_disableAll;
|
||||||
getDynamicIFrames(doc).forEach(function(iframe) {
|
getDynamicIFrames(doc).forEach(function (iframe) {
|
||||||
if (iframeIsLoadingSrcDoc(iframe)) {
|
if (iframeIsLoadingSrcDoc(iframe)) {
|
||||||
addStyleToIFrameSrcDoc(iframe, styleElement);
|
addStyleToIFrameSrcDoc(iframe, styleElement);
|
||||||
} else {
|
} else {
|
||||||
|
@ -224,7 +240,7 @@ function iframeIsDynamic(f) {
|
||||||
// Cross-origin, so it's not a dynamic iframe
|
// Cross-origin, so it's not a dynamic iframe
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return href == document.location.href || href.indexOf("about:") == 0;
|
return href == document.location.href || href.indexOf("about:") === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function iframeIsLoadingSrcDoc(f) {
|
function iframeIsLoadingSrcDoc(f) {
|
||||||
|
@ -244,9 +260,11 @@ function addStyleToIFrameSrcDoc(iframe, styleElement) {
|
||||||
function replaceAll(newStyles, doc, pass2) {
|
function replaceAll(newStyles, doc, pass2) {
|
||||||
var oldStyles = [].slice.call(doc.querySelectorAll("STYLE.stylish" + (pass2 ? "[id$='-ghost']" : "")));
|
var oldStyles = [].slice.call(doc.querySelectorAll("STYLE.stylish" + (pass2 ? "[id$='-ghost']" : "")));
|
||||||
if (!pass2) {
|
if (!pass2) {
|
||||||
oldStyles.forEach(function(style) { style.id += "-ghost"; });
|
oldStyles.forEach(function (style) {
|
||||||
|
style.id += "-ghost";
|
||||||
|
});
|
||||||
}
|
}
|
||||||
getDynamicIFrames(doc).forEach(function(iframe) {
|
getDynamicIFrames(doc).forEach(function (iframe) {
|
||||||
replaceAll(newStyles, iframe.contentDocument, pass2);
|
replaceAll(newStyles, iframe.contentDocument, pass2);
|
||||||
});
|
});
|
||||||
if (doc == document && !pass2) {
|
if (doc == document && !pass2) {
|
||||||
|
@ -255,13 +273,15 @@ function replaceAll(newStyles, doc, pass2) {
|
||||||
replaceAll(newStyles, doc, true);
|
replaceAll(newStyles, doc, true);
|
||||||
}
|
}
|
||||||
if (pass2) {
|
if (pass2) {
|
||||||
oldStyles.forEach(function(style) { style.remove(); });
|
oldStyles.forEach(function (style) {
|
||||||
|
style.remove();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Observe dynamic IFRAMEs being added
|
// Observe dynamic IFRAMEs being added
|
||||||
function initObserver() {
|
function initObserver() {
|
||||||
iframeObserver = new MutationObserver(function(mutations) {
|
iframeObserver = new MutationObserver(function (mutations) {
|
||||||
if (mutations.length > 1000) {
|
if (mutations.length > 1000) {
|
||||||
// use a much faster method for very complex pages with 100,000 mutations
|
// use a much faster method for very complex pages with 100,000 mutations
|
||||||
// (observer usually receives 1k-10k mutations per call)
|
// (observer usually receives 1k-10k mutations per call)
|
||||||
|
@ -288,8 +308,11 @@ function initObserver() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iframeObserver.start = function() {
|
iframeObserver.start = function () {
|
||||||
// will be ignored by browser if already observing
|
// will be ignored by browser if already observing
|
||||||
iframeObserver.observe(document, {childList: true, subtree: true});
|
iframeObserver.observe(document, {
|
||||||
}
|
childList: true,
|
||||||
|
subtree: true
|
||||||
|
});
|
||||||
|
};
|
||||||
}
|
}
|
124
background.js
124
background.js
|
@ -1,6 +1,9 @@
|
||||||
|
/*jshint undef:false*/
|
||||||
var frameIdMessageable;
|
var frameIdMessageable;
|
||||||
runTryCatch(function() {
|
runTryCatch(function () {
|
||||||
chrome.tabs.sendMessage(0, {}, {frameId: 0}, function() {
|
chrome.tabs.sendMessage(0, {}, {
|
||||||
|
frameId: 0
|
||||||
|
}, function () {
|
||||||
var clearError = chrome.runtime.lastError;
|
var clearError = chrome.runtime.lastError;
|
||||||
frameIdMessageable = true;
|
frameIdMessageable = true;
|
||||||
});
|
});
|
||||||
|
@ -14,28 +17,41 @@ if ("onHistoryStateUpdated" in chrome.webNavigation) {
|
||||||
chrome.webNavigation.onHistoryStateUpdated.addListener(webNavigationListener.bind(this, "styleReplaceAll"));
|
chrome.webNavigation.onHistoryStateUpdated.addListener(webNavigationListener.bind(this, "styleReplaceAll"));
|
||||||
}
|
}
|
||||||
chrome.webNavigation.onBeforeNavigate.addListener(webNavigationListener.bind(this, null));
|
chrome.webNavigation.onBeforeNavigate.addListener(webNavigationListener.bind(this, null));
|
||||||
|
|
||||||
function webNavigationListener(method, data) {
|
function webNavigationListener(method, data) {
|
||||||
// Until Chrome 41, we can't target a frame with a message
|
// Until Chrome 41, we can't target a frame with a message
|
||||||
// (https://developer.chrome.com/extensions/tabs#method-sendMessage)
|
// (https://developer.chrome.com/extensions/tabs#method-sendMessage)
|
||||||
// so a style affecting a page with an iframe will affect the main page as well.
|
// so a style affecting a page with an iframe will affect the main page as well.
|
||||||
// Skip doing this for frames in pre-41 to prevent page flicker.
|
// Skip doing this for frames in pre-41 to prevent page flicker.
|
||||||
if (data.frameId != 0 && !frameIdMessageable) {
|
if (data.frameId !== 0 && !frameIdMessageable) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getStyles({matchUrl: data.url, enabled: true, asHash: true}, function(styleHash) {
|
getStyles({
|
||||||
|
matchUrl: data.url,
|
||||||
|
enabled: true,
|
||||||
|
asHash: true
|
||||||
|
}, function (styleHash) {
|
||||||
if (method) {
|
if (method) {
|
||||||
chrome.tabs.sendMessage(data.tabId, {method: method, styles: styleHash},
|
chrome.tabs.sendMessage(data.tabId, {
|
||||||
frameIdMessageable ? {frameId: data.frameId} : undefined);
|
method: method,
|
||||||
|
styles: styleHash
|
||||||
|
},
|
||||||
|
frameIdMessageable ? {
|
||||||
|
frameId: data.frameId
|
||||||
|
} : undefined);
|
||||||
}
|
}
|
||||||
if (data.frameId == 0) {
|
if (data.frameId === 0) {
|
||||||
updateIcon({id: data.tabId, url: data.url}, styleHash);
|
updateIcon({
|
||||||
|
id: data.tabId,
|
||||||
|
url: data.url
|
||||||
|
}, styleHash);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// catch direct URL hash modifications not invoked via HTML5 history API
|
// catch direct URL hash modifications not invoked via HTML5 history API
|
||||||
var tabUrlHasHash = {};
|
var tabUrlHasHash = {};
|
||||||
chrome.tabs.onUpdated.addListener(function(tabId, info, tab) {
|
chrome.tabs.onUpdated.addListener(function (tabId, info, tab) {
|
||||||
if (info.status == "loading" && info.url) {
|
if (info.status == "loading" && info.url) {
|
||||||
if (info.url.indexOf('#') > 0) {
|
if (info.url.indexOf('#') > 0) {
|
||||||
tabUrlHasHash[tabId] = true;
|
tabUrlHasHash[tabId] = true;
|
||||||
|
@ -45,21 +61,23 @@ chrome.tabs.onUpdated.addListener(function(tabId, info, tab) {
|
||||||
// do nothing since the tab neither had # before nor has # now
|
// do nothing since the tab neither had # before nor has # now
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
webNavigationListener("styleReplaceAll", {tabId: tabId, frameId: 0, url: info.url});
|
webNavigationListener("styleReplaceAll", {
|
||||||
|
tabId: tabId,
|
||||||
|
frameId: 0,
|
||||||
|
url: info.url
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
chrome.tabs.onRemoved.addListener(function(tabId, info) {
|
chrome.tabs.onRemoved.addListener(function (tabId, info) {
|
||||||
delete tabUrlHasHash[tabId];
|
delete tabUrlHasHash[tabId];
|
||||||
});
|
});
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
|
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
|
||||||
switch (request.method) {
|
switch (request.method) {
|
||||||
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
|
if (request.matchUrl && !request.id && sender && sender.tab && sender.frameId === 0 && sender.tab.url == request.matchUrl) {
|
||||||
&& sender && sender.tab && sender.frameId == 0
|
|
||||||
&& sender.tab.url == request.matchUrl) {
|
|
||||||
updateIcon(sender.tab, styles);
|
updateIcon(sender.tab, styles);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -72,17 +90,25 @@ chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "healthCheck":
|
case "healthCheck":
|
||||||
getDatabase(function() { sendResponse(true); }, function() { sendResponse(false); });
|
getDatabase(function () {
|
||||||
|
sendResponse(true);
|
||||||
|
}, function () {
|
||||||
|
sendResponse(false);
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
case "openURL":
|
case "openURL":
|
||||||
openURL(request);
|
openURL(request);
|
||||||
break;
|
break;
|
||||||
case "styleDisableAll":
|
case "styleDisableAll":
|
||||||
chrome.contextMenus.update("disableAll", {checked: request.disableAll});
|
chrome.contextMenus.update("disableAll", {
|
||||||
|
checked: request.disableAll
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case "prefChanged":
|
case "prefChanged":
|
||||||
if (request.prefName == "show-badge") {
|
if (request.prefName == "show-badge") {
|
||||||
chrome.contextMenus.update("show-badge", {checked: request.value});
|
chrome.contextMenus.update("show-badge", {
|
||||||
|
checked: request.value
|
||||||
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -91,14 +117,18 @@ chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
|
||||||
|
|
||||||
// Not available in Firefox - https://bugzilla.mozilla.org/show_bug.cgi?id=1240350
|
// Not available in Firefox - https://bugzilla.mozilla.org/show_bug.cgi?id=1240350
|
||||||
if ("commands" in chrome) {
|
if ("commands" in chrome) {
|
||||||
chrome.commands.onCommand.addListener(function(command) {
|
chrome.commands.onCommand.addListener(function (command) {
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case "openManage":
|
case "openManage":
|
||||||
openURL({url: chrome.extension.getURL("manage.html")});
|
openURL({
|
||||||
|
url: chrome.extension.getURL("manage.html")
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case "styleDisableAll":
|
case "styleDisableAll":
|
||||||
disableAllStylesToggle();
|
disableAllStylesToggle();
|
||||||
chrome.contextMenus.update("disableAll", {checked: prefs.get("disableAll")});
|
chrome.contextMenus.update("disableAll", {
|
||||||
|
checked: prefs.get("disableAll")
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -106,18 +136,28 @@ if ("commands" in chrome) {
|
||||||
|
|
||||||
// contextMenus API is present in ancient Chrome but it throws an exception
|
// contextMenus API is present in ancient Chrome but it throws an exception
|
||||||
// upon encountering the unsupported parameter value "browser_action", so we have to catch it.
|
// upon encountering the unsupported parameter value "browser_action", so we have to catch it.
|
||||||
runTryCatch(function() {
|
runTryCatch(function () {
|
||||||
chrome.contextMenus.create({
|
chrome.contextMenus.create({
|
||||||
id: "show-badge", title: chrome.i18n.getMessage("menuShowBadge"),
|
id: "show-badge",
|
||||||
type: "checkbox", contexts: ["browser_action"], checked: prefs.get("show-badge")
|
title: chrome.i18n.getMessage("menuShowBadge"),
|
||||||
}, function() { var clearError = chrome.runtime.lastError });
|
type: "checkbox",
|
||||||
|
contexts: ["browser_action"],
|
||||||
|
checked: prefs.get("show-badge")
|
||||||
|
}, function () {
|
||||||
|
var clearError = chrome.runtime.lastError;
|
||||||
|
});
|
||||||
chrome.contextMenus.create({
|
chrome.contextMenus.create({
|
||||||
id: "disableAll", title: chrome.i18n.getMessage("disableAllStyles"),
|
id: "disableAll",
|
||||||
type: "checkbox", contexts: ["browser_action"], checked: prefs.get("disableAll")
|
title: chrome.i18n.getMessage("disableAllStyles"),
|
||||||
}, function() { var clearError = chrome.runtime.lastError });
|
type: "checkbox",
|
||||||
|
contexts: ["browser_action"],
|
||||||
|
checked: prefs.get("disableAll")
|
||||||
|
}, function () {
|
||||||
|
var clearError = chrome.runtime.lastError;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
chrome.contextMenus.onClicked.addListener(function(info, tab) {
|
chrome.contextMenus.onClicked.addListener(function (info, tab) {
|
||||||
if (info.menuItemId == "disableAll") {
|
if (info.menuItemId == "disableAll") {
|
||||||
disableAllStylesToggle(info.checked);
|
disableAllStylesToggle(info.checked);
|
||||||
} else {
|
} else {
|
||||||
|
@ -133,14 +173,16 @@ function disableAllStylesToggle(newState) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the DB so that any first run actions will be performed immediately when the background page loads.
|
// Get the DB so that any first run actions will be performed immediately when the background page loads.
|
||||||
getDatabase(function() {}, reportError);
|
getDatabase(function () {}, reportError);
|
||||||
|
|
||||||
// When an edit page gets attached or detached, remember its state so we can do the same to the next one to open.
|
// When an edit page gets attached or detached, remember its state so we can do the same to the next one to open.
|
||||||
var editFullUrl = chrome.extension.getURL("edit.html");
|
var editFullUrl = chrome.extension.getURL("edit.html");
|
||||||
chrome.tabs.onAttached.addListener(function(tabId, data) {
|
chrome.tabs.onAttached.addListener(function (tabId, data) {
|
||||||
chrome.tabs.get(tabId, function(tabData) {
|
chrome.tabs.get(tabId, function (tabData) {
|
||||||
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.set("openEditInWindow", win.tabs.length == 1);
|
prefs.set("openEditInWindow", win.tabs.length == 1);
|
||||||
});
|
});
|
||||||
|
@ -149,13 +191,19 @@ chrome.tabs.onAttached.addListener(function(tabId, data) {
|
||||||
});
|
});
|
||||||
|
|
||||||
function openURL(options) {
|
function openURL(options) {
|
||||||
chrome.tabs.query({currentWindow: true, url: options.url}, function(tabs) {
|
chrome.tabs.query({
|
||||||
|
currentWindow: true,
|
||||||
|
url: options.url
|
||||||
|
}, function (tabs) {
|
||||||
// switch to an existing tab with the requested url
|
// switch to an existing tab with the requested url
|
||||||
if (tabs.length) {
|
if (tabs.length) {
|
||||||
chrome.tabs.highlight({windowId: tabs[0].windowId, tabs: tabs[0].index}, function (window) {});
|
chrome.tabs.highlight({
|
||||||
|
windowId: tabs[0].windowId,
|
||||||
|
tabs: tabs[0].index
|
||||||
|
}, function (window) {});
|
||||||
} else {
|
} else {
|
||||||
delete options.method;
|
delete options.method;
|
||||||
getActiveTab(function(tab) {
|
getActiveTab(function (tab) {
|
||||||
// re-use an active new tab page
|
// re-use an active new tab page
|
||||||
chrome.tabs[tab.url == "chrome://newtab/" ? "update" : "create"](options);
|
chrome.tabs[tab.url == "chrome://newtab/" ? "update" : "create"](options);
|
||||||
});
|
});
|
||||||
|
@ -164,6 +212,6 @@ function openURL(options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var codeMirrorThemes;
|
var codeMirrorThemes;
|
||||||
getCodeMirrorThemes(function(themes) {
|
getCodeMirrorThemes(function (themes) {
|
||||||
codeMirrorThemes = themes;
|
codeMirrorThemes = themes;
|
||||||
});
|
});
|
9937
csslint/csslint.js
9937
csslint/csslint.js
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,4 @@
|
||||||
|
/*jshint undef:false*/
|
||||||
healthCheck();
|
healthCheck();
|
||||||
|
|
||||||
function healthCheck() {
|
function healthCheck() {
|
||||||
|
|
79
install.js
79
install.js
|
@ -1,5 +1,9 @@
|
||||||
chrome.runtime.sendMessage({method: "getStyles", url: getMeta("stylish-id-url") || location.href}, function(response) {
|
/*jshint undef:false*/
|
||||||
if (response.length == 0) {
|
chrome.runtime.sendMessage({
|
||||||
|
method: "getStyles",
|
||||||
|
url: getMeta("stylish-id-url") || location.href
|
||||||
|
}, function (response) {
|
||||||
|
if (response.length === 0) {
|
||||||
sendEvent("styleCanBeInstalledChrome");
|
sendEvent("styleCanBeInstalledChrome");
|
||||||
} else {
|
} else {
|
||||||
var installedStyle = response[0];
|
var installedStyle = response[0];
|
||||||
|
@ -7,32 +11,42 @@ chrome.runtime.sendMessage({method: "getStyles", url: getMeta("stylish-id-url")
|
||||||
// use the md5 if available
|
// use the md5 if available
|
||||||
var md5Url = getMeta("stylish-md5-url");
|
var md5Url = getMeta("stylish-md5-url");
|
||||||
if (md5Url && installedStyle.md5Url && installedStyle.originalMd5) {
|
if (md5Url && installedStyle.md5Url && installedStyle.originalMd5) {
|
||||||
getResource(md5Url, function(md5) {
|
getResource(md5Url, function (md5) {
|
||||||
if (md5 == installedStyle.originalMd5) {
|
if (md5 == installedStyle.originalMd5) {
|
||||||
sendEvent("styleAlreadyInstalledChrome", {updateUrl: installedStyle.updateUrl});
|
sendEvent("styleAlreadyInstalledChrome", {
|
||||||
|
updateUrl: installedStyle.updateUrl
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
sendEvent("styleCanBeUpdatedChrome", {updateUrl: installedStyle.updateUrl});
|
sendEvent("styleCanBeUpdatedChrome", {
|
||||||
|
updateUrl: installedStyle.updateUrl
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
getResource(getMeta("stylish-code-chrome"), function(code) {
|
getResource(getMeta("stylish-code-chrome"), function (code) {
|
||||||
// this would indicate a failure (a style with settings?).
|
// this would indicate a failure (a style with settings?).
|
||||||
if (code == null) {
|
if (code === null) {
|
||||||
sendEvent("styleCanBeUpdatedChrome", {updateUrl: installedStyle.updateUrl});
|
sendEvent("styleCanBeUpdatedChrome", {
|
||||||
|
updateUrl: installedStyle.updateUrl
|
||||||
|
});
|
||||||
}
|
}
|
||||||
var json = JSON.parse(code);
|
var json = JSON.parse(code);
|
||||||
if (json.sections.length == installedStyle.sections.length) {
|
if (json.sections.length == installedStyle.sections.length) {
|
||||||
if (json.sections.every(function(section) {
|
if (json.sections.every(function (section) {
|
||||||
return installedStyle.sections.some(function(installedSection) {
|
return installedStyle.sections.some(function (installedSection) {
|
||||||
return sectionsAreEqual(section, installedSection);
|
return sectionsAreEqual(section, installedSection);
|
||||||
});
|
});
|
||||||
})) {
|
})) {
|
||||||
// everything's the same
|
// everything's the same
|
||||||
sendEvent("styleAlreadyInstalledChrome", {updateUrl: installedStyle.updateUrl});
|
sendEvent("styleAlreadyInstalledChrome", {
|
||||||
|
updateUrl: installedStyle.updateUrl
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
sendEvent("styleCanBeUpdatedChrome", {updateUrl: installedStyle.updateUrl});
|
}
|
||||||
|
sendEvent("styleCanBeUpdatedChrome", {
|
||||||
|
updateUrl: installedStyle.updateUrl
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +56,7 @@ function sectionsAreEqual(a, b) {
|
||||||
if (a.code != b.code) {
|
if (a.code != b.code) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return ["urls", "urlPrefixes", "domains", "regexps"].every(function(attribute) {
|
return ["urls", "urlPrefixes", "domains", "regexps"].every(function (attribute) {
|
||||||
return arraysAreEqual(a[attribute], b[attribute]);
|
return arraysAreEqual(a[attribute], b[attribute]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -50,13 +64,13 @@ function sectionsAreEqual(a, b) {
|
||||||
function arraysAreEqual(a, b) {
|
function arraysAreEqual(a, b) {
|
||||||
// treat empty array and undefined as equivalent
|
// treat empty array and undefined as equivalent
|
||||||
if (typeof a == "undefined")
|
if (typeof a == "undefined")
|
||||||
return (typeof b == "undefined") || (b.length == 0);
|
return (typeof b == "undefined") || (b.length === 0);
|
||||||
if (typeof b == "undefined")
|
if (typeof b == "undefined")
|
||||||
return (typeof a == "undefined") || (a.length == 0);
|
return (typeof a == "undefined") || (a.length === 0);
|
||||||
if (a.length != b.length) {
|
if (a.length != b.length) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return a.every(function(entry) {
|
return a.every(function (entry) {
|
||||||
return b.indexOf(entry) != -1;
|
return b.indexOf(entry) != -1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -65,18 +79,20 @@ function sendEvent(type, data) {
|
||||||
if (typeof data == "undefined") {
|
if (typeof data == "undefined") {
|
||||||
data = null;
|
data = null;
|
||||||
}
|
}
|
||||||
var stylishEvent = new CustomEvent(type, {detail: data});
|
var stylishEvent = new CustomEvent(type, {
|
||||||
|
detail: data
|
||||||
|
});
|
||||||
document.dispatchEvent(stylishEvent);
|
document.dispatchEvent(stylishEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("stylishInstallChrome", function() {
|
document.addEventListener("stylishInstallChrome", function () {
|
||||||
getResource(getMeta("stylish-description"), function(name) {
|
getResource(getMeta("stylish-description"), function (name) {
|
||||||
if (confirm(chrome.i18n.getMessage('styleInstall', [name]))) {
|
if (confirm(chrome.i18n.getMessage('styleInstall', [name]))) {
|
||||||
getResource(getMeta("stylish-code-chrome"), function(code) {
|
getResource(getMeta("stylish-code-chrome"), function (code) {
|
||||||
// check for old style json
|
// check for old style json
|
||||||
var json = JSON.parse(code);
|
var json = JSON.parse(code);
|
||||||
json.method = "saveStyle";
|
json.method = "saveStyle";
|
||||||
chrome.runtime.sendMessage(json, function(response) {
|
chrome.runtime.sendMessage(json, function (response) {
|
||||||
sendEvent("styleInstalledChrome");
|
sendEvent("styleInstalledChrome");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -85,15 +101,18 @@ document.addEventListener("stylishInstallChrome", function() {
|
||||||
});
|
});
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
document.addEventListener("stylishUpdateChrome", function() {
|
document.addEventListener("stylishUpdateChrome", function () {
|
||||||
chrome.runtime.sendMessage({method: "getStyles", url: getMeta("stylish-id-url") || location.href}, function(response) {
|
chrome.runtime.sendMessage({
|
||||||
|
method: "getStyles",
|
||||||
|
url: getMeta("stylish-id-url") || location.href
|
||||||
|
}, function (response) {
|
||||||
var style = response[0];
|
var style = response[0];
|
||||||
if (confirm(chrome.i18n.getMessage('styleUpdate', [style.name]))) {
|
if (confirm(chrome.i18n.getMessage('styleUpdate', [style.name]))) {
|
||||||
getResource(getMeta("stylish-code-chrome"), function(code) {
|
getResource(getMeta("stylish-code-chrome"), function (code) {
|
||||||
var json = JSON.parse(code);
|
var json = JSON.parse(code);
|
||||||
json.method = "saveStyle";
|
json.method = "saveStyle";
|
||||||
json.id = style.id;
|
json.id = style.id;
|
||||||
chrome.runtime.sendMessage(json, function() {
|
chrome.runtime.sendMessage(json, function () {
|
||||||
sendEvent("styleInstalledChrome");
|
sendEvent("styleInstalledChrome");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -108,14 +127,14 @@ function getMeta(name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getResource(url, callback) {
|
function getResource(url, callback) {
|
||||||
if (url.indexOf("#") == 0) {
|
if (url.indexOf("#") === 0) {
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(document.getElementById(url.substring(1)).innerText);
|
callback(document.getElementById(url.substring(1)).innerText);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.onreadystatechange = function() {
|
xhr.onreadystatechange = function () {
|
||||||
if (xhr.readyState == 4 && callback) {
|
if (xhr.readyState == 4 && callback) {
|
||||||
if (xhr.status >= 400) {
|
if (xhr.status >= 400) {
|
||||||
callback(null);
|
callback(null);
|
||||||
|
@ -123,11 +142,11 @@ function getResource(url, callback) {
|
||||||
callback(xhr.responseText);
|
callback(xhr.responseText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
if (url.length > 2000) {
|
if (url.length > 2000) {
|
||||||
var parts = url.split("?");
|
var parts = url.split("?");
|
||||||
xhr.open("POST", parts[0], true);
|
xhr.open("POST", parts[0], true);
|
||||||
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
|
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||||
xhr.send(parts[1]);
|
xhr.send(parts[1]);
|
||||||
} else {
|
} else {
|
||||||
xhr.open("GET", url, true);
|
xhr.open("GET", url, true);
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
/*jshint undef:false*/
|
||||||
var template = {};
|
var template = {};
|
||||||
tDocLoader();
|
tDocLoader();
|
||||||
|
|
||||||
function t(key, params) {
|
function t(key, params) {
|
||||||
var s = chrome.i18n.getMessage(key, params)
|
var s = chrome.i18n.getMessage(key, params);
|
||||||
if (s == "") {
|
if (s === "") {
|
||||||
throw "Missing string '" + key + "'.";
|
throw "Missing string '" + key + "'.";
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
@ -44,7 +45,7 @@ function tNodeList(nodes) {
|
||||||
for (var a = node.attributes.length - 1; a >= 0; a--) {
|
for (var a = node.attributes.length - 1; a >= 0; a--) {
|
||||||
var attr = node.attributes[a];
|
var attr = node.attributes[a];
|
||||||
var name = attr.nodeName;
|
var name = attr.nodeName;
|
||||||
if (name.indexOf("i18n-") != 0) {
|
if (name.indexOf("i18n-") !== 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
name = name.substr(5); // "i18n-".length
|
name = name.substr(5); // "i18n-".length
|
||||||
|
|
153
manage.js
153
manage.js
|
@ -1,3 +1,4 @@
|
||||||
|
/*jshint undef:false*/
|
||||||
var lastUpdatedStyleId = null;
|
var lastUpdatedStyleId = null;
|
||||||
var installed;
|
var installed;
|
||||||
|
|
||||||
|
@ -5,11 +6,15 @@ var appliesToExtraTemplate = document.createElement("span");
|
||||||
appliesToExtraTemplate.className = "applies-to-extra";
|
appliesToExtraTemplate.className = "applies-to-extra";
|
||||||
appliesToExtraTemplate.innerHTML = " " + t('appliesDisplayTruncatedSuffix');
|
appliesToExtraTemplate.innerHTML = " " + t('appliesDisplayTruncatedSuffix');
|
||||||
|
|
||||||
chrome.runtime.sendMessage({method: "getStyles"}, showStyles);
|
chrome.runtime.sendMessage({
|
||||||
|
method: "getStyles"
|
||||||
|
}, showStyles);
|
||||||
|
|
||||||
function showStyles(styles) {
|
function showStyles(styles) {
|
||||||
if (!styles) { // Chrome is starting up
|
if (!styles) { // Chrome is starting up
|
||||||
chrome.runtime.sendMessage({method: "getStyles"}, showStyles);
|
chrome.runtime.sendMessage({
|
||||||
|
method: "getStyles"
|
||||||
|
}, showStyles);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!installed) {
|
if (!installed) {
|
||||||
|
@ -18,8 +23,10 @@ function showStyles(styles) {
|
||||||
document.stylishStyles = styles;
|
document.stylishStyles = styles;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
styles.sort(function(a, b) { return a.name.localeCompare(b.name)});
|
styles.sort(function (a, b) {
|
||||||
styles.map(createStyleElement).forEach(function(e) {
|
return a.name.localeCompare(b.name);
|
||||||
|
});
|
||||||
|
styles.map(createStyleElement).forEach(function (e) {
|
||||||
installed.appendChild(e);
|
installed.appendChild(e);
|
||||||
});
|
});
|
||||||
if (history.state) {
|
if (history.state) {
|
||||||
|
@ -44,23 +51,24 @@ function createStyleElement(style) {
|
||||||
var styleName = e.querySelector(".style-name");
|
var styleName = e.querySelector(".style-name");
|
||||||
styleName.appendChild(document.createTextNode(style.name));
|
styleName.appendChild(document.createTextNode(style.name));
|
||||||
if (style.url) {
|
if (style.url) {
|
||||||
var homepage = template.styleHomepage.cloneNode(true)
|
var homepage = template.styleHomepage.cloneNode(true);
|
||||||
homepage.setAttribute("href", style.url);
|
homepage.setAttribute("href", style.url);
|
||||||
styleName.appendChild(document.createTextNode(" " ));
|
styleName.appendChild(document.createTextNode(" "));
|
||||||
styleName.appendChild(homepage);
|
styleName.appendChild(homepage);
|
||||||
}
|
}
|
||||||
var domains = [];
|
var domains = [];
|
||||||
var urls = [];
|
var urls = [];
|
||||||
var urlPrefixes = [];
|
var urlPrefixes = [];
|
||||||
var regexps = [];
|
var regexps = [];
|
||||||
|
|
||||||
function add(array, property) {
|
function add(array, property) {
|
||||||
style.sections.forEach(function(section) {
|
style.sections.forEach(function (section) {
|
||||||
if (section[property]) {
|
if (section[property]) {
|
||||||
section[property].filter(function(value) {
|
section[property].filter(function (value) {
|
||||||
return array.indexOf(value) == -1;
|
return array.indexOf(value) == -1;
|
||||||
}).forEach(function(value) {
|
}).forEach(function (value) {
|
||||||
array.push(value);
|
array.push(value);
|
||||||
});;
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -74,12 +82,16 @@ function createStyleElement(style) {
|
||||||
if (urls)
|
if (urls)
|
||||||
appliesToToShow = appliesToToShow.concat(urls);
|
appliesToToShow = appliesToToShow.concat(urls);
|
||||||
if (urlPrefixes)
|
if (urlPrefixes)
|
||||||
appliesToToShow = appliesToToShow.concat(urlPrefixes.map(function(u) { return u + "*"; }));
|
appliesToToShow = appliesToToShow.concat(urlPrefixes.map(function (u) {
|
||||||
|
return u + "*";
|
||||||
|
}));
|
||||||
if (regexps)
|
if (regexps)
|
||||||
appliesToToShow = appliesToToShow.concat(regexps.map(function(u) { return "/" + u + "/"; }));
|
appliesToToShow = appliesToToShow.concat(regexps.map(function (u) {
|
||||||
|
return "/" + u + "/";
|
||||||
|
}));
|
||||||
var appliesToString = "";
|
var appliesToString = "";
|
||||||
var showAppliesToExtra = false;
|
var showAppliesToExtra = false;
|
||||||
if (appliesToToShow.length == "")
|
if (appliesToToShow.length === "")
|
||||||
appliesToString = t('appliesToEverything');
|
appliesToString = t('appliesToEverything');
|
||||||
else if (appliesToToShow.length <= 10)
|
else if (appliesToToShow.length <= 10)
|
||||||
appliesToString = appliesToToShow.join(", ");
|
appliesToString = appliesToToShow.join(", ");
|
||||||
|
@ -93,10 +105,12 @@ function createStyleElement(style) {
|
||||||
}
|
}
|
||||||
var editLink = e.querySelector(".style-edit-link");
|
var editLink = e.querySelector(".style-edit-link");
|
||||||
editLink.setAttribute("href", editLink.getAttribute("href") + style.id);
|
editLink.setAttribute("href", editLink.getAttribute("href") + style.id);
|
||||||
editLink.addEventListener("click", function(event) {
|
editLink.addEventListener("click", function (event) {
|
||||||
if (!event.altKey) {
|
if (!event.altKey) {
|
||||||
var left = event.button == 0, middle = event.button == 1,
|
var left = event.button === 0,
|
||||||
shift = event.shiftKey, ctrl = event.ctrlKey;
|
middle = event.button == 1,
|
||||||
|
shift = event.shiftKey,
|
||||||
|
ctrl = event.ctrlKey;
|
||||||
var openWindow = left && shift && !ctrl;
|
var openWindow = left && shift && !ctrl;
|
||||||
var openBackgroundTab = (middle && !shift) || (left && ctrl && !shift);
|
var openBackgroundTab = (middle && !shift) || (left && ctrl && !shift);
|
||||||
var openForegroundTab = (middle && shift) || (left && ctrl && shift);
|
var openForegroundTab = (middle && shift) || (left && ctrl && shift);
|
||||||
|
@ -116,16 +130,22 @@ function createStyleElement(style) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
history.replaceState({scrollY: window.scrollY}, document.title);
|
history.replaceState({
|
||||||
getActiveTab(function(tab) {
|
scrollY: window.scrollY
|
||||||
|
}, document.title);
|
||||||
|
getActiveTab(function (tab) {
|
||||||
sessionStorageHash("manageStylesHistory").set(tab.id, url);
|
sessionStorageHash("manageStylesHistory").set(tab.id, url);
|
||||||
location.href = url;
|
location.href = url;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
e.querySelector(".enable").addEventListener("click", function(event) { enable(event, true); }, false);
|
e.querySelector(".enable").addEventListener("click", function (event) {
|
||||||
e.querySelector(".disable").addEventListener("click", function(event) { enable(event, false); }, false);
|
enable(event, true);
|
||||||
|
}, false);
|
||||||
|
e.querySelector(".disable").addEventListener("click", function (event) {
|
||||||
|
enable(event, false);
|
||||||
|
}, false);
|
||||||
e.querySelector(".check-update").addEventListener("click", doCheckUpdate, false);
|
e.querySelector(".check-update").addEventListener("click", doCheckUpdate, false);
|
||||||
e.querySelector(".update").addEventListener("click", doUpdate, false);
|
e.querySelector(".update").addEventListener("click", doUpdate, false);
|
||||||
e.querySelector(".delete").addEventListener("click", doDelete, false);
|
e.querySelector(".delete").addEventListener("click", doDelete, false);
|
||||||
|
@ -160,7 +180,7 @@ function getStyleElement(event) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
|
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
|
||||||
switch (request.method) {
|
switch (request.method) {
|
||||||
case "styleUpdated":
|
case "styleUpdated":
|
||||||
handleUpdate(request.style);
|
handleUpdate(request.style);
|
||||||
|
@ -181,7 +201,7 @@ function handleUpdate(style) {
|
||||||
lastUpdatedStyleId = null;
|
lastUpdatedStyleId = null;
|
||||||
element.className = element.className += " update-done";
|
element.className = element.className += " update-done";
|
||||||
element.querySelector(".update-note").innerHTML = t('updateCompleted');
|
element.querySelector(".update-note").innerHTML = t('updateCompleted');
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDelete(id) {
|
function handleDelete(id) {
|
||||||
|
@ -198,12 +218,12 @@ function doCheckUpdate(event) {
|
||||||
function applyUpdateAll() {
|
function applyUpdateAll() {
|
||||||
var btnApply = document.getElementById("apply-all-updates");
|
var btnApply = document.getElementById("apply-all-updates");
|
||||||
btnApply.disabled = true;
|
btnApply.disabled = true;
|
||||||
setTimeout(function() {
|
setTimeout(function () {
|
||||||
btnApply.style.display = "none";
|
btnApply.style.display = "none";
|
||||||
btnApply.disabled = false;
|
btnApply.disabled = false;
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
Array.prototype.forEach.call(document.querySelectorAll(".can-update .update"), function(button) {
|
Array.prototype.forEach.call(document.querySelectorAll(".can-update .update"), function (button) {
|
||||||
button.click();
|
button.click();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -220,18 +240,18 @@ function checkUpdateAll() {
|
||||||
var elements = document.querySelectorAll("[style-update-url]");
|
var elements = document.querySelectorAll("[style-update-url]");
|
||||||
var toCheckCount = elements.length;
|
var toCheckCount = elements.length;
|
||||||
var updatableCount = 0;
|
var updatableCount = 0;
|
||||||
Array.prototype.forEach.call(elements, function(element) {
|
Array.prototype.forEach.call(elements, function (element) {
|
||||||
checkUpdate(element, function(success) {
|
checkUpdate(element, function (success) {
|
||||||
if (success) {
|
if (success) {
|
||||||
++updatableCount;
|
++updatableCount;
|
||||||
}
|
}
|
||||||
if (--toCheckCount == 0) {
|
if (--toCheckCount === 0) {
|
||||||
btnCheck.disabled = false;
|
btnCheck.disabled = false;
|
||||||
if (updatableCount) {
|
if (updatableCount) {
|
||||||
btnApply.classList.remove("hidden");
|
btnApply.classList.remove("hidden");
|
||||||
} else {
|
} else {
|
||||||
noUpdates.classList.remove("hidden");
|
noUpdates.classList.remove("hidden");
|
||||||
setTimeout(function() {
|
setTimeout(function () {
|
||||||
noUpdates.classList.add("hidden");
|
noUpdates.classList.add("hidden");
|
||||||
}, 10000);
|
}, 10000);
|
||||||
}
|
}
|
||||||
|
@ -249,7 +269,10 @@ function checkUpdate(element, callback) {
|
||||||
var originalMd5 = element.getAttribute("style-original-md5");
|
var originalMd5 = element.getAttribute("style-original-md5");
|
||||||
|
|
||||||
function handleSuccess(forceUpdate, serverJson) {
|
function handleSuccess(forceUpdate, serverJson) {
|
||||||
chrome.runtime.sendMessage({method: "getStyles", id: id}, function(styles) {
|
chrome.runtime.sendMessage({
|
||||||
|
method: "getStyles",
|
||||||
|
id: id
|
||||||
|
}, function (styles) {
|
||||||
var style = styles[0];
|
var style = styles[0];
|
||||||
var needsUpdate = false;
|
var needsUpdate = false;
|
||||||
if (!forceUpdate && codeIsEqual(style.sections, serverJson.sections)) {
|
if (!forceUpdate && codeIsEqual(style.sections, serverJson.sections)) {
|
||||||
|
@ -265,7 +288,7 @@ function checkUpdate(element, callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleFailure(status) {
|
function handleFailure(status) {
|
||||||
if (status == 0) {
|
if (status === 0) {
|
||||||
handleNeedsUpdate(t('updateCheckFailServerUnreachable'), id, null);
|
handleNeedsUpdate(t('updateCheckFailServerUnreachable'), id, null);
|
||||||
} else {
|
} else {
|
||||||
handleNeedsUpdate(t('updateCheckFailBadResponseCode', [status]), id, null);
|
handleNeedsUpdate(t('updateCheckFailBadResponseCode', [status]), id, null);
|
||||||
|
@ -276,9 +299,9 @@ function checkUpdate(element, callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!md5Url || !originalMd5) {
|
if (!md5Url || !originalMd5) {
|
||||||
checkUpdateFullCode(url, false, handleSuccess, handleFailure)
|
checkUpdateFullCode(url, false, handleSuccess, handleFailure);
|
||||||
} else {
|
} else {
|
||||||
checkUpdateMd5(originalMd5, md5Url, function(needsUpdate) {
|
checkUpdateMd5(originalMd5, md5Url, function (needsUpdate) {
|
||||||
if (needsUpdate) {
|
if (needsUpdate) {
|
||||||
// If the md5 shows a change we will update regardless of whether the code looks different
|
// If the md5 shows a change we will update regardless of whether the code looks different
|
||||||
checkUpdateFullCode(url, true, handleSuccess, handleFailure);
|
checkUpdateFullCode(url, true, handleSuccess, handleFailure);
|
||||||
|
@ -293,13 +316,13 @@ function checkUpdate(element, callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkUpdateFullCode(url, forceUpdate, successCallback, failureCallback) {
|
function checkUpdateFullCode(url, forceUpdate, successCallback, failureCallback) {
|
||||||
download(url, function(responseText) {
|
download(url, function (responseText) {
|
||||||
successCallback(forceUpdate, JSON.parse(responseText));
|
successCallback(forceUpdate, JSON.parse(responseText));
|
||||||
}, failureCallback);
|
}, failureCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkUpdateMd5(originalMd5, md5Url, successCallback, failureCallback) {
|
function checkUpdateMd5(originalMd5, md5Url, successCallback, failureCallback) {
|
||||||
download(md5Url, function(responseText) {
|
download(md5Url, function (responseText) {
|
||||||
if (responseText.length != 32) {
|
if (responseText.length != 32) {
|
||||||
failureCallback(-1);
|
failureCallback(-1);
|
||||||
return;
|
return;
|
||||||
|
@ -313,16 +336,16 @@ function download(url, successCallback, failureCallback) {
|
||||||
xhr.onreadystatechange = function (aEvt) {
|
xhr.onreadystatechange = function (aEvt) {
|
||||||
if (xhr.readyState == 4) {
|
if (xhr.readyState == 4) {
|
||||||
if (xhr.status == 200) {
|
if (xhr.status == 200) {
|
||||||
successCallback(xhr.responseText)
|
successCallback(xhr.responseText);
|
||||||
} else {
|
} else {
|
||||||
failureCallback(xhr.status);
|
failureCallback(xhr.status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
if (url.length > 2000) {
|
if (url.length > 2000) {
|
||||||
var parts = url.split("?");
|
var parts = url.split("?");
|
||||||
xhr.open("POST", parts[0], true);
|
xhr.open("POST", parts[0], true);
|
||||||
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
|
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||||
xhr.send(parts[1]);
|
xhr.send(parts[1]);
|
||||||
} else {
|
} else {
|
||||||
xhr.open("GET", url, true);
|
xhr.open("GET", url, true);
|
||||||
|
@ -371,7 +394,7 @@ function codeIsEqual(a, b) {
|
||||||
for (var i = 0; i < a.length; i++) {
|
for (var i = 0; i < a.length; i++) {
|
||||||
var found = false;
|
var found = false;
|
||||||
for (var j = 0; j < b.length; j++) {
|
for (var j = 0; j < b.length; j++) {
|
||||||
var allEquals = properties.every(function(property) {
|
var allEquals = properties.every(function (property) {
|
||||||
return jsonEquals(a[i], b[j], property);
|
return jsonEquals(a[i], b[j], property);
|
||||||
});
|
});
|
||||||
if (allEquals) {
|
if (allEquals) {
|
||||||
|
@ -387,11 +410,13 @@ function codeIsEqual(a, b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function jsonEquals(a, b, property) {
|
function jsonEquals(a, b, property) {
|
||||||
var aProp = a[property], typeA = getType(aProp);
|
var aProp = a[property],
|
||||||
var bProp = b[property], typeB = getType(bProp);
|
typeA = getType(aProp);
|
||||||
|
var bProp = b[property],
|
||||||
|
typeB = getType(bProp);
|
||||||
if (typeA != typeB) {
|
if (typeA != typeB) {
|
||||||
// consider empty arrays equivalent to lack of property
|
// consider empty arrays equivalent to lack of property
|
||||||
if ((typeA == "undefined" || (typeA == "array" && aProp.length == 0)) && (typeB == "undefined" || (typeB == "array" && bProp.length == 0))) {
|
if ((typeA == "undefined" || (typeA == "array" && aProp.length === 0)) && (typeB == "undefined" || (typeB == "array" && bProp.length === 0))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -427,9 +452,12 @@ function searchStyles(immediately) {
|
||||||
clearTimeout(searchStyles.timeout);
|
clearTimeout(searchStyles.timeout);
|
||||||
searchStyles.timeout = setTimeout(doSearch, 100);
|
searchStyles.timeout = setTimeout(doSearch, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
function doSearch() {
|
function doSearch() {
|
||||||
chrome.runtime.sendMessage({method: "getStyles"}, function(styles) {
|
chrome.runtime.sendMessage({
|
||||||
styles.forEach(function(style) {
|
method: "getStyles"
|
||||||
|
}, function (styles) {
|
||||||
|
styles.forEach(function (style) {
|
||||||
var el = document.querySelector("[style-id='" + style.id + "']");
|
var el = document.querySelector("[style-id='" + style.id + "']");
|
||||||
if (el) {
|
if (el) {
|
||||||
el.style.display = !query || isMatchingText(style.name) || isMatchingStyle(style) ? "" : "none";
|
el.style.display = !query || isMatchingText(style.name) || isMatchingStyle(style) ? "" : "none";
|
||||||
|
@ -437,43 +465,49 @@ function searchStyles(immediately) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMatchingStyle(style) {
|
function isMatchingStyle(style) {
|
||||||
return style.sections.some(function(section) {
|
return style.sections.some(function (section) {
|
||||||
return Object.keys(section).some(function(key) {
|
return Object.keys(section).some(function (key) {
|
||||||
var value = section[key];
|
var value = section[key];
|
||||||
switch (typeof value) {
|
switch (typeof value) {
|
||||||
case "string": return isMatchingText(value);
|
case "string":
|
||||||
case "object": return value.some(isMatchingText);
|
return isMatchingText(value);
|
||||||
|
case "object":
|
||||||
|
return value.some(isMatchingText);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMatchingText(text) {
|
function isMatchingText(text) {
|
||||||
return text.toLocaleLowerCase().indexOf(query) >= 0;
|
return text.toLocaleLowerCase().indexOf(query) >= 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onFilterChange (className, event) {
|
function onFilterChange(className, event) {
|
||||||
installed.classList.toggle(className, event.target.checked);
|
installed.classList.toggle(className, event.target.checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
function initFilter(className, node) {
|
function initFilter(className, node) {
|
||||||
node.addEventListener("change", onFilterChange.bind(undefined, className), false);
|
node.addEventListener("change", onFilterChange.bind(undefined, className), false);
|
||||||
onFilterChange(className, {target: node});
|
onFilterChange(className, {
|
||||||
|
target: node
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function importStyles (e) {
|
function importStyles(e) {
|
||||||
var file = e.target.files[0];
|
var file = e.target.files[0];
|
||||||
var reader = new FileReader();
|
var reader = new FileReader();
|
||||||
var styles = [];
|
var styles = [];
|
||||||
|
|
||||||
function save () {
|
function save() {
|
||||||
var style = styles.shift();
|
var style = styles.shift();
|
||||||
if (style) {
|
if (style) {
|
||||||
delete style.id;
|
delete style.id;
|
||||||
saveStyle(style, save);
|
saveStyle(style, save);
|
||||||
}
|
} else {
|
||||||
else {
|
window.location.reload();
|
||||||
window.location.reload()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,22 +515,21 @@ function importStyles (e) {
|
||||||
try {
|
try {
|
||||||
styles = JSON.parse(evt.target.result);
|
styles = JSON.parse(evt.target.result);
|
||||||
save();
|
save();
|
||||||
}
|
} catch (e) {
|
||||||
catch (e) {
|
|
||||||
window.alert(e.message);
|
window.alert(e.message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
reader.onerror = function (e) {
|
reader.onerror = function (e) {
|
||||||
window.alert(e.message);
|
window.alert(e.message);
|
||||||
}
|
};
|
||||||
reader.readAsText(file)
|
reader.readAsText(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectAll () {
|
function selectAll() {
|
||||||
document.execCommand('selectAll');
|
document.execCommand('selectAll');
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
installed = document.getElementById("installed");
|
installed = document.getElementById("installed");
|
||||||
if (document.stylishStyles) {
|
if (document.stylishStyles) {
|
||||||
showStyles(document.stylishStyles);
|
showStyles(document.stylishStyles);
|
||||||
|
|
61
messaging.js
61
messaging.js
|
@ -1,14 +1,20 @@
|
||||||
|
/*jshint undef:false*/
|
||||||
function notifyAllTabs(request) {
|
function notifyAllTabs(request) {
|
||||||
chrome.windows.getAll({populate: true}, function(windows) {
|
chrome.windows.getAll({
|
||||||
windows.forEach(function(win) {
|
populate: true
|
||||||
win.tabs.forEach(function(tab) {
|
}, function (windows) {
|
||||||
|
windows.forEach(function (win) {
|
||||||
|
win.tabs.forEach(function (tab) {
|
||||||
chrome.tabs.sendMessage(tab.id, request);
|
chrome.tabs.sendMessage(tab.id, request);
|
||||||
updateIcon(tab);
|
updateIcon(tab);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// notify all open popups
|
// notify all open popups
|
||||||
var reqPopup = shallowMerge({}, request, {method: "updatePopup", reason: request.method});
|
var reqPopup = shallowMerge({}, request, {
|
||||||
|
method: "updatePopup",
|
||||||
|
reason: request.method
|
||||||
|
});
|
||||||
chrome.runtime.sendMessage(reqPopup);
|
chrome.runtime.sendMessage(reqPopup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +26,7 @@ function updateIcon(tab, styles) {
|
||||||
}
|
}
|
||||||
if (styles) {
|
if (styles) {
|
||||||
// check for not-yet-existing tabs e.g. omnibox instant search
|
// check for not-yet-existing tabs e.g. omnibox instant search
|
||||||
chrome.tabs.get(tab.id, function() {
|
chrome.tabs.get(tab.id, function () {
|
||||||
if (!chrome.runtime.lastError) {
|
if (!chrome.runtime.lastError) {
|
||||||
// for 'styles' asHash:true fake the length by counting numeric ids manually
|
// for 'styles' asHash:true fake the length by counting numeric ids manually
|
||||||
if (styles.length === undefined) {
|
if (styles.length === undefined) {
|
||||||
|
@ -34,33 +40,47 @@ function updateIcon(tab, styles) {
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getTabRealURL(tab, function(url) {
|
getTabRealURL(tab, function (url) {
|
||||||
// if we have access to this, call directly. a page sending a message to itself doesn't seem to work right.
|
// if we have access to this, call directly. a page sending a message to itself doesn't seem to work right.
|
||||||
if (typeof getStyles != "undefined") {
|
if (typeof getStyles != "undefined") {
|
||||||
getStyles({matchUrl: url, enabled: true}, stylesReceived);
|
getStyles({
|
||||||
|
matchUrl: url,
|
||||||
|
enabled: true
|
||||||
|
}, stylesReceived);
|
||||||
} else {
|
} else {
|
||||||
chrome.runtime.sendMessage({method: "getStyles", matchUrl: url, enabled: true}, stylesReceived);
|
chrome.runtime.sendMessage({
|
||||||
|
method: "getStyles",
|
||||||
|
matchUrl: url,
|
||||||
|
enabled: true
|
||||||
|
}, stylesReceived);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function stylesReceived(styles) {
|
function stylesReceived(styles) {
|
||||||
var disableAll = "disableAll" in styles ? styles.disableAll : prefs.get("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: {
|
path: {
|
||||||
// Material Design 2016 new size is 16px
|
// Material Design 2016 new size is 16px
|
||||||
16: "16" + postfix + ".png", 32: "32" + postfix + ".png",
|
16: "16" + postfix + ".png",
|
||||||
|
32: "32" + postfix + ".png",
|
||||||
// Chromium forks or non-chromium browsers may still use the traditional 19px
|
// Chromium forks or non-chromium browsers may still use the traditional 19px
|
||||||
19: "19" + postfix + ".png", 38: "38" + postfix + ".png",
|
19: "19" + postfix + ".png",
|
||||||
|
38: "38" + postfix + ".png",
|
||||||
},
|
},
|
||||||
tabId: tab.id
|
tabId: tab.id
|
||||||
}, function() {
|
}, function () {
|
||||||
// if the tab was just closed an error may occur,
|
// if the tab was just closed an error may occur,
|
||||||
// e.g. 'windowPosition' pref updated in edit.js::window.onbeforeunload
|
// e.g. 'windowPosition' pref updated in edit.js::window.onbeforeunload
|
||||||
if (!chrome.runtime.lastError) {
|
if (!chrome.runtime.lastError) {
|
||||||
var t = prefs.get("show-badge") && styles.length ? ("" + styles.length) : "";
|
var t = prefs.get("show-badge") && styles.length ? ("" + styles.length) : "";
|
||||||
chrome.browserAction.setBadgeText({text: t, tabId: tab.id});
|
chrome.browserAction.setBadgeText({
|
||||||
chrome.browserAction.setBadgeBackgroundColor({color: disableAll ? "#aaa" : [0, 0, 0, 0]});
|
text: t,
|
||||||
|
tabId: tab.id
|
||||||
|
});
|
||||||
|
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 + "'.");
|
||||||
|
@ -68,13 +88,16 @@ function updateIcon(tab, styles) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getActiveTab(callback) {
|
function getActiveTab(callback) {
|
||||||
chrome.tabs.query({currentWindow: true, active: true}, function(tabs) {
|
chrome.tabs.query({
|
||||||
|
currentWindow: true,
|
||||||
|
active: true
|
||||||
|
}, function (tabs) {
|
||||||
callback(tabs[0]);
|
callback(tabs[0]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getActiveTabRealURL(callback) {
|
function getActiveTabRealURL(callback) {
|
||||||
getActiveTab(function(tab) {
|
getActiveTab(function (tab) {
|
||||||
getTabRealURL(tab, callback);
|
getTabRealURL(tab, callback);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -83,7 +106,11 @@ function getTabRealURL(tab, callback) {
|
||||||
if (tab.url != "chrome://newtab/") {
|
if (tab.url != "chrome://newtab/") {
|
||||||
callback(tab.url);
|
callback(tab.url);
|
||||||
} else {
|
} else {
|
||||||
chrome.webNavigation.getFrame({tabId: tab.id, frameId: 0, processId: -1}, function(frame) {
|
chrome.webNavigation.getFrame({
|
||||||
|
tabId: tab.id,
|
||||||
|
frameId: 0,
|
||||||
|
processId: -1
|
||||||
|
}, function (frame) {
|
||||||
frame && callback(frame.url);
|
frame && callback(frame.url);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
78
popup.js
78
popup.js
|
@ -1,3 +1,4 @@
|
||||||
|
/*jshint undef:false*/
|
||||||
var writeStyleTemplate = document.createElement("a");
|
var writeStyleTemplate = document.createElement("a");
|
||||||
writeStyleTemplate.className = "write-style-link";
|
writeStyleTemplate.className = "write-style-link";
|
||||||
|
|
||||||
|
@ -17,7 +18,10 @@ function updatePopUp(url) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
chrome.runtime.sendMessage({method: "getStyles", matchUrl: url}, showStyles);
|
chrome.runtime.sendMessage({
|
||||||
|
method: "getStyles",
|
||||||
|
matchUrl: url
|
||||||
|
}, showStyles);
|
||||||
document.querySelector("#find-styles a").href = "https://userstyles.org/styles/browse/all/" + encodeURIComponent("file" === urlWillWork[1] ? "file:" : url);
|
document.querySelector("#find-styles a").href = "https://userstyles.org/styles/browse/all/" + encodeURIComponent("file" === urlWillWork[1] ? "file:" : url);
|
||||||
|
|
||||||
// Write new style links
|
// Write new style links
|
||||||
|
@ -29,23 +33,29 @@ 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.get("popup.breadcrumbs.usePath")
|
!prefs.get("popup.breadcrumbs.usePath") ? t("writeStyleForURL").replace(/ /g, "\u00a0") : /\/\/[^/]+\/(.*)/.exec(url)[1]
|
||||||
? t("writeStyleForURL").replace(/ /g, "\u00a0")
|
|
||||||
: /\/\/[^/]+\/(.*)/.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.get("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) {
|
||||||
urlLink.addEventListener("focus", function(event) { this.parentNode.classList.add("url()") }, false);
|
this.parentNode.classList.add("url()");
|
||||||
urlLink.addEventListener("mouseleave", function(event) { this.parentNode.classList.remove("url()") }, false);
|
}, false);
|
||||||
urlLink.addEventListener("blur", function(event) { this.parentNode.classList.remove("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("blur", function (event) {
|
||||||
|
this.parentNode.classList.remove("url()");
|
||||||
|
}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For domain
|
// For domain
|
||||||
var domains = getDomains(url)
|
var domains = getDomains(url);
|
||||||
domains.forEach(function(domain) {
|
domains.forEach(function (domain) {
|
||||||
// Don't include TLD
|
// Don't include TLD
|
||||||
if (domains.length > 1 && domain.indexOf(".") == -1) {
|
if (domains.length > 1 && domain.indexOf(".") == -1) {
|
||||||
return;
|
return;
|
||||||
|
@ -59,7 +69,7 @@ function updatePopUp(url) {
|
||||||
});
|
});
|
||||||
|
|
||||||
var writeStyle = document.querySelector("#write-style");
|
var writeStyle = document.querySelector("#write-style");
|
||||||
writeStyleLinks.forEach(function(link, index) {
|
writeStyleLinks.forEach(function (link, index) {
|
||||||
link.addEventListener("click", openLinkInTabOrWindow, false);
|
link.addEventListener("click", openLinkInTabOrWindow, false);
|
||||||
container.appendChild(link);
|
container.appendChild(link);
|
||||||
});
|
});
|
||||||
|
@ -72,14 +82,14 @@ function updatePopUp(url) {
|
||||||
|
|
||||||
function showStyles(styles) {
|
function showStyles(styles) {
|
||||||
var enabledFirst = prefs.get("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);
|
||||||
});
|
});
|
||||||
if (styles.length == 0) {
|
if (styles.length === 0) {
|
||||||
installed.innerHTML = "<div class='entry' id='no-styles'>" + t('noStylesForSite') + "</div>";
|
installed.innerHTML = "<div class='entry' id='no-styles'>" + t('noStylesForSite') + "</div>";
|
||||||
}
|
}
|
||||||
styles.map(createStyleElement).forEach(function(e) {
|
styles.map(createStyleElement).forEach(function (e) {
|
||||||
installed.appendChild(e);
|
installed.appendChild(e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -100,13 +110,24 @@ function createStyleElement(style) {
|
||||||
editLink.setAttribute("href", editLink.getAttribute("href") + style.id);
|
editLink.setAttribute("href", editLink.getAttribute("href") + style.id);
|
||||||
editLink.addEventListener("click", openLinkInTabOrWindow, false);
|
editLink.addEventListener("click", openLinkInTabOrWindow, false);
|
||||||
|
|
||||||
styleName.addEventListener("click", function() { this.checkbox.click(); event.preventDefault(); });
|
styleName.addEventListener("click", function () {
|
||||||
|
this.checkbox.click();
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
// clicking the checkbox will toggle it, and this will run after that happens
|
// clicking the checkbox will toggle it, and this will run after that happens
|
||||||
checkbox.addEventListener("click", function() { enable(event, event.target.checked); }, false);
|
checkbox.addEventListener("click", function () {
|
||||||
e.querySelector(".enable").addEventListener("click", function() { enable(event, true); }, false);
|
enable(event, event.target.checked);
|
||||||
e.querySelector(".disable").addEventListener("click", function() { enable(event, false); }, false);
|
}, false);
|
||||||
|
e.querySelector(".enable").addEventListener("click", function () {
|
||||||
|
enable(event, true);
|
||||||
|
}, false);
|
||||||
|
e.querySelector(".disable").addEventListener("click", function () {
|
||||||
|
enable(event, false);
|
||||||
|
}, false);
|
||||||
|
|
||||||
e.querySelector(".delete").addEventListener("click", function() { doDelete(event, false); }, false);
|
e.querySelector(".delete").addEventListener("click", function () {
|
||||||
|
doDelete(event, false);
|
||||||
|
}, false);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +168,9 @@ function getId(event) {
|
||||||
function openLinkInTabOrWindow(event) {
|
function openLinkInTabOrWindow(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (prefs.get("openEditInWindow", false)) {
|
if (prefs.get("openEditInWindow", false)) {
|
||||||
var options = {url: event.target.href}
|
var options = {
|
||||||
|
url: event.target.href
|
||||||
|
};
|
||||||
var wp = prefs.get("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);
|
||||||
|
@ -159,7 +182,10 @@ function openLinkInTabOrWindow(event) {
|
||||||
|
|
||||||
function openLink(event) {
|
function openLink(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
chrome.runtime.sendMessage({method: "openURL", url: event.target.href});
|
chrome.runtime.sendMessage({
|
||||||
|
method: "openURL",
|
||||||
|
url: event.target.href
|
||||||
|
});
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +194,7 @@ function handleUpdate(style) {
|
||||||
if (styleElement) {
|
if (styleElement) {
|
||||||
installed.replaceChild(createStyleElement(style), styleElement);
|
installed.replaceChild(createStyleElement(style), styleElement);
|
||||||
} else {
|
} else {
|
||||||
getActiveTabRealURL(function(url) {
|
getActiveTabRealURL(function (url) {
|
||||||
if (chrome.extension.getBackgroundPage().getApplicableSections(style, url).length) {
|
if (chrome.extension.getBackgroundPage().getApplicableSections(style, url).length) {
|
||||||
// a new style for the current url is installed
|
// a new style for the current url is installed
|
||||||
document.getElementById("unavailable").style.display = "none";
|
document.getElementById("unavailable").style.display = "none";
|
||||||
|
@ -185,7 +211,7 @@ function handleDelete(id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
|
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
|
||||||
if (request.method == "updatePopup") {
|
if (request.method == "updatePopup") {
|
||||||
switch (request.reason) {
|
switch (request.reason) {
|
||||||
case "styleAdded":
|
case "styleAdded":
|
||||||
|
@ -199,11 +225,11 @@ chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
["find-styles-link", "open-manage-link"].forEach(function(id) {
|
["find-styles-link", "open-manage-link"].forEach(function (id) {
|
||||||
document.getElementById(id).addEventListener("click", openLink, false);
|
document.getElementById(id).addEventListener("click", openLink, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById("disableAll").addEventListener("change", function(event) {
|
document.getElementById("disableAll").addEventListener("change", function (event) {
|
||||||
installed.classList.toggle("disabled", prefs.get("disableAll"));
|
installed.classList.toggle("disabled", prefs.get("disableAll"));
|
||||||
});
|
});
|
||||||
setupLivePrefs(["disableAll"]);
|
setupLivePrefs(["disableAll"]);
|
|
@ -1,31 +1,32 @@
|
||||||
|
/*jshint undef:false*/
|
||||||
var webSqlStorage = {
|
var webSqlStorage = {
|
||||||
|
|
||||||
migrate: function() {
|
migrate: function () {
|
||||||
if (typeof openDatabase == "undefined") {
|
if (typeof openDatabase == "undefined") {
|
||||||
// No WebSQL - no migration!
|
// No WebSQL - no migration!
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
webSqlStorage.getStyles(function(styles) {
|
webSqlStorage.getStyles(function (styles) {
|
||||||
getDatabase(function(db) {
|
getDatabase(function (db) {
|
||||||
var tx = db.transaction(["styles"], "readwrite");
|
var tx = db.transaction(["styles"], "readwrite");
|
||||||
var os = tx.objectStore("styles");
|
var os = tx.objectStore("styles");
|
||||||
styles.forEach(function(s) {
|
styles.forEach(function (s) {
|
||||||
webSqlStorage.cleanStyle(s)
|
webSqlStorage.cleanStyle(s);
|
||||||
os.add(s);
|
os.add(s);
|
||||||
});
|
});
|
||||||
// While this was running, the styles were loaded from the (empty) indexed db
|
// While this was running, the styles were loaded from the (empty) indexed db
|
||||||
setTimeout(function() {
|
setTimeout(function () {
|
||||||
invalidateCache(true);
|
invalidateCache(true);
|
||||||
}, 500);
|
}, 500);
|
||||||
});
|
});
|
||||||
}, null);
|
}, null);
|
||||||
},
|
},
|
||||||
|
|
||||||
cleanStyle: function(s) {
|
cleanStyle: function (s) {
|
||||||
delete s.id;
|
delete s.id;
|
||||||
s.sections.forEach(function(section) {
|
s.sections.forEach(function (section) {
|
||||||
delete section.id;
|
delete section.id;
|
||||||
["urls", "urlPrefixes", "domains", "regexps"].forEach(function(property) {
|
["urls", "urlPrefixes", "domains", "regexps"].forEach(function (property) {
|
||||||
if (!section[property]) {
|
if (!section[property]) {
|
||||||
section[property] = [];
|
section[property] = [];
|
||||||
}
|
}
|
||||||
|
@ -33,8 +34,8 @@ var webSqlStorage = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getStyles: function(callback) {
|
getStyles: function (callback) {
|
||||||
webSqlStorage.getDatabase(function(db) {
|
webSqlStorage.getDatabase(function (db) {
|
||||||
if (!db) {
|
if (!db) {
|
||||||
callback([]);
|
callback([]);
|
||||||
return;
|
return;
|
||||||
|
@ -44,12 +45,13 @@ var webSqlStorage = {
|
||||||
var params = [];
|
var params = [];
|
||||||
|
|
||||||
t.executeSql('SELECT DISTINCT s.*, se.id section_id, se.code, sm.name metaName, sm.value metaValue FROM styles s LEFT JOIN sections se ON se.style_id = s.id LEFT JOIN section_meta sm ON sm.section_id = se.id WHERE 1' + where + ' ORDER BY s.id, se.id, sm.id', params, function (t, r) {
|
t.executeSql('SELECT DISTINCT s.*, se.id section_id, se.code, sm.name metaName, sm.value metaValue FROM styles s LEFT JOIN sections se ON se.style_id = s.id LEFT JOIN section_meta sm ON sm.section_id = se.id WHERE 1' + where + ' ORDER BY s.id, se.id, sm.id', params, function (t, r) {
|
||||||
var styles = [];
|
var styles = [],
|
||||||
var currentStyle = null;
|
currentStyle = null,
|
||||||
var currentSection = null;
|
currentSection = null,
|
||||||
|
metaName;
|
||||||
for (var i = 0; i < r.rows.length; i++) {
|
for (var i = 0; i < r.rows.length; i++) {
|
||||||
var values = r.rows.item(i);
|
var values = r.rows.item(i);
|
||||||
var metaName = null;
|
metaName = null;
|
||||||
switch (values.metaName) {
|
switch (values.metaName) {
|
||||||
case null:
|
case null:
|
||||||
break;
|
break;
|
||||||
|
@ -60,22 +62,34 @@ var webSqlStorage = {
|
||||||
metaName = "urlPrefixes";
|
metaName = "urlPrefixes";
|
||||||
break;
|
break;
|
||||||
case "domain":
|
case "domain":
|
||||||
var metaName = "domains";
|
metaName = "domains";
|
||||||
break;
|
break;
|
||||||
case "regexps":
|
case "regexps":
|
||||||
var metaName = "regexps";
|
metaName = "regexps";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
var metaName = values.metaName + "s";
|
metaName = values.metaName + "s";
|
||||||
}
|
}
|
||||||
var metaValue = values.metaValue;
|
var metaValue = values.metaValue;
|
||||||
if (currentStyle == null || currentStyle.id != values.id) {
|
if (currentStyle === null || currentStyle.id != values.id) {
|
||||||
currentStyle = {id: values.id, url: values.url, updateUrl: values.updateUrl, md5Url: values.md5Url, name: values.name, enabled: values.enabled == "true", originalMd5: values.originalMd5, sections: []};
|
currentStyle = {
|
||||||
|
id: values.id,
|
||||||
|
url: values.url,
|
||||||
|
updateUrl: values.updateUrl,
|
||||||
|
md5Url: values.md5Url,
|
||||||
|
name: values.name,
|
||||||
|
enabled: values.enabled == "true",
|
||||||
|
originalMd5: values.originalMd5,
|
||||||
|
sections: []
|
||||||
|
};
|
||||||
styles.push(currentStyle);
|
styles.push(currentStyle);
|
||||||
}
|
}
|
||||||
if (values.section_id != null) {
|
if (values.section_id !== null) {
|
||||||
if (currentSection == null || currentSection.id != values.section_id) {
|
if (currentSection === null || currentSection.id != values.section_id) {
|
||||||
currentSection = {id: values.section_id, code: values.code};
|
currentSection = {
|
||||||
|
id: values.section_id,
|
||||||
|
code: values.code
|
||||||
|
};
|
||||||
currentStyle.sections.push(currentSection);
|
currentStyle.sections.push(currentSection);
|
||||||
}
|
}
|
||||||
if (metaName && metaValue) {
|
if (metaName && metaValue) {
|
||||||
|
@ -93,14 +107,14 @@ var webSqlStorage = {
|
||||||
}, reportError);
|
}, reportError);
|
||||||
},
|
},
|
||||||
|
|
||||||
getDatabase: function(ready, error) {
|
getDatabase: function (ready, error) {
|
||||||
try {
|
try {
|
||||||
stylishDb = openDatabase('stylish', '', 'Stylish Styles', 5*1024*1024);
|
stylishDb = openDatabase('stylish', '', 'Stylish Styles', 5 * 1024 * 1024);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
error();
|
error();
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
if (stylishDb.version == "") {
|
if (stylishDb.version === "") {
|
||||||
// It didn't already exist, we have nothing to migrate.
|
// It didn't already exist, we have nothing to migrate.
|
||||||
ready(null);
|
ready(null);
|
||||||
return;
|
return;
|
||||||
|
@ -120,15 +134,17 @@ var webSqlStorage = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
dbV11: function(d, error, done) {
|
dbV11: function (d, error, done) {
|
||||||
d.changeVersion(d.version, '1.1', function (t) {
|
d.changeVersion(d.version, '1.1', function (t) {
|
||||||
t.executeSql('CREATE TABLE styles (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, url TEXT, updateUrl TEXT, md5Url TEXT, name TEXT NOT NULL, code TEXT NOT NULL, enabled INTEGER NOT NULL, originalCode TEXT NULL);');
|
t.executeSql('CREATE TABLE styles (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, url TEXT, updateUrl TEXT, md5Url TEXT, name TEXT NOT NULL, code TEXT NOT NULL, enabled INTEGER NOT NULL, originalCode TEXT NULL);');
|
||||||
t.executeSql('CREATE TABLE style_meta (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, style_id INTEGER NOT NULL, name TEXT NOT NULL, value TEXT NOT NULL);');
|
t.executeSql('CREATE TABLE style_meta (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, style_id INTEGER NOT NULL, name TEXT NOT NULL, value TEXT NOT NULL);');
|
||||||
t.executeSql('CREATE INDEX style_meta_style_id ON style_meta (style_id);');
|
t.executeSql('CREATE INDEX style_meta_style_id ON style_meta (style_id);');
|
||||||
}, error, function() { webSqlStorage.dbV12(d, error, done)});
|
}, error, function () {
|
||||||
|
webSqlStorage.dbV12(d, error, done);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
dbV12: function(d, error, done) {
|
dbV12: function (d, error, done) {
|
||||||
d.changeVersion(d.version, '1.2', function (t) {
|
d.changeVersion(d.version, '1.2', function (t) {
|
||||||
// add section table
|
// add section table
|
||||||
t.executeSql('CREATE TABLE sections (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, style_id INTEGER NOT NULL, code TEXT NOT NULL);');
|
t.executeSql('CREATE TABLE sections (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, style_id INTEGER NOT NULL, code TEXT NOT NULL);');
|
||||||
|
@ -144,26 +160,34 @@ var webSqlStorage = {
|
||||||
t.executeSql('INSERT INTO newstyles (id, url, updateUrl, md5Url, name, enabled) SELECT id, url, updateUrl, md5Url, name, enabled FROM styles;');
|
t.executeSql('INSERT INTO newstyles (id, url, updateUrl, md5Url, name, enabled) SELECT id, url, updateUrl, md5Url, name, enabled FROM styles;');
|
||||||
t.executeSql('DROP TABLE styles;');
|
t.executeSql('DROP TABLE styles;');
|
||||||
t.executeSql('ALTER TABLE newstyles RENAME TO styles;');
|
t.executeSql('ALTER TABLE newstyles RENAME TO styles;');
|
||||||
}, error, function() { webSqlStorage.dbV13(d, error, done)});
|
}, error, function () {
|
||||||
|
webSqlStorage.dbV13(d, error, done);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
dbV13: function(d, error, done) {
|
dbV13: function (d, error, done) {
|
||||||
d.changeVersion(d.version, '1.3', function (t) {
|
d.changeVersion(d.version, '1.3', function (t) {
|
||||||
// clear out orphans
|
// clear out orphans
|
||||||
t.executeSql('DELETE FROM section_meta WHERE section_id IN (SELECT sections.id FROM sections LEFT JOIN styles ON styles.id = sections.style_id WHERE styles.id IS NULL);');
|
t.executeSql('DELETE FROM section_meta WHERE section_id IN (SELECT sections.id FROM sections LEFT JOIN styles ON styles.id = sections.style_id WHERE styles.id IS NULL);');
|
||||||
t.executeSql('DELETE FROM sections WHERE id IN (SELECT sections.id FROM sections LEFT JOIN styles ON styles.id = sections.style_id WHERE styles.id IS NULL);');
|
t.executeSql('DELETE FROM sections WHERE id IN (SELECT sections.id FROM sections LEFT JOIN styles ON styles.id = sections.style_id WHERE styles.id IS NULL);');
|
||||||
}, error, function() { webSqlStorage.dbV14(d, error, done)});
|
}, error, function () {
|
||||||
|
webSqlStorage.dbV14(d, error, done);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
dbV14: function(d, error, done) {
|
dbV14: function (d, error, done) {
|
||||||
d.changeVersion(d.version, '1.4', function (t) {
|
d.changeVersion(d.version, '1.4', function (t) {
|
||||||
t.executeSql('UPDATE styles SET url = null WHERE url = "undefined";');
|
t.executeSql('UPDATE styles SET url = null WHERE url = "undefined";');
|
||||||
}, error, function() { webSqlStorage.dbV15(d, error, done)});
|
}, error, function () {
|
||||||
|
webSqlStorage.dbV15(d, error, done);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
dbV15: function(d, error, done) {
|
dbV15: function (d, error, done) {
|
||||||
d.changeVersion(d.version, '1.5', function (t) {
|
d.changeVersion(d.version, '1.5', function (t) {
|
||||||
t.executeSql('ALTER TABLE styles ADD COLUMN originalMd5 TEXT NULL;');
|
t.executeSql('ALTER TABLE styles ADD COLUMN originalMd5 TEXT NULL;');
|
||||||
}, error, function() { done(d); });
|
}, error, function () {
|
||||||
|
done(d);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
267
storage.js
267
storage.js
|
@ -1,37 +1,43 @@
|
||||||
|
/*jshint undef:false*/
|
||||||
function getDatabase(ready, error) {
|
function getDatabase(ready, error) {
|
||||||
var dbOpenRequest = window.indexedDB.open("stylish", 2);
|
var dbOpenRequest = window.indexedDB.open("stylish", 2);
|
||||||
dbOpenRequest.onsuccess = function(e) {
|
dbOpenRequest.onsuccess = function (e) {
|
||||||
ready(e.target.result);
|
ready(e.target.result);
|
||||||
};
|
};
|
||||||
dbOpenRequest.onerror = function(event) {
|
dbOpenRequest.onerror = function (event) {
|
||||||
console.log(event.target.errorCode);
|
console.log(event.target.errorCode);
|
||||||
if (error) {
|
if (error) {
|
||||||
error(event);
|
error(event);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
dbOpenRequest.onupgradeneeded = function(event) {
|
dbOpenRequest.onupgradeneeded = function (event) {
|
||||||
if (event.oldVersion == 0) {
|
if (event.oldVersion === 0) {
|
||||||
var os = event.target.result.createObjectStore("styles", {keyPath: 'id', autoIncrement: true});
|
var os = event.target.result.createObjectStore("styles", {
|
||||||
|
keyPath: 'id',
|
||||||
|
autoIncrement: true
|
||||||
|
});
|
||||||
webSqlStorage.migrate();
|
webSqlStorage.migrate();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
|
var cachedStyles = null,
|
||||||
|
request;
|
||||||
|
|
||||||
var cachedStyles = null;
|
|
||||||
function getStyles(options, callback) {
|
function getStyles(options, callback) {
|
||||||
if (cachedStyles != null) {
|
if (cachedStyles !== null) {
|
||||||
callback(filterStyles(cachedStyles, options));
|
callback(filterStyles(cachedStyles, options));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getDatabase(function(db) {
|
getDatabase(function (db) {
|
||||||
var tx = db.transaction(["styles"], "readonly");
|
var tx = db.transaction(["styles"], "readonly");
|
||||||
var os = tx.objectStore("styles");
|
var os = tx.objectStore("styles");
|
||||||
var all = [];
|
var all = [];
|
||||||
os.openCursor().onsuccess = function(event) {
|
os.openCursor().onsuccess = function (event) {
|
||||||
var cursor = event.target.result;
|
var cursor = event.target.result;
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
var s = cursor.value
|
var s = cursor.value;
|
||||||
s.id = cursor.key
|
s.id = cursor.key;
|
||||||
all.push(cursor.value);
|
all.push(cursor.value);
|
||||||
cursor.continue();
|
cursor.continue();
|
||||||
} else {
|
} else {
|
||||||
|
@ -45,7 +51,9 @@ function getStyles(options, callback) {
|
||||||
function invalidateCache(andNotify) {
|
function invalidateCache(andNotify) {
|
||||||
cachedStyles = null;
|
cachedStyles = null;
|
||||||
if (andNotify) {
|
if (andNotify) {
|
||||||
chrome.runtime.sendMessage({method: "invalidateCache"});
|
chrome.runtime.sendMessage({
|
||||||
|
method: "invalidateCache"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,27 +63,29 @@ function filterStyles(styles, options) {
|
||||||
var id = "id" in options ? Number(options.id) : null;
|
var id = "id" in options ? Number(options.id) : null;
|
||||||
var matchUrl = "matchUrl" in options ? options.matchUrl : null;
|
var matchUrl = "matchUrl" in options ? options.matchUrl : null;
|
||||||
|
|
||||||
if (enabled != null) {
|
if (enabled !== null) {
|
||||||
styles = styles.filter(function(style) {
|
styles = styles.filter(function (style) {
|
||||||
return style.enabled == enabled;
|
return style.enabled == enabled;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (url != null) {
|
if (url !== null) {
|
||||||
styles = styles.filter(function(style) {
|
styles = styles.filter(function (style) {
|
||||||
return style.url == url;
|
return style.url == url;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (id != null) {
|
if (id !== null) {
|
||||||
styles = styles.filter(function(style) {
|
styles = styles.filter(function (style) {
|
||||||
return style.id == id;
|
return style.id == id;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (matchUrl != null) {
|
if (matchUrl !== null) {
|
||||||
// Return as a hash from style to applicable sections? Can only be used with matchUrl.
|
// Return as a hash from style to applicable sections? Can only be used with matchUrl.
|
||||||
var asHash = "asHash" in options ? options.asHash : false;
|
var asHash = "asHash" in options ? options.asHash : false;
|
||||||
if (asHash) {
|
if (asHash) {
|
||||||
var h = {disableAll: prefs.get("disableAll", false)};
|
var h = {
|
||||||
styles.forEach(function(style) {
|
disableAll: prefs.get("disableAll", false)
|
||||||
|
};
|
||||||
|
styles.forEach(function (style) {
|
||||||
var applicableSections = getApplicableSections(style, matchUrl);
|
var applicableSections = getApplicableSections(style, matchUrl);
|
||||||
if (applicableSections.length > 0) {
|
if (applicableSections.length > 0) {
|
||||||
h[style.id] = applicableSections;
|
h[style.id] = applicableSections;
|
||||||
|
@ -83,7 +93,7 @@ function filterStyles(styles, options) {
|
||||||
});
|
});
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
styles = styles.filter(function(style) {
|
styles = styles.filter(function (style) {
|
||||||
var applicableSections = getApplicableSections(style, matchUrl);
|
var applicableSections = getApplicableSections(style, matchUrl);
|
||||||
return applicableSections.length > 0;
|
return applicableSections.length > 0;
|
||||||
});
|
});
|
||||||
|
@ -92,14 +102,14 @@ function filterStyles(styles, options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveStyle(o, callback) {
|
function saveStyle(o, callback) {
|
||||||
getDatabase(function(db) {
|
getDatabase(function (db) {
|
||||||
var tx = db.transaction(["styles"], "readwrite");
|
var tx = db.transaction(["styles"], "readwrite");
|
||||||
var os = tx.objectStore("styles");
|
var os = tx.objectStore("styles");
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
if (o.id) {
|
if (o.id) {
|
||||||
var request = os.get(Number(o.id));
|
request = os.get(Number(o.id));
|
||||||
request.onsuccess = function(event) {
|
request.onsuccess = function (event) {
|
||||||
var style = request.result;
|
var style = request.result;
|
||||||
for (var prop in o) {
|
for (var prop in o) {
|
||||||
if (prop == "id") {
|
if (prop == "id") {
|
||||||
|
@ -108,8 +118,11 @@ function saveStyle(o, callback) {
|
||||||
style[prop] = o[prop];
|
style[prop] = o[prop];
|
||||||
}
|
}
|
||||||
request = os.put(style);
|
request = os.put(style);
|
||||||
request.onsuccess = function(event) {
|
request.onsuccess = function (event) {
|
||||||
notifyAllTabs({method: "styleUpdated", style: style});
|
notifyAllTabs({
|
||||||
|
method: "styleUpdated",
|
||||||
|
style: style
|
||||||
|
});
|
||||||
invalidateCache(true);
|
invalidateCache(true);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(style);
|
callback(style);
|
||||||
|
@ -121,14 +134,14 @@ function saveStyle(o, callback) {
|
||||||
|
|
||||||
// Create
|
// Create
|
||||||
// Set optional things to null if they're undefined
|
// Set optional things to null if they're undefined
|
||||||
["updateUrl", "md5Url", "url", "originalMd5"].filter(function(att) {
|
["updateUrl", "md5Url", "url", "originalMd5"].filter(function (att) {
|
||||||
return !(att in o);
|
return !(att in o);
|
||||||
}).forEach(function(att) {
|
}).forEach(function (att) {
|
||||||
o[att] = null;
|
o[att] = null;
|
||||||
});
|
});
|
||||||
// Set other optional things to empty array if they're undefined
|
// Set other optional things to empty array if they're undefined
|
||||||
o.sections.forEach(function(section) {
|
o.sections.forEach(function (section) {
|
||||||
["urls", "urlPrefixes", "domains", "regexps"].forEach(function(property) {
|
["urls", "urlPrefixes", "domains", "regexps"].forEach(function (property) {
|
||||||
if (!section[property]) {
|
if (!section[property]) {
|
||||||
section[property] = [];
|
section[property] = [];
|
||||||
}
|
}
|
||||||
|
@ -139,13 +152,16 @@ function saveStyle(o, callback) {
|
||||||
o.enabled = true;
|
o.enabled = true;
|
||||||
}
|
}
|
||||||
// Make sure it's not null - that makes indexeddb sad
|
// Make sure it's not null - that makes indexeddb sad
|
||||||
delete o["id"];
|
delete o.id;
|
||||||
var request = os.add(o);
|
request = os.add(o);
|
||||||
request.onsuccess = function(event) {
|
request.onsuccess = function (event) {
|
||||||
invalidateCache(true);
|
invalidateCache(true);
|
||||||
// Give it the ID that was generated
|
// Give it the ID that was generated
|
||||||
o.id = event.target.result;
|
o.id = event.target.result;
|
||||||
notifyAllTabs({method: "styleAdded", style: o});
|
notifyAllTabs({
|
||||||
|
method: "styleAdded",
|
||||||
|
style: o
|
||||||
|
});
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(o);
|
callback(o);
|
||||||
}
|
}
|
||||||
|
@ -154,26 +170,36 @@ function saveStyle(o, callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function enableStyle(id, enabled) {
|
function enableStyle(id, enabled) {
|
||||||
saveStyle({id: id, enabled: enabled}, function(style) {
|
saveStyle({
|
||||||
|
id: id,
|
||||||
|
enabled: enabled
|
||||||
|
}, function (style) {
|
||||||
handleUpdate(style);
|
handleUpdate(style);
|
||||||
notifyAllTabs({method: "styleUpdated", style: style});
|
notifyAllTabs({
|
||||||
|
method: "styleUpdated",
|
||||||
|
style: style
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteStyle(id) {
|
function deleteStyle(id) {
|
||||||
getDatabase(function(db) {
|
getDatabase(function (db) {
|
||||||
var tx = db.transaction(["styles"], "readwrite");
|
var tx = db.transaction(["styles"], "readwrite");
|
||||||
var os = tx.objectStore("styles");
|
var os = tx.objectStore("styles");
|
||||||
var request = os.delete(Number(id));
|
request = os.delete(Number(id));
|
||||||
request.onsuccess = function(event) {
|
request.onsuccess = function (event) {
|
||||||
handleDelete(id);
|
handleDelete(id);
|
||||||
invalidateCache(true);
|
invalidateCache(true);
|
||||||
notifyAllTabs({method: "styleDeleted", id: id});
|
notifyAllTabs({
|
||||||
|
method: "styleDeleted",
|
||||||
|
id: id
|
||||||
|
});
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function reportError() {
|
function reportError() {
|
||||||
|
var i;
|
||||||
for (i in arguments) {
|
for (i in arguments) {
|
||||||
if ("message" in arguments[i]) {
|
if ("message" in arguments[i]) {
|
||||||
//alert(arguments[i].message);
|
//alert(arguments[i].message);
|
||||||
|
@ -190,7 +216,7 @@ function fixBoolean(b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDomains(url) {
|
function getDomains(url) {
|
||||||
if (url.indexOf("file:") == 0) {
|
if (url.indexOf("file:") === 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
var d = /.*?:\/*([^\/:]+)/.exec(url)[1];
|
var d = /.*?:\/*([^\/:]+)/.exec(url)[1];
|
||||||
|
@ -213,8 +239,9 @@ function getType(o) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var namespacePattern = /^\s*(@namespace[^;]+;\s*)+$/;
|
var namespacePattern = /^\s*(@namespace[^;]+;\s*)+$/;
|
||||||
|
|
||||||
function getApplicableSections(style, url) {
|
function getApplicableSections(style, url) {
|
||||||
var sections = style.sections.filter(function(section) {
|
var sections = style.sections.filter(function (section) {
|
||||||
return sectionAppliesToUrl(section, url);
|
return sectionAppliesToUrl(section, url);
|
||||||
});
|
});
|
||||||
// ignore if it's just namespaces
|
// ignore if it's just namespaces
|
||||||
|
@ -226,14 +253,14 @@ function getApplicableSections(style, url) {
|
||||||
|
|
||||||
function sectionAppliesToUrl(section, url) {
|
function sectionAppliesToUrl(section, url) {
|
||||||
// only http, https, file, and chrome-extension allowed
|
// only http, https, file, and chrome-extension allowed
|
||||||
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
|
// other extensions can't be styled
|
||||||
if (url.indexOf("chrome-extension") == 0 && url.indexOf(chrome.extension.getURL("")) != 0) {
|
if (url.indexOf("chrome-extension") === 0 && url.indexOf(chrome.extension.getURL("")) !== 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (section.urls.length == 0 && section.domains.length == 0 && section.urlPrefixes.length == 0 && section.regexps.length == 0) {
|
if (section.urls.length === 0 && section.domains.length === 0 && section.urlPrefixes.length === 0 && section.regexps.length === 0) {
|
||||||
//console.log(section.id + " is global");
|
//console.log(section.id + " is global");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -241,19 +268,19 @@ function sectionAppliesToUrl(section, url) {
|
||||||
//console.log(section.id + " applies to " + url + " due to URL rules");
|
//console.log(section.id + " applies to " + url + " due to URL rules");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (section.urlPrefixes.some(function(prefix) {
|
if (section.urlPrefixes.some(function (prefix) {
|
||||||
return url.indexOf(prefix) == 0;
|
return url.indexOf(prefix) === 0;
|
||||||
})) {
|
})) {
|
||||||
//console.log(section.id + " applies to " + url + " due to URL prefix rules");
|
//console.log(section.id + " applies to " + url + " due to URL prefix rules");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (section.domains.length > 0 && getDomains(url).some(function(domain) {
|
if (section.domains.length > 0 && getDomains(url).some(function (domain) {
|
||||||
return section.domains.indexOf(domain) != -1;
|
return section.domains.indexOf(domain) != -1;
|
||||||
})) {
|
})) {
|
||||||
//console.log(section.id + " applies due to " + url + " due to domain rules");
|
//console.log(section.id + " applies due to " + url + " due to domain rules");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (section.regexps.some(function(regexp) {
|
if (section.regexps.some(function (regexp) {
|
||||||
// we want to match the full url, so add ^ and $ if not already present
|
// we want to match the full url, so add ^ and $ if not already present
|
||||||
if (regexp[0] != "^") {
|
if (regexp[0] != "^") {
|
||||||
regexp = "^" + regexp;
|
regexp = "^" + regexp;
|
||||||
|
@ -261,7 +288,9 @@ function sectionAppliesToUrl(section, url) {
|
||||||
if (regexp[regexp.length - 1] != "$") {
|
if (regexp[regexp.length - 1] != "$") {
|
||||||
regexp += "$";
|
regexp += "$";
|
||||||
}
|
}
|
||||||
var re = runTryCatch(function() { return new RegExp(regexp) });
|
var re = runTryCatch(function () {
|
||||||
|
return new RegExp(regexp);
|
||||||
|
});
|
||||||
if (re) {
|
if (re) {
|
||||||
return (re).test(url);
|
return (re).test(url);
|
||||||
} else {
|
} else {
|
||||||
|
@ -282,29 +311,34 @@ function isCheckbox(el) {
|
||||||
// js engine can't optimize the entire function if it contains try-catch
|
// js engine can't optimize the entire function if it contains try-catch
|
||||||
// so we should keep it isolated from normal code in a minimal wrapper
|
// so we should keep it isolated from normal code in a minimal wrapper
|
||||||
function runTryCatch(func) {
|
function runTryCatch(func) {
|
||||||
try { return func() }
|
try {
|
||||||
catch(e) {}
|
return func();
|
||||||
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accepts an array of pref names (values are fetched via prefs.get)
|
// Accepts an array of pref names (values are fetched via prefs.get)
|
||||||
// and establishes a two-way connection between the document elements and the actual prefs
|
// and establishes a two-way connection between the document elements and the actual prefs
|
||||||
function setupLivePrefs(IDs) {
|
function setupLivePrefs(IDs) {
|
||||||
var localIDs = {};
|
var localIDs = {};
|
||||||
IDs.forEach(function(id) {
|
IDs.forEach(function (id) {
|
||||||
localIDs[id] = true;
|
localIDs[id] = true;
|
||||||
updateElement(id).addEventListener("change", function() {
|
updateElement(id).addEventListener("change", function () {
|
||||||
prefs.set(this.id, isCheckbox(this) ? this.checked : this.value);
|
prefs.set(this.id, isCheckbox(this) ? this.checked : this.value);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
chrome.runtime.onMessage.addListener(function(request) {
|
chrome.runtime.onMessage.addListener(function (request) {
|
||||||
if (request.prefName in localIDs) {
|
if (request.prefName in localIDs) {
|
||||||
updateElement(request.prefName);
|
updateElement(request.prefName);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function updateElement(id) {
|
function updateElement(id) {
|
||||||
var el = document.getElementById(id);
|
var el = document.getElementById(id);
|
||||||
el[isCheckbox(el) ? "checked" : "value"] = prefs.get(id);
|
el[isCheckbox(el) ? "checked" : "value"] = prefs.get(id);
|
||||||
el.dispatchEvent(new Event("change", {bubbles: true, cancelable: true}));
|
el.dispatchEvent(new Event("change", {
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true
|
||||||
|
}));
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -349,9 +383,11 @@ var prefs = chrome.extension.getBackgroundPage().prefs || new function Prefs() {
|
||||||
|
|
||||||
var syncTimeout; // see broadcast() function below
|
var syncTimeout; // see broadcast() function below
|
||||||
|
|
||||||
Object.defineProperty(this, "readOnlyValues", {value: {}});
|
Object.defineProperty(this, "readOnlyValues", {
|
||||||
|
value: {}
|
||||||
|
});
|
||||||
|
|
||||||
Prefs.prototype.get = function(key, defaultValue) {
|
Prefs.prototype.get = function (key, defaultValue) {
|
||||||
if (key in values) {
|
if (key in values) {
|
||||||
return values[key];
|
return values[key];
|
||||||
}
|
}
|
||||||
|
@ -364,11 +400,11 @@ var prefs = chrome.extension.getBackgroundPage().prefs || new function Prefs() {
|
||||||
console.warn("No default preference for '%s'", key);
|
console.warn("No default preference for '%s'", key);
|
||||||
};
|
};
|
||||||
|
|
||||||
Prefs.prototype.getAll = function(key) {
|
Prefs.prototype.getAll = function (key) {
|
||||||
return deepCopy(values);
|
return deepCopy(values);
|
||||||
};
|
};
|
||||||
|
|
||||||
Prefs.prototype.set = function(key, value, options) {
|
Prefs.prototype.set = function (key, value, options) {
|
||||||
var oldValue = deepCopy(values[key]);
|
var oldValue = deepCopy(values[key]);
|
||||||
values[key] = value;
|
values[key] = value;
|
||||||
defineReadonlyProperty(this.readOnlyValues, key, value);
|
defineReadonlyProperty(this.readOnlyValues, key, value);
|
||||||
|
@ -377,32 +413,47 @@ var prefs = chrome.extension.getBackgroundPage().prefs || new function Prefs() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Prefs.prototype.remove = function(key) { me.set(key, undefined) };
|
Prefs.prototype.remove = function (key) {
|
||||||
|
me.set(key, undefined);
|
||||||
|
};
|
||||||
|
|
||||||
Prefs.prototype.broadcast = function(key, value, options) {
|
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.runtime.sendMessage(message);
|
chrome.runtime.sendMessage(message);
|
||||||
if (key == "disableAll") {
|
if (key == "disableAll") {
|
||||||
notifyAllTabs({method: "styleDisableAll", disableAll: value});
|
notifyAllTabs({
|
||||||
|
method: "styleDisableAll",
|
||||||
|
disableAll: value
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (!options || !options.noSync) {
|
if (!options || !options.noSync) {
|
||||||
clearTimeout(syncTimeout);
|
clearTimeout(syncTimeout);
|
||||||
syncTimeout = setTimeout(function() {
|
syncTimeout = setTimeout(function () {
|
||||||
getSync().set({"settings": values});
|
getSync().set({
|
||||||
|
"settings": values
|
||||||
|
});
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.keys(defaults).forEach(function(key) {
|
Object.keys(defaults).forEach(function (key) {
|
||||||
me.set(key, defaults[key], {noBroadcast: true});
|
me.set(key, defaults[key], {
|
||||||
|
noBroadcast: true
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
getSync().get("settings", function(result) {
|
getSync().get("settings", function (result) {
|
||||||
var synced = result.settings;
|
var synced = result.settings;
|
||||||
for (var key in defaults) {
|
for (var key in defaults) {
|
||||||
if (synced && (key in synced)) {
|
if (synced && (key in synced)) {
|
||||||
me.set(key, synced[key], {noSync: true});
|
me.set(key, synced[key], {
|
||||||
|
noSync: true
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
var value = tryMigrating(key);
|
var value = tryMigrating(key);
|
||||||
if (value !== undefined) {
|
if (value !== undefined) {
|
||||||
|
@ -412,18 +463,23 @@ var prefs = chrome.extension.getBackgroundPage().prefs || new function Prefs() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
chrome.storage.onChanged.addListener(function(changes, area) {
|
chrome.storage.onChanged.addListener(function (changes, area) {
|
||||||
if (area == "sync" && "settings" in changes) {
|
if (area == "sync" && "settings" in changes) {
|
||||||
var synced = changes.settings.newValue;
|
var synced = changes.settings.newValue,
|
||||||
|
key;
|
||||||
if (synced) {
|
if (synced) {
|
||||||
for (key in defaults) {
|
for (key in defaults) {
|
||||||
if (key in synced) {
|
if (key in synced) {
|
||||||
me.set(key, synced[key], {noSync: true});
|
me.set(key, synced[key], {
|
||||||
|
noSync: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// user manually deleted our settings, we'll recreate them
|
// user manually deleted our settings, we'll recreate them
|
||||||
getSync().set({"settings": values});
|
getSync().set({
|
||||||
|
"settings": values
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -443,24 +499,30 @@ var prefs = chrome.extension.getBackgroundPage().prefs || new function Prefs() {
|
||||||
case "object":
|
case "object":
|
||||||
try {
|
try {
|
||||||
return JSON.parse(value);
|
return JSON.parse(value);
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
console.log("Cannot migrate from localStorage %s = '%s': %o", key, value, e);
|
console.log("Cannot migrate from localStorage %s = '%s': %o", key, value, e);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
};
|
}();
|
||||||
|
|
||||||
function getCodeMirrorThemes(callback) {
|
function getCodeMirrorThemes(callback) {
|
||||||
chrome.runtime.getPackageDirectoryEntry(function(rootDir) {
|
chrome.runtime.getPackageDirectoryEntry(function (rootDir) {
|
||||||
rootDir.getDirectory("codemirror/theme", {create: false}, function(themeDir) {
|
rootDir.getDirectory("codemirror/theme", {
|
||||||
themeDir.createReader().readEntries(function(entries) {
|
create: false
|
||||||
|
}, function (themeDir) {
|
||||||
|
themeDir.createReader().readEntries(function (entries) {
|
||||||
var themes = [chrome.i18n.getMessage("defaultTheme")];
|
var themes = [chrome.i18n.getMessage("defaultTheme")];
|
||||||
entries
|
entries
|
||||||
.filter(function(entry) { return entry.isFile })
|
.filter(function (entry) {
|
||||||
.sort(function(a, b) { return a.name < b.name ? -1 : 1 })
|
return entry.isFile;
|
||||||
.forEach(function(entry) {
|
})
|
||||||
|
.sort(function (a, b) {
|
||||||
|
return a.name < b.name ? -1 : 1;
|
||||||
|
})
|
||||||
|
.forEach(function (entry) {
|
||||||
themes.push(entry.name.replace(/\.css$/, ""));
|
themes.push(entry.name.replace(/\.css$/, ""));
|
||||||
});
|
});
|
||||||
if (callback) {
|
if (callback) {
|
||||||
|
@ -474,14 +536,24 @@ function getCodeMirrorThemes(callback) {
|
||||||
function sessionStorageHash(name) {
|
function sessionStorageHash(name) {
|
||||||
var hash = {
|
var hash = {
|
||||||
value: {},
|
value: {},
|
||||||
set: function(k, v) { this.value[k] = v; this.updateStorage(); },
|
set: function (k, v) {
|
||||||
unset: function(k) { delete this.value[k]; this.updateStorage(); },
|
this.value[k] = v;
|
||||||
updateStorage: function() {
|
this.updateStorage();
|
||||||
|
},
|
||||||
|
unset: function (k) {
|
||||||
|
delete this.value[k];
|
||||||
|
this.updateStorage();
|
||||||
|
},
|
||||||
|
updateStorage: function () {
|
||||||
sessionStorage[this.name] = JSON.stringify(this.value);
|
sessionStorage[this.name] = JSON.stringify(this.value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
try { hash.value = JSON.parse(sessionStorage[name]); } catch(e) {}
|
try {
|
||||||
Object.defineProperty(hash, "name", {value: name});
|
hash.value = JSON.parse(sessionStorage[name]);
|
||||||
|
} catch (e) {}
|
||||||
|
Object.defineProperty(hash, "name", {
|
||||||
|
value: name
|
||||||
|
});
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,7 +566,7 @@ function deepCopy(obj) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function deepMerge(target, obj1 /* plus any number of object arguments */) {
|
function deepMerge(target, obj1 /* plus any number of object arguments */ ) {
|
||||||
for (var i = 1; i < arguments.length; i++) {
|
for (var i = 1; i < arguments.length; i++) {
|
||||||
var obj = arguments[i];
|
var obj = arguments[i];
|
||||||
for (var k in obj) {
|
for (var k in obj) {
|
||||||
|
@ -512,7 +584,7 @@ function deepMerge(target, obj1 /* plus any number of object arguments */) {
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
function shallowMerge(target, obj1 /* plus any number of object arguments */) {
|
function shallowMerge(target, obj1 /* plus any number of object arguments */ ) {
|
||||||
for (var i = 1; i < arguments.length; i++) {
|
for (var i = 1; i < arguments.length; i++) {
|
||||||
var obj = arguments[i];
|
var obj = arguments[i];
|
||||||
for (var k in obj) {
|
for (var k in obj) {
|
||||||
|
@ -544,7 +616,10 @@ function defineReadonlyProperty(obj, key, value) {
|
||||||
if (typeof copy == "object") {
|
if (typeof copy == "object") {
|
||||||
Object.freeze(copy);
|
Object.freeze(copy);
|
||||||
}
|
}
|
||||||
Object.defineProperty(obj, key, {value: copy, configurable: true})
|
Object.defineProperty(obj, key, {
|
||||||
|
value: copy,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Polyfill, can be removed when Firefox gets this - https://bugzilla.mozilla.org/show_bug.cgi?id=1220494
|
// Polyfill, can be removed when Firefox gets this - https://bugzilla.mozilla.org/show_bug.cgi?id=1220494
|
||||||
|
@ -554,10 +629,10 @@ function getSync() {
|
||||||
}
|
}
|
||||||
crappyStorage = {};
|
crappyStorage = {};
|
||||||
return {
|
return {
|
||||||
get: function(key, callback) {
|
get: function (key, callback) {
|
||||||
callback(crappyStorage[key] || {});
|
callback(crappyStorage[key] || {});
|
||||||
},
|
},
|
||||||
set: function(source, callback) {
|
set: function (source, callback) {
|
||||||
for (var property in source) {
|
for (var property in source) {
|
||||||
if (source.hasOwnProperty(property)) {
|
if (source.hasOwnProperty(property)) {
|
||||||
crappyStorage[property] = source[property];
|
crappyStorage[property] = source[property];
|
||||||
|
@ -565,5 +640,5 @@ function getSync() {
|
||||||
}
|
}
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user