issue 44 Stop using deprecated Chrome APIs
This commit is contained in:
parent
8dbd59b08a
commit
9270dc1596
72
apply.js
72
apply.js
|
@ -1,25 +1,19 @@
|
|||
chrome.extension.sendRequest({name:"getStylesToApply"}, function(response) {
|
||||
chrome.extension.sendMessage({method: "getStyles", matchUrl: location.href, enabled: true, updateBadge: window == window.top}, function(response) {
|
||||
response.forEach(applyStyle);
|
||||
});
|
||||
|
||||
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
|
||||
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
|
||||
switch(request.name) {
|
||||
case "styleDeleted":
|
||||
removeStyle(request.id);
|
||||
sendResponse({});
|
||||
break;
|
||||
case "styleUpdated":
|
||||
removeStyle(request.style.id);
|
||||
//fallthrough
|
||||
case "styleAdded":
|
||||
if (request.style.enabled == "true") {
|
||||
chrome.extension.sendRequest({name: "getStyleApplies", style: request.style, url: location.href}, function(response) {
|
||||
if (response) {
|
||||
applyStyle(response);
|
||||
}
|
||||
});
|
||||
applyStyle(request.style);
|
||||
}
|
||||
sendResponse({});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -31,54 +25,24 @@ function removeStyle(id) {
|
|||
}
|
||||
|
||||
function applyStyle(s) {
|
||||
var style = document.createElement("style");
|
||||
style.setAttribute("id", "stylish-" + s.id);
|
||||
style.setAttribute("class", "stylish");
|
||||
style.setAttribute("type", "text/css");
|
||||
style.appendChild(document.createTextNode(s.sections.filter(filterSection).map(function(section) {
|
||||
return section.code;
|
||||
}).join("\n")));
|
||||
if (document.head) {
|
||||
document.head.appendChild(style);
|
||||
} else {
|
||||
document.documentElement.appendChild(style);
|
||||
}
|
||||
}
|
||||
|
||||
function filterSection(section) {
|
||||
// global
|
||||
if (!section.urls && !section.urlPrefixes && !section.domains && !section.regexps) {
|
||||
return true;
|
||||
}
|
||||
if (section.urls && section.urls.some(function(url) {
|
||||
return url == location.href;
|
||||
})) {
|
||||
return true;
|
||||
}
|
||||
if (section.urlPrefixes && section.urlPrefixes.some(function(urlPrefix) {
|
||||
return location.href.indexOf(urlPrefix) == 0;
|
||||
})) {
|
||||
return true;
|
||||
}
|
||||
if (section.domains) {
|
||||
var currentDomains = getDomains(location.href);
|
||||
if (section.domains.some(function(domain) {
|
||||
return currentDomains.indexOf(domain) >= 0;
|
||||
})) {
|
||||
return true;
|
||||
chrome.extension.sendMessage({method: "getStyleApplies", style: s, url: location.href}, function(response) {
|
||||
if (response && response.length > 0) {
|
||||
applySections(s, response);
|
||||
}
|
||||
}
|
||||
return section.regexps && section.regexps.some(function(regexp) {
|
||||
return (new RegExp(regexp)).test(location.href);
|
||||
});
|
||||
}
|
||||
|
||||
function getDomains(url) {
|
||||
var d = /.*?:\/*([^\/]+)/.exec(url)[1];
|
||||
var domains = [d];
|
||||
while (d.indexOf(".") != -1) {
|
||||
d = d.substring(d.indexOf(".") + 1);
|
||||
domains.push(d);
|
||||
function applySections(style, sections) {
|
||||
var styleElement = document.createElement("style");
|
||||
styleElement.setAttribute("id", "stylish-" + style.id);
|
||||
styleElement.setAttribute("class", "stylish");
|
||||
styleElement.setAttribute("type", "text/css");
|
||||
styleElement.appendChild(document.createTextNode(sections.map(function(section) {
|
||||
return section.code;
|
||||
}).join("\n")));
|
||||
if (document.head) {
|
||||
document.head.appendChild(styleElement);
|
||||
} else {
|
||||
document.documentElement.appendChild(styleElement);
|
||||
}
|
||||
return domains;
|
||||
}
|
||||
|
|
285
background.js
285
background.js
|
@ -1,78 +1,283 @@
|
|||
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
|
||||
switch (request.name) {
|
||||
case "getStylesToApply":
|
||||
getStyles({matchUrl: sender.tab.url, enabled: true}, function(r) {
|
||||
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
|
||||
switch (request.method) {
|
||||
case "getStyles":
|
||||
getStyles(request, function(r) {
|
||||
sendResponse(r);
|
||||
chrome.browserAction.setBadgeText({text: getBadgeText(r), tabId: sender.tab.id});
|
||||
if (request.updateBadge) {
|
||||
var t = getBadgeText(r);
|
||||
console.log("Tab " + sender.tab.id + " (" + sender.tab.url + ") badge text set to '" + t + "'.");
|
||||
chrome.browserAction.setBadgeText({text: t, tabId: sender.tab.id});
|
||||
} else {
|
||||
console.log("Tab " + sender.tab.id + " (" + sender.tab.url + ") doesn't get badge text.");
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "getStylesForUrl":
|
||||
getStyles({url: request.url}, sendResponse);
|
||||
break;
|
||||
return true;
|
||||
case "getStyleApplies":
|
||||
sendResponse(styleAppliesToUrl(request.style, request.url));
|
||||
break;
|
||||
case "saveFromJSON":
|
||||
saveFromJSON(request.json);
|
||||
sendResponse({});
|
||||
break;
|
||||
sendResponse(getApplicableSections(request.style, request.url));
|
||||
return true;
|
||||
case "saveStyle":
|
||||
saveStyle(request, sendResponse);
|
||||
return true;
|
||||
case "styleChanged":
|
||||
cachedGlobalStyleIds = null;
|
||||
cachedStyles = [];
|
||||
sendResponse({});
|
||||
break;
|
||||
case "getCachedStyles":
|
||||
sendResponse(cachedStyles);
|
||||
break;
|
||||
case "cacheStyles":
|
||||
request.styles.forEach(function(style) {
|
||||
cachedStyles[style.id] = style;
|
||||
});
|
||||
cachedStyles = null;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
function styleAppliesToUrl(style, url) {
|
||||
style.sections = style.sections.filter(function(section) {
|
||||
function getStyles(options, callback) {
|
||||
|
||||
var enabled = fixBoolean(options.enabled);
|
||||
var url = "url" in options ? options.url : null;
|
||||
var id = "id" in options ? options.id : null;
|
||||
var matchUrl = "matchUrl" in options ? options.matchUrl : null;
|
||||
|
||||
var callCallback = function() {
|
||||
callback(cachedStyles.filter(function(style) {
|
||||
if (enabled != null && fixBoolean(style.enabled) != enabled) {
|
||||
return false;
|
||||
}
|
||||
if (url != null && style.url != url) {
|
||||
return false;
|
||||
}
|
||||
if (id != null && style.id != id) {
|
||||
return false;
|
||||
}
|
||||
if (matchUrl != null && getApplicableSections(style, matchUrl) == 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
if (cachedStyles) {
|
||||
callCallback();
|
||||
return;
|
||||
}
|
||||
|
||||
getDatabase(function(db) {
|
||||
db.readTransaction(function (t) {
|
||||
var where = "";
|
||||
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) {
|
||||
cachedStyles = [];
|
||||
var currentStyle = null;
|
||||
var currentSection = null;
|
||||
for (var i = 0; i < r.rows.length; i++) {
|
||||
var values = r.rows.item(i);
|
||||
var metaName = null;
|
||||
switch (values.metaName) {
|
||||
case null:
|
||||
break;
|
||||
case "url":
|
||||
metaName = "urls";
|
||||
break;
|
||||
case "url-prefix":
|
||||
metaName = "urlPrefixes";
|
||||
break;
|
||||
case "domain":
|
||||
var metaName = "domains";
|
||||
break;
|
||||
case "regexps":
|
||||
var metaName = "regexps";
|
||||
break;
|
||||
default:
|
||||
var metaName = values.metaName + "s";
|
||||
}
|
||||
var metaValue = values.metaValue;
|
||||
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, sections: []};
|
||||
cachedStyles.push(currentStyle);
|
||||
}
|
||||
if (currentSection == null || currentSection.id != values.section_id) {
|
||||
currentSection = {id: values.section_id, code: values.code};
|
||||
currentStyle.sections.push(currentSection);
|
||||
}
|
||||
if (metaName && metaValue) {
|
||||
if (currentSection[metaName]) {
|
||||
currentSection[metaName].push(metaValue);
|
||||
} else {
|
||||
currentSection[metaName] = [metaValue];
|
||||
}
|
||||
}
|
||||
}
|
||||
callCallback();
|
||||
}, reportError);
|
||||
}, reportError);
|
||||
}, reportError);
|
||||
}
|
||||
|
||||
function fixBoolean(b) {
|
||||
if (typeof b != "undefined") {
|
||||
return b != "false";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const namespacePattern = /^\s*@namespace\s+([a-zA-Z]+\s+)?url\(\"?http:\/\/www.w3.org\/1999\/xhtml\"?\);?\s*$/;
|
||||
function getApplicableSections(style, url) {
|
||||
var sections = style.sections.filter(function(section) {
|
||||
return sectionAppliesToUrl(section, url);
|
||||
});
|
||||
if (style.sections.size == 0) {
|
||||
return null;
|
||||
// ignore if it's just a namespace
|
||||
if (sections.length == 1 && namespacePattern.test(sections[0].code)) {
|
||||
return [];
|
||||
}
|
||||
return style;
|
||||
return sections;
|
||||
}
|
||||
|
||||
function sectionAppliesToUrl(section, url) {
|
||||
// only http and https allowed
|
||||
if (url.indexOf("http") != 0) {
|
||||
return false;
|
||||
}
|
||||
if (!section.urls && !section.domains && !section.urlPrefixes && !section.regexps) {
|
||||
console.log(section + " is global");
|
||||
console.log(section.id + " is global");
|
||||
return true;
|
||||
}
|
||||
if (section.urls && section.urls.indexOf(url) != -1) {
|
||||
console.log(section + " applies to " + url + " due to URL rules");
|
||||
console.log(section.id + " applies to " + url + " due to URL rules");
|
||||
return true;
|
||||
}
|
||||
if (section.urlPrefixes && section.urlPrefixes.some(function(prefix) {
|
||||
return url.indexOf(prefix) == 0;
|
||||
})) {
|
||||
console.log(section + " applies to " + url + " due to URL prefix rules");
|
||||
console.log(section.id + " applies to " + url + " due to URL prefix rules");
|
||||
return true;
|
||||
}
|
||||
if (section.domains && getDomains(url).some(function(domain) {
|
||||
return section.domains.indexOf(domain) != -1;
|
||||
})) {
|
||||
console.log(section + " applies due to " + url + " due to domain rules");
|
||||
console.log(section.id + " applies due to " + url + " due to domain rules");
|
||||
return true;
|
||||
}
|
||||
if (section.regexps && section.regexps.some(function(regexp) {
|
||||
// we want to match the full url, so add ^ and $ if not already present
|
||||
if (regexp[0] != "^") {
|
||||
regexp = "^" + regexp;
|
||||
}
|
||||
if (regexp[regexp.length - 1] != "$") {
|
||||
regexp += "$";
|
||||
}
|
||||
return (new RegExp(regexp)).test(url);
|
||||
})) {
|
||||
console.log(section + " applies to " + url + " due to regexp rules");
|
||||
console.log(section.id + " applies to " + url + " due to regexp rules");
|
||||
return true;
|
||||
}
|
||||
console.log(section + " does not apply due to " + url);
|
||||
console.log(section.id + " does not apply due to " + url);
|
||||
return false;
|
||||
}
|
||||
|
||||
var cachedGlobalStyleIds = null;
|
||||
var cachedStyles = [];
|
||||
var background = true;
|
||||
var cachedStyles = null;
|
||||
|
||||
function saveStyle(o, callback) {
|
||||
getDatabase(function(db) {
|
||||
db.transaction(function(t) {
|
||||
if (o.id) {
|
||||
// update whatever's been passed
|
||||
if ("name" in o) {
|
||||
t.executeSql('UPDATE styles SET name = ? WHERE id = ?;', [o.name, o.id]);
|
||||
}
|
||||
if ("enabled" in o) {
|
||||
t.executeSql('UPDATE styles SET enabled = ? WHERE id = ?;', [o.enabled, o.id]);
|
||||
}
|
||||
if ("url" in o) {
|
||||
t.executeSql('UPDATE styles SET url = ? WHERE id = ?;', [o.url, o.id]);
|
||||
}
|
||||
if ("updateUrl" in o) {
|
||||
t.executeSql('UPDATE styles SET updateUrl = ? WHERE id = ?;', [o.updateUrl, o.id]);
|
||||
}
|
||||
if ("md5Url" in o) {
|
||||
t.executeSql('UPDATE styles SET md5Url = ? WHERE id = ?;', [o.md5Url, o.id]);
|
||||
}
|
||||
} else {
|
||||
// create a new record
|
||||
if (!("updateUrl" in o)) {
|
||||
o.updateUrl = null;
|
||||
}
|
||||
if (!("md5Url" in o)) {
|
||||
o.md5Url = null;
|
||||
}
|
||||
t.executeSql('INSERT INTO styles (name, enabled, url, updateUrl, md5Url) VALUES (?, ?, ?, ?, ?);', [o.name, true, o.url, o.updateUrl, o.md5Url]);
|
||||
}
|
||||
|
||||
if ("sections" in o) {
|
||||
if (o.id) {
|
||||
// clear existing records
|
||||
t.executeSql('DELETE FROM section_meta WHERE section_id IN (SELECT id FROM sections WHERE style_id = ?);', [o.id]);
|
||||
t.executeSql('DELETE FROM sections WHERE style_id = ?;', [o.id]);
|
||||
}
|
||||
|
||||
o.sections.forEach(function(section) {
|
||||
if (o.id) {
|
||||
t.executeSql('INSERT INTO sections (style_id, code) VALUES (?, ?);', [o.id, section.code]);
|
||||
} else {
|
||||
t.executeSql('INSERT INTO sections (style_id, code) SELECT id, ? FROM styles ORDER BY id DESC LIMIT 1;', [section.code]);
|
||||
}
|
||||
if (section.urls) {
|
||||
section.urls.forEach(function(u) {
|
||||
t.executeSql("INSERT INTO section_meta (section_id, name, value) SELECT id, 'url', ? FROM sections ORDER BY id DESC LIMIT 1;", [u]);
|
||||
});
|
||||
}
|
||||
if (section.urlPrefixes) {
|
||||
section.urlPrefixes.forEach(function(u) {
|
||||
t.executeSql("INSERT INTO section_meta (section_id, name, value) SELECT id, 'url-prefix', ? FROM sections ORDER BY id DESC LIMIT 1;", [u]);
|
||||
});
|
||||
}
|
||||
if (section.domains) {
|
||||
section.domains.forEach(function(u) {
|
||||
t.executeSql("INSERT INTO section_meta (section_id, name, value) SELECT id, 'domain', ? FROM sections ORDER BY id DESC LIMIT 1;", [u]);
|
||||
});
|
||||
}
|
||||
if (section.regexps) {
|
||||
section.regexps.forEach(function(u) {
|
||||
t.executeSql("INSERT INTO section_meta (section_id, name, value) SELECT id, 'regexp', ? FROM sections ORDER BY id DESC LIMIT 1;", [u]);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}, reportError, function() {saveFromJSONComplete(o.id, callback)});
|
||||
}, reportError);
|
||||
}
|
||||
|
||||
function saveFromJSONComplete(id, callback) {
|
||||
cachedStyles = null;
|
||||
|
||||
if (id) {
|
||||
getStyles({method: "getStyles", id: id}, function(styles) {
|
||||
saveFromJSONStyleReloaded("styleUpdated", styles[0], callback);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// we need to load the id for new ones
|
||||
getDatabase(function(db) {
|
||||
db.readTransaction(function (t) {
|
||||
t.executeSql('SELECT id FROM styles ORDER BY id DESC LIMIT 1', [], function(t, r) {
|
||||
var id = r.rows.item(0).id;
|
||||
getStyles({method: "getStyles", id: id}, function(styles) {
|
||||
saveFromJSONStyleReloaded("styleAdded", styles[0], callback);
|
||||
});
|
||||
}, reportError)
|
||||
}, reportError)
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function saveFromJSONStyleReloaded(updateType, style, callback) {
|
||||
notifyAllTabs({name:updateType, style: style});
|
||||
if (callback) {
|
||||
callback(style);
|
||||
}
|
||||
}
|
||||
|
||||
function getDomains(url) {
|
||||
var d = /.*?:\/*([^\/]+)/.exec(url)[1];
|
||||
var domains = [d];
|
||||
while (d.indexOf(".") != -1) {
|
||||
d = d.substring(d.indexOf(".") + 1);
|
||||
domains.push(d);
|
||||
}
|
||||
return domains;
|
||||
}
|
||||
|
||||
|
|
21
edit.html
21
edit.html
|
@ -35,11 +35,6 @@
|
|||
#sections > div:not(:first-child) {
|
||||
border-top: 2px solid black;
|
||||
}
|
||||
span {
|
||||
cursor: pointer;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
width: 10em;
|
||||
|
@ -86,23 +81,21 @@
|
|||
}
|
||||
</style>
|
||||
<script src="localization.js"></script>
|
||||
<script src="storage.js"></script>
|
||||
<script src="messaging.js"></script>
|
||||
<script src="edit.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="header">
|
||||
<h1 id="heading"></h1>
|
||||
<section id="basic-info">
|
||||
<div><label for="name"><script>o("styleNameLabel")</script></label><input id="name" onchange="makeDirty()"><div>
|
||||
<div><label for="enabled"><script>o("styleEnabledLabel")</script></label><input type="checkbox" id="enabled" onchange="makeDirty()"></div>
|
||||
<div><label for="name" id="name-label"></label><input id="name"><div>
|
||||
<div><label for="enabled" id="enabled-label"></label><input type="checkbox" id="enabled"></div>
|
||||
</section>
|
||||
<button onclick="showMozillaFormat()"><script>o("styleToMozillaFormat")</script></button><img id="to-mozilla-help" src="help.png" onclick="showToMozillaHelp()"><br><br>
|
||||
<button onclick="save()"><script>o("styleSaveLabel")</script></button>
|
||||
<a href="manage.html"><button><script>o("styleCancelEditLabel")</script></button></a>
|
||||
<button id="to-mozilla"></button><img id="to-mozilla-help" src="help.png"><br><br>
|
||||
<button id="save-button"></button>
|
||||
<a href="manage.html"><button id="cancel-button"></button></a>
|
||||
</div>
|
||||
<section id="sections">
|
||||
<h2><script>o("styleSectionsTitle")</script> <img id="sections-help" src="help.png" onclick="showSectionHelp()"></h2>
|
||||
<h2><span id="sections-heading"></span> <img id="sections-help" src="help.png"></h2>
|
||||
</section>
|
||||
<script src="edit.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
138
edit.js
138
edit.js
|
@ -2,14 +2,14 @@ var styleId = null;
|
|||
var dirty = false;
|
||||
|
||||
var appliesToTemplate = document.createElement("li");
|
||||
appliesToTemplate.innerHTML = '<select name="applies-type" onchange="makeDirty()"><option value="url">' + t("appliesUrlOption") + '</option><option value="url-prefix">' + t("appliesUrlPrefixOption") + '</option><option value="domain">' + t("appliesDomainOption") + '</option><option value="regexp">' + t("appliesRegexpOption") + '</option></select><input name="applies-value" onchange="makeDirty()"><button onclick="removeAppliesTo(event)" class="remove-applies-to">' + t("appliesRemove") + '</button><button class="add-applies-to" onclick="addAppliesTo(this.parentNode.parentNode)">' + t("appliesAdd") + '</button>';
|
||||
appliesToTemplate.innerHTML = '<select name="applies-type" class="applies-type"><option value="url">' + t("appliesUrlOption") + '</option><option value="url-prefix">' + t("appliesUrlPrefixOption") + '</option><option value="domain">' + t("appliesDomainOption") + '</option><option value="regexp">' + t("appliesRegexpOption") + '</option></select><input name="applies-value" class="applies-value"><button class="remove-applies-to">' + t("appliesRemove") + '</button><button class="add-applies-to">' + t("appliesAdd") + '</button>';
|
||||
|
||||
var appliesToEverythingTemplate = document.createElement("li");
|
||||
appliesToEverythingTemplate.className = "applies-to-everything";
|
||||
appliesToEverythingTemplate.innerHTML = t("appliesToEverything") + ' <button class="add-applies-to" onclick="addAppliesTo(this.parentNode.parentNode)">' + t("appliesSpecify") + '</button>'
|
||||
appliesToEverythingTemplate.innerHTML = t("appliesToEverything") + ' <button class="add-applies-to">' + t("appliesSpecify") + '</button>'
|
||||
|
||||
var sectionTemplate = document.createElement("div");
|
||||
sectionTemplate.innerHTML = '<label>' + t('sectionCode') + '</label><textarea class="code" onchange="makeDirty()"></textarea><br><div class="applies-to"><label>' + t("appliesLabel") + ' <img src="help.png" onclick="showAppliesToHelp()" alt="' + t('helpAlt') + '"></label><ul class="applies-to-list"></ul></div><button class="remove-section" onclick="removeSection(event)">' + t('sectionRemove') + '</button><button class="add-section" onclick="addSection()">' + t('sectionAdd') + '</button>';
|
||||
sectionTemplate.innerHTML = '<label>' + t('sectionCode') + '</label><textarea class="code"></textarea><br><div class="applies-to"><label>' + t("appliesLabel") + ' <img class="applies-to-help" src="help.png" alt="' + t('helpAlt') + '"></label><ul class="applies-to-list"></ul></div><button class="remove-section">' + t('sectionRemove') + '</button><button class="add-section">' + t('sectionAdd') + '</button>';
|
||||
|
||||
function makeDirty() {
|
||||
dirty = true;
|
||||
|
@ -30,23 +30,36 @@ function addAppliesTo(list, name, value) {
|
|||
e = appliesToTemplate.cloneNode(true);
|
||||
e.querySelector("[name=applies-type]").value = name;
|
||||
e.querySelector("[name=applies-value]").value = value;
|
||||
e.querySelector(".remove-applies-to").addEventListener("click", removeAppliesTo, false);
|
||||
e.querySelector(".applies-value").addEventListener("change", makeDirty, false);
|
||||
e.querySelector(".applies-type").addEventListener("change", makeDirty, false);
|
||||
} else if (showingEverything || list.hasChildNodes()) {
|
||||
e = appliesToTemplate.cloneNode(true);
|
||||
if (list.hasChildNodes()) {
|
||||
e.querySelector("[name=applies-type]").value = list.querySelector("li:last-child [name='applies-type']").value;
|
||||
}
|
||||
e.querySelector(".remove-applies-to").addEventListener("click", removeAppliesTo, false);
|
||||
e.querySelector(".applies-value").addEventListener("change", makeDirty, false);
|
||||
e.querySelector(".applies-type").addEventListener("change", makeDirty, false);
|
||||
} else {
|
||||
e = appliesToEverythingTemplate.cloneNode(true);
|
||||
}
|
||||
e.querySelector(".add-applies-to").addEventListener("click", function() {addAppliesTo(this.parentNode.parentNode)}, false);
|
||||
list.appendChild(e);
|
||||
}
|
||||
|
||||
function addSection(section) {
|
||||
var div = sectionTemplate.cloneNode(true);
|
||||
div.querySelector(".applies-to-help").addEventListener("click", showAppliesToHelp, false);
|
||||
div.querySelector(".remove-section").addEventListener("click", removeSection, false);
|
||||
div.querySelector(".add-section").addEventListener("click", function() {addSection()}, false);
|
||||
|
||||
var appliesTo = div.querySelector(".applies-to-list");
|
||||
|
||||
if (section) {
|
||||
div.querySelector(".code").value = section.code;
|
||||
var codeElement = div.querySelector(".code");
|
||||
codeElement.value = section.code;
|
||||
codeElement.addEventListener("change", makeDirty, false);
|
||||
if (section.urls) {
|
||||
section.urls.forEach(function(url) {
|
||||
addAppliesTo(appliesTo, "url", url);
|
||||
|
@ -82,7 +95,9 @@ function removeAppliesTo(event) {
|
|||
var appliesToList = event.target.parentNode.parentNode;
|
||||
appliesToList.removeChild(event.target.parentNode);
|
||||
if (!appliesToList.hasChildNodes()) {
|
||||
appliesToList.appendChild(appliesToEverythingTemplate);
|
||||
var e = appliesToEverythingTemplate.cloneNode(true);
|
||||
e.querySelector(".add-applies-to").addEventListener("click", function() {addAppliesTo(this.parentNode.parentNode)}, false);
|
||||
appliesToList.appendChild(e);
|
||||
}
|
||||
makeDirty();
|
||||
}
|
||||
|
@ -106,7 +121,7 @@ function init() {
|
|||
}
|
||||
// This is an edit
|
||||
var id = idMatch[1];
|
||||
getStyles({id: id}, function(styles) {
|
||||
chrome.extension.sendMessage({method: "getStyles", id: id}, function(styles) {
|
||||
var style = styles[0];
|
||||
styleId = style.id;
|
||||
initWithStyle(style);
|
||||
|
@ -117,7 +132,7 @@ function initWithStyle(style) {
|
|||
document.getElementById("name").value = style.name;
|
||||
document.getElementById("enabled").checked = style.enabled == "true";
|
||||
document.getElementById("heading").innerHTML = t("editStyleHeading");
|
||||
initTitle(style);
|
||||
initTitle(style.name);
|
||||
// if this was done in response to an update, we need to clear existing sections
|
||||
Array.prototype.forEach.call(document.querySelectorAll("#sections > div"), function(div) {
|
||||
div.parentNode.removeChild(div);
|
||||
|
@ -125,8 +140,8 @@ function initWithStyle(style) {
|
|||
style.sections.forEach(addSection);
|
||||
}
|
||||
|
||||
function initTitle(style) {
|
||||
document.title = t('editStyleTitle', [style.name]);
|
||||
function initTitle(name) {
|
||||
document.title = t('editStyleTitle', [name]);
|
||||
}
|
||||
|
||||
function validate() {
|
||||
|
@ -145,31 +160,14 @@ function save() {
|
|||
}
|
||||
var name = document.getElementById("name").value;
|
||||
var enabled = document.getElementById("enabled").checked;
|
||||
getDatabase(function(db) {
|
||||
db.transaction(function (t) {
|
||||
var sections = getSections();
|
||||
if (styleId == null) {
|
||||
t.executeSql('INSERT INTO styles (name, enabled) VALUES (?, ?);', [name, enabled]);
|
||||
sections.forEach(function(s) {
|
||||
t.executeSql("INSERT INTO sections (style_id, code) SELECT id, ? FROM styles ORDER BY id DESC LIMIT 1;", [s.code]);
|
||||
s.meta.forEach(function(m) {
|
||||
t.executeSql("INSERT INTO section_meta (section_id, name, value) SELECT id, ?, ? FROM sections ORDER BY id DESC LIMIT 1;", [m[0], m[1]]);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
t.executeSql('UPDATE styles SET name = ?, enabled = ? WHERE id = ?;', [name, enabled, styleId]);
|
||||
t.executeSql('DELETE FROM section_meta WHERE section_id IN (SELECT id FROM sections WHERE style_id = ?);', [styleId]);
|
||||
t.executeSql('DELETE FROM sections WHERE style_id = ?;', [styleId]);
|
||||
sections.forEach(function(s) {
|
||||
t.executeSql("INSERT INTO sections (style_id, code) VALUES (?, ?);", [styleId, s.code]);
|
||||
s.meta.forEach(function(m) {
|
||||
t.executeSql("INSERT INTO section_meta (section_id, name, value) SELECT id, ?, ? FROM sections ORDER BY id DESC LIMIT 1;", [m[0], m[1]]);
|
||||
});
|
||||
});
|
||||
}
|
||||
dirty = false;
|
||||
}, reportError, saveComplete);
|
||||
}, reportError);
|
||||
var request = {
|
||||
method: "saveStyle",
|
||||
id: styleId,
|
||||
name: name,
|
||||
enabled: enabled,
|
||||
sections: getSections(),
|
||||
};
|
||||
chrome.extension.sendMessage(request, saveComplete);
|
||||
}
|
||||
|
||||
function getSections() {
|
||||
|
@ -179,13 +177,15 @@ function getSections() {
|
|||
if (/^\s*$/.test(code)) {
|
||||
return;
|
||||
}
|
||||
sections.push({code: code, meta: getMeta(div)});
|
||||
var meta = getMeta(div);
|
||||
meta.code = code;
|
||||
sections.push(meta);
|
||||
});
|
||||
return sections;
|
||||
}
|
||||
|
||||
function getMeta(e) {
|
||||
var meta = [];
|
||||
var meta = {urls: [], urlPrefixes: [], domains: [], regexps: []};
|
||||
Array.prototype.forEach.call(e.querySelector(".applies-to-list").childNodes, function(li) {
|
||||
if (li.className == appliesToEverythingTemplate.className) {
|
||||
return;
|
||||
|
@ -193,26 +193,33 @@ function getMeta(e) {
|
|||
var a = li.querySelector("[name=applies-type]").value;
|
||||
var b = li.querySelector("[name=applies-value]").value;
|
||||
if (a && b) {
|
||||
meta.push([a, b]);
|
||||
switch (a) {
|
||||
case "url":
|
||||
meta.urls.push(b);
|
||||
break;
|
||||
case "url-prefix":
|
||||
meta.urlPrefixes.push(b);
|
||||
break;
|
||||
case "domain":
|
||||
meta.domains.push(b);
|
||||
break;
|
||||
case "regexp":
|
||||
meta.regexps.push(b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
return meta;
|
||||
}
|
||||
|
||||
function saveComplete() {
|
||||
if (styleId == null) {
|
||||
// Load the style id
|
||||
getDatabase(function(db) {
|
||||
db.readTransaction(function (t) {
|
||||
t.executeSql('SELECT id FROM styles ORDER BY id DESC LIMIT 1', [], function(t, r) {
|
||||
styleId = r.rows.item(0).id;
|
||||
notifySave(true);
|
||||
}, reportError)
|
||||
}, reportError)
|
||||
});
|
||||
return;
|
||||
function saveComplete(id) {
|
||||
// Go from new style URL to edit style URL
|
||||
if (location.href.indexOf("id=") == -1) {
|
||||
// give the code above a moment before we kill the page
|
||||
setTimeout(function() {location.href = "edit.html?id=" + id;}, 200);
|
||||
} else {
|
||||
initTitle(document.getElementById("name").value);
|
||||
}
|
||||
notifySave(false);
|
||||
}
|
||||
|
||||
function showMozillaFormat() {
|
||||
|
@ -233,20 +240,6 @@ function toMozillaFormat() {
|
|||
}).join("\n\n");
|
||||
}
|
||||
|
||||
function notifySave(newStyle) {
|
||||
chrome.extension.sendRequest({name: "styleChanged"});
|
||||
getStyles({id: styleId}, function(styles) {
|
||||
if (newStyle) {
|
||||
notifyAllTabs({name:"styleAdded", style: styles[0]});
|
||||
// give the code above a moment before we kill the page
|
||||
setTimeout(function() {location.href = "edit.html?id=" + styleId;}, 200);
|
||||
} else {
|
||||
initTitle(styles[0]);
|
||||
notifyAllTabs({name:"styleUpdated", style: styles[0]});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function showSectionHelp() {
|
||||
showHelp(t("sectionHelp"));
|
||||
}
|
||||
|
@ -263,11 +256,12 @@ function showHelp(text) {
|
|||
alert(text);
|
||||
}
|
||||
|
||||
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
|
||||
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
|
||||
var installed = document.getElementById("installed");
|
||||
switch(request.name) {
|
||||
case "styleUpdated":
|
||||
initWithStyle(request.style);
|
||||
dirty = false;
|
||||
break;
|
||||
case "styleDeleted":
|
||||
if (styleId == request.id) {
|
||||
|
@ -276,3 +270,17 @@ chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
tE("name-label", "styleNameLabel");
|
||||
tE("enabled-label", "styleEnabledLabel");
|
||||
tE("to-mozilla", "styleToMozillaFormat");
|
||||
tE("save-button", "styleSaveLabel");
|
||||
tE("cancel-button", "styleCancelEditLabel");
|
||||
tE("sections-heading", "styleSectionsTitle");
|
||||
document.getElementById("name").addEventListener("change", makeDirty, false);
|
||||
document.getElementById("enabled").addEventListener("change", makeDirty, false);
|
||||
document.getElementById("to-mozilla").addEventListener("click", showMozillaFormat, false);
|
||||
document.getElementById("to-mozilla-help").addEventListener("click", showToMozillaHelp, false);
|
||||
document.getElementById("save-button").addEventListener("click", save, false);
|
||||
document.getElementById("sections-help").addEventListener("click", showSectionHelp, false);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
chrome.extension.sendRequest({name:"getStylesForUrl", url: getMeta("stylish-id-url") || location.href}, function(response) {
|
||||
chrome.extension.sendMessage({method: "getStyles", url: getMeta("stylish-id-url") || location.href}, function(response) {
|
||||
if (response.length == 0) {
|
||||
sendEvent("styleCanBeInstalledChrome");
|
||||
} else {
|
||||
|
@ -18,7 +18,8 @@ document.addEventListener("stylishInstallChrome", function() {
|
|||
getResource(getMeta("stylish-code-chrome"), function(code) {
|
||||
// check for old style json
|
||||
var json = JSON.parse(code);
|
||||
chrome.extension.sendRequest({name:"saveFromJSON", json: json}, function(response) {
|
||||
json.method = "saveStyle";
|
||||
chrome.extension.sendMessage(json, function(response) {
|
||||
sendEvent("styleInstalledChrome");
|
||||
});
|
||||
});
|
||||
|
|
12
manage.html
12
manage.html
|
@ -87,16 +87,18 @@
|
|||
<script src="localization.js"></script>
|
||||
<script src="storage.js"></script>
|
||||
<script src="messaging.js"></script>
|
||||
<script src="manage.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="header">
|
||||
<img src="128.png">
|
||||
<h1><script>o("manageHeading")</script></h1>
|
||||
<p><script>o("manageText")</script></p>
|
||||
<p><button onclick="checkUpdateAll()"><script>o("checkAllUpdates")</script></button></p>
|
||||
<p><a href="edit.html"><button><script>o("addStyleLabel")</script></button></a></p>
|
||||
<h1 id="manage-heading"></h1>
|
||||
<p id="manage-text"></p>
|
||||
<p><button id="check-all-updates"></button></p>
|
||||
<p><a href="edit.html"><button id="add-style-label"></button></a></p>
|
||||
</div>
|
||||
<div id="installed"></div>
|
||||
|
||||
<script src="manage.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
30
manage.js
30
manage.js
|
@ -1,12 +1,11 @@
|
|||
|
||||
var styleTemplate = document.createElement("div");
|
||||
styleTemplate.innerHTML = "<h2 class='style-name'></h2><p class='applies-to'></p><p class='actions'><a class='style-edit-link' href='edit.html?id='><button>" + t('editStyleLabel') + "</button></a><button class='enable' onclick='enable(event, true)'>" + t('enableStyleLabel') + "</button><button class='disable' onclick='enable(event, false)'>" + t('disableStyleLabel') + "</button><button class='delete' onclick='doDelete(event)'>" + t('deleteStyleLabel') + "</button><button class='check-update' onclick='doCheckUpdate(event)'>" + t('checkForUpdate') + "</button><button class='update' onclick='doUpdate(event)'>" + t('installUpdate') + "</button><span class='update-note'></span></p>";
|
||||
styleTemplate.innerHTML = "<h2 class='style-name'></h2><p class='applies-to'></p><p class='actions'><a class='style-edit-link' href='edit.html?id='><button>" + t('editStyleLabel') + "</button></a><button class='enable'>" + t('enableStyleLabel') + "</button><button class='disable'>" + t('disableStyleLabel') + "</button><button class='delete'>" + t('deleteStyleLabel') + "</button><button class='check-update'>" + t('checkForUpdate') + "</button><button class='update'>" + t('installUpdate') + "</button><span class='update-note'></span></p>";
|
||||
|
||||
var appliesToExtraTemplate = document.createElement("span");
|
||||
appliesToExtraTemplate.className = "applies-to-extra";
|
||||
appliesToExtraTemplate.innerHTML = t('appliesDisplayTruncatedSuffix');
|
||||
appliesToExtraTemplate.innerHTML = " " + t('appliesDisplayTruncatedSuffix');
|
||||
|
||||
getStyles({}, showStyles);
|
||||
chrome.extension.sendMessage({method: "getStyles"}, showStyles);
|
||||
|
||||
function showStyles(styles) {
|
||||
var installed = document.getElementById("installed");
|
||||
|
@ -80,6 +79,11 @@ function createStyleElement(style) {
|
|||
}
|
||||
var editLink = e.querySelector(".style-edit-link");
|
||||
editLink.setAttribute("href", editLink.getAttribute("href") + style.id);
|
||||
e.querySelector(".enable").addEventListener("click", function(event) { 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(".update").addEventListener("click", doUpdate, false);
|
||||
e.querySelector(".delete").addEventListener("click", doDelete, false);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
@ -111,19 +115,16 @@ function getStyleElement(event) {
|
|||
return null;
|
||||
}
|
||||
|
||||
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
|
||||
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
|
||||
switch(request.name) {
|
||||
case "styleUpdated":
|
||||
handleUpdate(request.style);
|
||||
sendResponse({});
|
||||
break;
|
||||
case "styleAdded":
|
||||
installed.appendChild(createStyleElement(request.style));
|
||||
sendResponse({});
|
||||
break;
|
||||
case "styleDeleted":
|
||||
handleDelete(request.id);
|
||||
sendResponse({});
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
@ -168,7 +169,7 @@ function checkUpdate(element) {
|
|||
}
|
||||
|
||||
function checkNeedsUpdate(id, serverJson) {
|
||||
getStyles({id: id}, function(styles) {
|
||||
chrome.extension.sendMessage({method: "getStyles", id: id}, function(styles) {
|
||||
var style = styles[0];
|
||||
if (codeIsEqual(style.sections, serverJson.sections)) {
|
||||
handleNeedsUpdate("no", id, serverJson);
|
||||
|
@ -199,10 +200,7 @@ function handleNeedsUpdate(needsUpdate, id, serverJson) {
|
|||
|
||||
function doUpdate(event) {
|
||||
var element = getStyleElement(event);
|
||||
var o = {};
|
||||
o.id = element.getAttribute('style-id');
|
||||
o.sections = element.updatedCode.sections;
|
||||
saveFromJSON(o, function() {
|
||||
chrome.extension.sendMessage({method: "saveStyle", id: element.getAttribute('style-id'), sections: element.updatedCode.sections}, function() {
|
||||
element.updatedCode = "";
|
||||
element.className = element.className.replace("can-update", "update-done");
|
||||
element.querySelector(".update-note").innerHTML = t('updateCompleted');
|
||||
|
@ -279,3 +277,9 @@ function getType(o) {
|
|||
}
|
||||
|
||||
document.title = t("manageTitle");
|
||||
tE("manage-heading", "manageHeading");
|
||||
tE("manage-text", "manageText", null, false);
|
||||
tE("check-all-updates", "checkAllUpdates");
|
||||
tE("add-style-label", "addStyleLabel");
|
||||
|
||||
document.getElementById("check-all-updates").addEventListener("click", checkUpdateAll, false);
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
{
|
||||
"name": "Stylish",
|
||||
"version": "0.10",
|
||||
"version": "1.0",
|
||||
"description": "__MSG_description__",
|
||||
"homepage_url": "http://userstyles.org",
|
||||
"manifest_version": 2,
|
||||
"icons": {
|
||||
"16": "16.png",
|
||||
"48": "48.png",
|
||||
|
@ -9,10 +11,11 @@
|
|||
},
|
||||
"permissions": [
|
||||
"tabs",
|
||||
"http://userstyles.org/",
|
||||
"http://userstyles.local/"
|
||||
"http://userstyles.org/"
|
||||
],
|
||||
"background_page": "background.html",
|
||||
"background": {
|
||||
"page": "background.html"
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["http://*/*", "https://*/*"],
|
||||
|
@ -21,7 +24,7 @@
|
|||
"js": ["apply.js"]
|
||||
},
|
||||
{
|
||||
"matches": ["http://userstyles.org/*", "http://userstyles.local/*"],
|
||||
"matches": ["http://userstyles.org/*"],
|
||||
"run_at": "document_end",
|
||||
"all_frames": false,
|
||||
"js": ["install.js"]
|
||||
|
|
11
messaging.js
11
messaging.js
|
@ -2,7 +2,7 @@ function notifyAllTabs(request) {
|
|||
chrome.windows.getAll({populate: true}, function(windows) {
|
||||
windows.forEach(function(win) {
|
||||
win.tabs.forEach(function(tab) {
|
||||
chrome.tabs.sendRequest(tab.id, request);
|
||||
chrome.tabs.sendMessage(tab.id, request);
|
||||
updateBadgeText(tab);
|
||||
});
|
||||
});
|
||||
|
@ -10,12 +10,13 @@ function notifyAllTabs(request) {
|
|||
}
|
||||
|
||||
function updateBadgeText(tab) {
|
||||
getStyles({matchUrl: tab.url}, function(styles) {
|
||||
chrome.browserAction.setBadgeText({text: getBadgeText(styles), tabId: tab.id});
|
||||
chrome.extension.sendMessage({method: "getStyles", matchUrl: tab.url, enabled: true}, function(styles) {
|
||||
var t = getBadgeText(styles);
|
||||
console.log("Tab " + tab.id + " (" + tab.url + ") badge text set to '" + t + "'.");
|
||||
chrome.browserAction.setBadgeText({text: t, tabId: tab.id});
|
||||
});
|
||||
}
|
||||
|
||||
function getBadgeText(styles) {
|
||||
var e = styles.filter(function(style) { return style.enabled == "true"; });
|
||||
return e.length == 0 ? "" : ("" + e.length);
|
||||
return styles.length == 0 ? "" : ("" + styles.length);
|
||||
}
|
||||
|
|
160
popup.html
160
popup.html
|
@ -1,117 +1,55 @@
|
|||
<style>
|
||||
body {
|
||||
width: 200px;
|
||||
}
|
||||
#no-styles {
|
||||
font-style: italic;
|
||||
}
|
||||
.disabled {
|
||||
color: #BBB;
|
||||
}
|
||||
.disabled .disable {
|
||||
display: none;
|
||||
}
|
||||
.enabled .enable {
|
||||
display: none;
|
||||
}
|
||||
.style-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
.actions {
|
||||
font-size: x-small;
|
||||
}
|
||||
a, a:visited {
|
||||
color: black;
|
||||
}
|
||||
.entry {
|
||||
padding-bottom: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
#find-styles, #manage-styles {
|
||||
font-size: smaller;
|
||||
}
|
||||
#find-styles {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src="localization.js"></script>
|
||||
<script src="storage.js"></script>
|
||||
<script src="messaging.js"></script>
|
||||
|
||||
<script>
|
||||
var styleTemplate = document.createElement("div");
|
||||
styleTemplate.innerHTML = "<div class='style-name'></div><div class='actions'><a class='style-edit-link' href='edit.html?id=' onclick='return openLink(event);'>" + t('editStyleLabel') + "</a> <a href='#' class='enable' onclick='enable(event, true);return false;'>" + t('enableStyleLabel') + "</a> <a href='#' class='disable' onclick='enable(event, false);return false;'>" + t('disableStyleLabel') + "</a> <a href='#' class='delete' onclick='doDelete(event);return false;'>" + t('deleteStyleLabel') + "</a></div>";
|
||||
|
||||
chrome.tabs.getSelected(null, function(tab) {
|
||||
//alert('here');
|
||||
getStyles({matchUrl: tab.url}, showStyles);
|
||||
document.querySelector("#find-styles a").href = "http://userstyles.org/styles/browse/all/" + encodeURIComponent(tab.url);
|
||||
});
|
||||
|
||||
function showStyles(styles) {
|
||||
var installed = document.getElementById("installed");
|
||||
if (styles.length == 0) {
|
||||
installed.innerHTML = "<div class='entry' id='no-styles'>" + t('noStylesForSite') + "</div>";
|
||||
}
|
||||
styles.map(createStyleElement).forEach(function(e) {
|
||||
installed.appendChild(e);
|
||||
});
|
||||
}
|
||||
|
||||
function createStyleElement(style) {
|
||||
var e = styleTemplate.cloneNode(true);
|
||||
e.setAttribute("class", "entry " + (style.enabled == "true" ? "enabled" : "disabled"));
|
||||
e.setAttribute("style-id", style.id);
|
||||
var styleName = e.querySelector(".style-name");
|
||||
styleName.appendChild(document.createTextNode(style.name));
|
||||
var editLink = e.querySelector(".style-edit-link");
|
||||
editLink.setAttribute("href", editLink.getAttribute("href") + style.id);
|
||||
return e;
|
||||
}
|
||||
|
||||
function enable(event, enabled) {
|
||||
var id = getId(event);
|
||||
enableStyle(id, enabled);
|
||||
}
|
||||
|
||||
function doDelete() {
|
||||
if (!confirm(t('deleteStyleConfirm'))) {
|
||||
return;
|
||||
}
|
||||
var id = getId(event);
|
||||
deleteStyle(id);
|
||||
}
|
||||
|
||||
function getId(event) {
|
||||
var e = event.target;
|
||||
while (e) {
|
||||
if (e.hasAttribute("style-id")) {
|
||||
return e.getAttribute("style-id");
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
width: 200px;
|
||||
}
|
||||
e = e.parentNode;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
#no-styles {
|
||||
font-style: italic;
|
||||
}
|
||||
.disabled {
|
||||
color: #BBB;
|
||||
}
|
||||
.disabled .disable {
|
||||
display: none;
|
||||
}
|
||||
.enabled .enable {
|
||||
display: none;
|
||||
}
|
||||
.style-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
.actions {
|
||||
font-size: x-small;
|
||||
}
|
||||
a, a:visited {
|
||||
color: black;
|
||||
}
|
||||
.entry {
|
||||
padding-bottom: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
#find-styles, #manage-styles {
|
||||
font-size: smaller;
|
||||
}
|
||||
#find-styles {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
function openLink(event) {
|
||||
chrome.tabs.create({url: event.target.href});
|
||||
return false;
|
||||
}
|
||||
<script src="localization.js"></script>
|
||||
<script src="storage.js"></script>
|
||||
<script src="messaging.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
function handleUpdate(style) {
|
||||
var installed = document.getElementById("installed");
|
||||
installed.replaceChild(createStyleElement(style), installed.querySelector("[style-id='" + style.id + "']"));
|
||||
}
|
||||
<div id="installed"></div>
|
||||
|
||||
function handleDelete(id) {
|
||||
var installed = document.getElementById("installed");
|
||||
installed.removeChild(installed.querySelector("[style-id='" + id + "']"));
|
||||
}
|
||||
</script>
|
||||
<div id="find-styles"><a id="find-styles-link" href="#"></a></div>
|
||||
<div id="manage-styles"><a id="open-manage-link" href="manage.html" target="_new"></a></div>
|
||||
|
||||
<div id="installed"></div>
|
||||
<script src="popup.js"></script>
|
||||
|
||||
<div id="find-styles"><a href="#" onclick="return openLink(event);"><script>o('findStylesForSite')</script></a></div>
|
||||
<div id="manage-styles"><a href="manage.html" target="_new"><script>o('openManage')</script></a></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
77
popup.js
Normal file
77
popup.js
Normal file
|
@ -0,0 +1,77 @@
|
|||
var styleTemplate = document.createElement("div");
|
||||
styleTemplate.innerHTML = "<div class='style-name'></div><div class='actions'><a class='style-edit-link' href='edit.html?id='>" + t('editStyleLabel') + "</a> <a href='#' class='enable'>" + t('enableStyleLabel') + "</a> <a href='#' class='disable'>" + t('disableStyleLabel') + "</a> <a href='#' class='delete'>" + t('deleteStyleLabel') + "</a></div>";
|
||||
|
||||
chrome.tabs.getSelected(null, function(tab) {
|
||||
chrome.extension.sendMessage({method: "getStyles", matchUrl: tab.url}, showStyles);
|
||||
document.querySelector("#find-styles a").href = "http://userstyles.org/styles/browse/all/" + encodeURIComponent(tab.url);
|
||||
});
|
||||
|
||||
function showStyles(styles) {
|
||||
var installed = document.getElementById("installed");
|
||||
if (styles.length == 0) {
|
||||
installed.innerHTML = "<div class='entry' id='no-styles'>" + t('noStylesForSite') + "</div>";
|
||||
}
|
||||
styles.map(createStyleElement).forEach(function(e) {
|
||||
installed.appendChild(e);
|
||||
});
|
||||
}
|
||||
|
||||
function createStyleElement(style) {
|
||||
var e = styleTemplate.cloneNode(true);
|
||||
e.setAttribute("class", "entry " + (style.enabled == "true" ? "enabled" : "disabled"));
|
||||
e.setAttribute("style-id", style.id);
|
||||
var styleName = e.querySelector(".style-name");
|
||||
styleName.appendChild(document.createTextNode(style.name));
|
||||
var editLink = e.querySelector(".style-edit-link");
|
||||
editLink.setAttribute("href", editLink.getAttribute("href") + style.id);
|
||||
editLink.addEventListener("click", openLink, 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);
|
||||
return e;
|
||||
}
|
||||
|
||||
function enable(event, enabled) {
|
||||
var id = getId(event);
|
||||
enableStyle(id, enabled);
|
||||
}
|
||||
|
||||
function doDelete() {
|
||||
if (!confirm(t('deleteStyleConfirm'))) {
|
||||
return;
|
||||
}
|
||||
var id = getId(event);
|
||||
deleteStyle(id);
|
||||
}
|
||||
|
||||
function getId(event) {
|
||||
var e = event.target;
|
||||
while (e) {
|
||||
if (e.hasAttribute("style-id")) {
|
||||
return e.getAttribute("style-id");
|
||||
}
|
||||
e = e.parentNode;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function openLink(event) {
|
||||
chrome.tabs.create({url: event.target.href});
|
||||
return false;
|
||||
}
|
||||
|
||||
function handleUpdate(style) {
|
||||
var installed = document.getElementById("installed");
|
||||
installed.replaceChild(createStyleElement(style), installed.querySelector("[style-id='" + style.id + "']"));
|
||||
}
|
||||
|
||||
function handleDelete(id) {
|
||||
var installed = document.getElementById("installed");
|
||||
installed.removeChild(installed.querySelector("[style-id='" + id + "']"));
|
||||
}
|
||||
|
||||
tE("open-manage-link", "openManage");
|
||||
tE("find-styles-link", "findStylesForSite");
|
||||
|
||||
document.getElementById("find-styles-link").addEventListener("click", openLink, false);
|
||||
|
307
storage.js
307
storage.js
|
@ -1,5 +1,3 @@
|
|||
var namespacePattern = /^\s*@namespace\s+([a-zA-Z]+\s+)?url\(\"?http:\/\/www.w3.org\/1999\/xhtml\"?\);?\s*$/;
|
||||
|
||||
var stylishDb = null;
|
||||
function getDatabase(ready, error) {
|
||||
if (stylishDb != null) {
|
||||
|
@ -53,303 +51,13 @@ function dbV13(d, error, done) {
|
|||
}, error, function() { done(d)});
|
||||
}
|
||||
|
||||
function getStyles(options, callback) {
|
||||
getDatabase(function(db) {
|
||||
db.readTransaction(function (t) {
|
||||
if ("matchUrl" in options) {
|
||||
// get a list of style ids that apply to the url. we need to do this separately because we need all the metas for the styles, not just the matching ones
|
||||
// find site-specific ones
|
||||
var sql = "SELECT DISTINCT s.style_id FROM sections s INNER JOIN section_meta sm ON sm.section_id = s.id WHERE (sm.name = 'url' and sm.value = ?) OR (sm.name = 'url-prefix' AND ? LIKE (sm.value || '%')) OR (sm.name = 'regexp' AND ? REGEXP sm.value)";
|
||||
var matchParams = [];
|
||||
var domains = getDomains(options.matchUrl);
|
||||
matchParams = matchParams.concat([options.matchUrl, options.matchUrl, options.matchUrl]).concat(domains);
|
||||
var domainClause = "";
|
||||
if (domains.length == 1) {
|
||||
sql += " OR (sm.name = 'domain' AND sm.value = ?)";
|
||||
} else if (domains.length > 1) {
|
||||
sql += " OR (sm.name = 'domain' AND sm.value IN (";
|
||||
sql += domains.map(function(d) { return "?";}).join(",");
|
||||
sql += '))';
|
||||
}
|
||||
t.executeSql(sql, matchParams, function (t, r) {
|
||||
var style_ids = [];
|
||||
if (options.id) {
|
||||
style_ids.push(options.id);
|
||||
}
|
||||
for (var i = 0; i < r.rows.length; i++) {
|
||||
var values = r.rows.item(i);
|
||||
style_ids.push(values.style_id);
|
||||
}
|
||||
// now add in global ones
|
||||
getGlobalStyleIds(function(ids) {
|
||||
style_ids = uniqueArray(style_ids.concat(ids));
|
||||
loadStyles(style_ids, options.enabled, options.url, callback);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
loadStyles(options.id ? [options.id] : null, options.enabled, options.url, callback);
|
||||
}
|
||||
}, reportError);
|
||||
}, reportError);
|
||||
}
|
||||
|
||||
function uniqueArray(ar) {
|
||||
return ar.filter(function(s, i, a){
|
||||
return i === a.lastIndexOf(s);
|
||||
});
|
||||
}
|
||||
|
||||
function getCache(callback) {
|
||||
if (isBackground()) {
|
||||
callback(cachedStyles);
|
||||
return;
|
||||
}
|
||||
chrome.extension.sendRequest({name: "getCachedStyles"}, callback);
|
||||
}
|
||||
|
||||
function fixBoolean(b) {
|
||||
if (typeof b != "undefined") {
|
||||
return b != "false";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function loadStyles(styleIds, enabled, url, callback) {
|
||||
// clean up the parameters
|
||||
enabled = fixBoolean(enabled);
|
||||
if (typeof url == "undefined") {
|
||||
url = null;
|
||||
}
|
||||
// grab what we can from the cache
|
||||
if (styleIds) {
|
||||
getCache(function(cache) {
|
||||
var styles = [];
|
||||
var styleIdsNeeded = [];
|
||||
styleIds.forEach(function(id) {
|
||||
if (cache[id]) {
|
||||
if (checkStyle(cache[id], enabled, url)) {
|
||||
styles.push(cache[id]);
|
||||
}
|
||||
} else {
|
||||
styleIdsNeeded.push(id);
|
||||
}
|
||||
});
|
||||
styleIds = styleIdsNeeded;
|
||||
// do we have everything we need?
|
||||
if (styleIds.length == 0) {
|
||||
callback(styles);
|
||||
return;
|
||||
}
|
||||
loadStylesFromDB(styles, styleIds, enabled, url, callback);
|
||||
});
|
||||
return;
|
||||
}
|
||||
loadStylesFromDB([], styleIds, enabled, url, callback);
|
||||
}
|
||||
|
||||
function checkStyle(style, enabled, url) {
|
||||
return (enabled == null || enabled == fixBoolean(style.enabled)) && (url == null || url == style.url);
|
||||
}
|
||||
|
||||
function loadStylesFromDB(styles, styleIds, enabled, url, callback) {
|
||||
// load from the db for the rest
|
||||
getDatabase(function(db) {
|
||||
db.readTransaction(function (t) {
|
||||
var where = "";
|
||||
var params = [];
|
||||
if (styleIds) {
|
||||
if (styleIds.size == 0) {
|
||||
callback([]);
|
||||
return;
|
||||
}
|
||||
|
||||
where += " AND s.id IN ("
|
||||
var firstStyleId = true;
|
||||
styleIds.forEach(function(styleId) {
|
||||
where += firstStyleId ? "?" : ",?";
|
||||
firstStyleId = false;
|
||||
params.push(styleId);
|
||||
});
|
||||
where += ")";
|
||||
}
|
||||
/*if (enabled != null) {
|
||||
where += ' AND enabled = ?';
|
||||
params.push(enabled);
|
||||
}
|
||||
if (url != null) {
|
||||
where += ' AND s.url = ?';
|
||||
params.push(url);
|
||||
}*/
|
||||
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 currentStyle = null;
|
||||
var currentSection = null;
|
||||
for (var i = 0; i < r.rows.length; i++) {
|
||||
var values = r.rows.item(i);
|
||||
var metaName = null;
|
||||
switch (values.metaName) {
|
||||
case null:
|
||||
break;
|
||||
case "url":
|
||||
metaName = "urls";
|
||||
break;
|
||||
case "url-prefix":
|
||||
metaName = "urlPrefixes";
|
||||
break;
|
||||
case "domain":
|
||||
var metaName = "domains";
|
||||
break;
|
||||
case "regexps":
|
||||
var metaName = "regexps";
|
||||
break;
|
||||
default:
|
||||
var metaName = values.metaName + "s";
|
||||
}
|
||||
var metaValue = values.metaValue;
|
||||
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, sections: []};
|
||||
styles.push(currentStyle);
|
||||
}
|
||||
if (currentSection == null || currentSection.id != values.section_id) {
|
||||
currentSection = {id: values.section_id, code: values.code};
|
||||
currentStyle.sections.push(currentSection);
|
||||
}
|
||||
if (metaName && metaValue) {
|
||||
if (currentSection[metaName]) {
|
||||
currentSection[metaName].push(metaValue);
|
||||
} else {
|
||||
currentSection[metaName] = [metaValue];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isBackground()) {
|
||||
styles.forEach(function(style) {
|
||||
cachedStyles[style.id] = style;
|
||||
|
||||
});
|
||||
} else {
|
||||
chrome.extension.sendRequest({name: "cacheStyles", styles: styles});
|
||||
}
|
||||
callback(styles.filter(function(style) {
|
||||
return checkStyle(style, enabled, url);
|
||||
}));
|
||||
}, reportError);
|
||||
}, reportError);
|
||||
}, reportError);
|
||||
}
|
||||
|
||||
function getGlobalStyleIds(callback) {
|
||||
if (isBackground() && cachedGlobalStyleIds != null) {
|
||||
callback(cachedGlobalStyleIds);
|
||||
return;
|
||||
}
|
||||
getDatabase(function(db) {
|
||||
db.readTransaction(function (t) {
|
||||
t.executeSql("SELECT DISTINCT s.style_id, s.code FROM sections s LEFT JOIN section_meta sm ON sm.section_id = s.id INNER JOIN styles st ON st.id = s.style_id GROUP BY s.id HAVING COUNT(sm.id) = 0", [], function (t, r) {
|
||||
var style_ids = [];
|
||||
for (var i = 0; i < r.rows.length; i++) {
|
||||
var values = r.rows.item(i);
|
||||
// ignore namespace only sections
|
||||
if (!namespacePattern.test(values.code) && style_ids.indexOf(values.style_id) == -1) {
|
||||
style_ids.push(values.style_id);
|
||||
}
|
||||
}
|
||||
if (isBackground()) {
|
||||
cachedGlobalStyleIds = style_ids;
|
||||
}
|
||||
callback(style_ids);
|
||||
}, reportError);
|
||||
}, reportError);
|
||||
}, reportError);
|
||||
}
|
||||
|
||||
|
||||
function saveFromJSON(o, callback) {
|
||||
getDatabase(function(db) {
|
||||
db.transaction(function (t) {
|
||||
if (o.id) {
|
||||
t.executeSql('DELETE FROM section_meta WHERE section_id IN (SELECT id FROM sections WHERE style_id = ?);', [o.id]);
|
||||
t.executeSql('DELETE FROM sections WHERE style_id = ?;', [o.id]);
|
||||
} else {
|
||||
t.executeSql('INSERT INTO styles (name, enabled, url, updateUrl) VALUES (?, ?, ?, ?);', [o.name, true, o.url, o.updateUrl]);
|
||||
}
|
||||
o.sections.forEach(function(section) {
|
||||
if (o.id) {
|
||||
t.executeSql('INSERT INTO sections (style_id, code) VALUES (?, ?);', [o.id, section.code]);
|
||||
} else {
|
||||
t.executeSql('INSERT INTO sections (style_id, code) SELECT id, ? FROM styles ORDER BY id DESC LIMIT 1;', [section.code]);
|
||||
}
|
||||
section.urls.forEach(function(u) {
|
||||
t.executeSql("INSERT INTO section_meta (section_id, name, value) SELECT id, 'url', ? FROM sections ORDER BY id DESC LIMIT 1;", [u]);
|
||||
});
|
||||
section.urlPrefixes.forEach(function(u) {
|
||||
t.executeSql("INSERT INTO section_meta (section_id, name, value) SELECT id, 'url-prefix', ? FROM sections ORDER BY id DESC LIMIT 1;", [u]);
|
||||
});
|
||||
section.domains.forEach(function(u) {
|
||||
t.executeSql("INSERT INTO section_meta (section_id, name, value) SELECT id, 'domain', ? FROM sections ORDER BY id DESC LIMIT 1;", [u]);
|
||||
});
|
||||
section.regexps.forEach(function(u) {
|
||||
t.executeSql("INSERT INTO section_meta (section_id, name, value) SELECT id, 'regexp', ? FROM sections ORDER BY id DESC LIMIT 1;", [u]);
|
||||
});
|
||||
});
|
||||
}, reportError, function() {saveFromJSONComplete(o.id, callback)});
|
||||
}, reportError);
|
||||
}
|
||||
|
||||
function saveFromJSONComplete(id, callback) {
|
||||
chrome.extension.sendRequest({name: "styleChanged"});
|
||||
if (id) {
|
||||
notifyAllTabs({name:"styleUpdated", style: id});
|
||||
if (callback) {
|
||||
callback(id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Load the style id
|
||||
getDatabase(function(db) {
|
||||
db.readTransaction(function (t) {
|
||||
t.executeSql('SELECT id FROM styles ORDER BY id DESC LIMIT 1', [], function(t, r) {
|
||||
var styleId = r.rows.item(0).id;
|
||||
getStyles({id: styleId}, function(styles) {
|
||||
notifyAllTabs({name:"styleAdded", style: styles[0]});
|
||||
});
|
||||
if (callback) {
|
||||
callback(styleId);
|
||||
}
|
||||
}, reportError)
|
||||
}, reportError)
|
||||
});
|
||||
}
|
||||
|
||||
function reportError() {
|
||||
for (i in arguments) {
|
||||
if ("message" in arguments[i]) {
|
||||
//alert(arguments[i].message);
|
||||
console.log(arguments[i].message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isBackground() {
|
||||
return typeof background != "undefined" && background;
|
||||
}
|
||||
|
||||
function getDomains(url) {
|
||||
var d = /.*?:\/*([^\/]+)/.exec(url)[1];
|
||||
var domains = [d];
|
||||
while (d.indexOf(".") != -1) {
|
||||
d = d.substring(d.indexOf(".") + 1);
|
||||
domains.push(d);
|
||||
}
|
||||
return domains;
|
||||
}
|
||||
|
||||
function enableStyle(id, enabled) {
|
||||
getDatabase(function(db) {
|
||||
db.transaction(function (t) {
|
||||
t.executeSql("UPDATE styles SET enabled = ? WHERE id = ?;", [enabled, id]);
|
||||
}, reportError, function() {
|
||||
chrome.extension.sendRequest({name: "styleChanged"});
|
||||
getStyles({id: id}, function(styles) {
|
||||
chrome.extension.sendMessage({method: "styleChanged"});
|
||||
chrome.extension.sendMessage({method: "getStyles", id: id}, function(styles) {
|
||||
handleUpdate(styles[0]);
|
||||
notifyAllTabs({name:"styleUpdated", style: styles[0]});
|
||||
});
|
||||
|
@ -364,9 +72,18 @@ function deleteStyle(id) {
|
|||
t.executeSql('DELETE FROM sections WHERE style_id = ?;', [id]);
|
||||
t.executeSql("DELETE FROM styles WHERE id = ?;", [id]);
|
||||
}, reportError, function() {
|
||||
chrome.extension.sendRequest({name: "styleChanged"});
|
||||
chrome.extension.sendMessage({method: "styleChanged"});
|
||||
handleDelete(id);
|
||||
notifyAllTabs({name:"styleDeleted", id: id});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function reportError() {
|
||||
for (i in arguments) {
|
||||
if ("message" in arguments[i]) {
|
||||
//alert(arguments[i].message);
|
||||
console.log(arguments[i].message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user