commit
3558277533
|
@ -60,6 +60,10 @@
|
||||||
"message": "URLs starting with",
|
"message": "URLs starting with",
|
||||||
"description": "Option to make the style apply to the entered string as a URL prefix"
|
"description": "Option to make the style apply to the entered string as a URL prefix"
|
||||||
},
|
},
|
||||||
|
"applyAllUpdates": {
|
||||||
|
"message": "Apply all updates",
|
||||||
|
"description": "Label for the button to apply all detected updates"
|
||||||
|
},
|
||||||
"checkAllUpdates": {
|
"checkAllUpdates": {
|
||||||
"message": "Check all styles for updates",
|
"message": "Check all styles for updates",
|
||||||
"description": "Label for the button to check all styles for updates"
|
"description": "Label for the button to check all styles for updates"
|
||||||
|
@ -288,6 +292,10 @@
|
||||||
"message": "Style is up to date.",
|
"message": "Style is up to date.",
|
||||||
"description": "Text that displays when an update check completed and no update is available"
|
"description": "Text that displays when an update check completed and no update is available"
|
||||||
},
|
},
|
||||||
|
"updateAllCheckSucceededNoUpdate": {
|
||||||
|
"message": "All styles are up to date.",
|
||||||
|
"description": "Text that displays when an update all check completed and no updates are available"
|
||||||
|
},
|
||||||
"updateCompleted": {
|
"updateCompleted": {
|
||||||
"message": "Update completed.",
|
"message": "Update completed.",
|
||||||
"description": "Text that displays when an update completed"
|
"description": "Text that displays when an update completed"
|
||||||
|
|
|
@ -33,6 +33,9 @@ chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
|
||||||
case "healthCheck":
|
case "healthCheck":
|
||||||
getDatabase(function() { sendResponse(true); }, function() { sendResponse(false); });
|
getDatabase(function() { sendResponse(true); }, function() { sendResponse(false); });
|
||||||
break;
|
break;
|
||||||
|
case "openURL":
|
||||||
|
openURL(request);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -321,3 +324,22 @@ chrome.tabs.onAttached.addListener(function(tabId, data) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function openURL(options) {
|
||||||
|
chrome.tabs.query({currentWindow: true, url: options.url}, function(tabs) {
|
||||||
|
// switch to an existing tab with the requested url
|
||||||
|
if (tabs.length) {
|
||||||
|
chrome.tabs.highlight({windowId: tabs[0].windowId, tabs: tabs[0].index}, function (window) {});
|
||||||
|
} else {
|
||||||
|
delete options.method;
|
||||||
|
chrome.tabs.query({currentWindow: true, active: true}, function(tabs) {
|
||||||
|
// re-use an active new tab page
|
||||||
|
if (tabs.length && tabs[0].url.match(/^chrome:\/\/newtab\/?$/)) {
|
||||||
|
chrome.tabs.update(options);
|
||||||
|
} else {
|
||||||
|
chrome.tabs.create(options);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
120
edit.html
120
edit.html
|
@ -34,19 +34,19 @@
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
font: 12px arial,sans-serif;
|
font: 12px arial,sans-serif;
|
||||||
}
|
}
|
||||||
#header {
|
#header {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0px;
|
top: 0;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
border-right: 1px dashed #AAA;
|
border-right: 1px dashed #AAA;
|
||||||
}
|
}
|
||||||
.notmac #header {
|
.notmac #header {
|
||||||
-webkit-box-shadow: 0px 0px 50px -18px black;
|
-webkit-box-shadow: 0 0 50px -18px black;
|
||||||
}
|
}
|
||||||
#sections {
|
#sections {
|
||||||
padding-left: 290px;
|
padding-left: 290px;
|
||||||
|
@ -62,7 +62,7 @@
|
||||||
}
|
}
|
||||||
#sections > div {
|
#sections > div {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
padding: 0px 15px;
|
padding: 0 15px;
|
||||||
}
|
}
|
||||||
#sections > div:not(:first-child) {
|
#sections > div:not(:first-child) {
|
||||||
border-top: 2px solid black;
|
border-top: 2px solid black;
|
||||||
|
@ -79,6 +79,13 @@
|
||||||
#header label {
|
#header label {
|
||||||
width: 60px;
|
width: 60px;
|
||||||
}
|
}
|
||||||
|
#options .aligned {
|
||||||
|
display: table-row;
|
||||||
|
}
|
||||||
|
#options .aligned > * {
|
||||||
|
display: table-cell;
|
||||||
|
margin: 0.5ex 0 0 0;
|
||||||
|
}
|
||||||
.code {
|
.code {
|
||||||
height: 10em;
|
height: 10em;
|
||||||
width: 40em;
|
width: 40em;
|
||||||
|
@ -154,24 +161,68 @@
|
||||||
width: auto;
|
width: auto;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
|
padding-top: 8px;
|
||||||
|
}
|
||||||
|
#header section {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
#header label {
|
||||||
|
width: auto;
|
||||||
|
vertical-align: baseline;
|
||||||
|
margin-right: .5em;
|
||||||
|
}
|
||||||
|
#header input[type="checkbox"] {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
#name {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
h1, h2 {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#basic-info > div {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
#actions br {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#actions img {
|
||||||
|
position: relative;
|
||||||
|
top: .2em;
|
||||||
|
margin-left: .2em;
|
||||||
|
}
|
||||||
|
#actions > * + button, #actions a {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
#options {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: baseline;
|
||||||
|
}
|
||||||
|
#options .option, #options .option > * {
|
||||||
|
flex: auto;
|
||||||
|
height: 1.8em;
|
||||||
|
margin: 0;
|
||||||
|
display: inline-block;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
#options .option {
|
||||||
|
margin-right: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sections {
|
#sections {
|
||||||
padding-left: 0px;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sections > div {
|
#sections > div {
|
||||||
padding: 0px;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sections-heading {
|
#sections-heading {
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
body > section > *:not(h2) {
|
body > section > *:not(h2) {
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* editor options */
|
/* editor options */
|
||||||
|
@ -193,43 +244,38 @@
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<h1 id="heading"></h1>
|
<h1 id="heading"></h1>
|
||||||
<section id="basic-info">
|
<section id="basic-info">
|
||||||
<div><label for="name" id="name-label"></label><input id="name"><div>
|
<div><label for="name" id="name-label"></label><input id="name" class="style-contributor"></div>
|
||||||
<div><label for="enabled" id="enabled-label"></label><input type="checkbox" id="enabled"></div>
|
<div><label for="enabled" id="enabled-label"></label><input type="checkbox" id="enabled" class="style-contributor"></div>
|
||||||
</section>
|
</section>
|
||||||
|
<section id="actions">
|
||||||
<button id="to-mozilla"></button><img id="to-mozilla-help" src="help.png"><br><br>
|
<button id="to-mozilla"></button><img id="to-mozilla-help" src="help.png"><br><br>
|
||||||
|
<button id="from-mozilla">From Mozilla format</button><img id="from-mozilla-help" src="help.png"><br><br>
|
||||||
<button id="save-button" title="Ctrl-S"></button>
|
<button id="save-button" title="Ctrl-S"></button>
|
||||||
<a href="manage.html"><button id="cancel-button"></button></a>
|
<a href="manage.html"><button id="cancel-button"></button></a>
|
||||||
<form id="options">
|
</section>
|
||||||
|
<section id="options">
|
||||||
<h2 id="options-heading"></h2>
|
<h2 id="options-heading"></h2>
|
||||||
<table cols="2">
|
<div class="option">
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
<input data-option="lineWrapping" id="editor.lineWrapping" type="checkbox">
|
<input data-option="lineWrapping" id="editor.lineWrapping" type="checkbox">
|
||||||
<label id="lineWrapping-label" for="editor.lineWrapping"></label>
|
<label id="lineWrapping-label" for="editor.lineWrapping"></label>
|
||||||
</td>
|
</div>
|
||||||
</tr>
|
<div class="option">
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
<input data-option="smartIndent" id="editor.smartIndent" type="checkbox">
|
<input data-option="smartIndent" id="editor.smartIndent" type="checkbox">
|
||||||
<label id="smartIndent-label" for="editor.smartIndent"></label>
|
<label id="smartIndent-label" for="editor.smartIndent"></label>
|
||||||
</td>
|
</div>
|
||||||
</tr>
|
<div class="option">
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
<input data-option="indentWithTabs" id="editor.indentWithTabs" type="checkbox">
|
<input data-option="indentWithTabs" id="editor.indentWithTabs" type="checkbox">
|
||||||
<label id="indentWithTabs-label" for="editor.indentWithTabs"></label>
|
<label id="indentWithTabs-label" for="editor.indentWithTabs"></label>
|
||||||
</td>
|
</div>
|
||||||
</tr>
|
<div class="option aligned">
|
||||||
<tr>
|
<label id="tabSize-label" for="editor.tabSize"></label>
|
||||||
<td><label id="tabSize-label" for="editor.tabSize"></label></td>
|
<input data-option="tabSize" id="editor.tabSize" type="number" min="0">
|
||||||
<td><input data-option="tabSize" id="editor.tabSize" type="number" min="0"></td>
|
</div>
|
||||||
</tr>
|
<div class="option aligned">
|
||||||
<tr>
|
<label id="keyMap-label" for="editor.keyMap"></label>
|
||||||
<td><label id="keyMap-label" for="editor.keyMap"></label></td>
|
<select data-option="keyMap" id="editor.keyMap"></select>
|
||||||
<td><select data-option="keyMap" id="editor.keyMap"></select></td>
|
</div>
|
||||||
</tr>
|
</section>
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
<section id="sections">
|
<section id="sections">
|
||||||
<h2><span id="sections-heading"></span> <img id="sections-help" src="help.png"></h2>
|
<h2><span id="sections-heading"></span> <img id="sections-help" src="help.png"></h2>
|
||||||
|
|
407
edit.js
407
edit.js
|
@ -1,84 +1,88 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var styleId = null;
|
var styleId = null;
|
||||||
var dirty = false;
|
var dirty = {}; // only the actually dirty items here
|
||||||
var lockScroll; // ensure the section doesn't jump when clicking selected text
|
var editors = []; // array of all CodeMirror instances
|
||||||
|
var lockScroll; // temporary focus-jump-on-click fix, TODO: revert c084ea3 once CM is updated
|
||||||
|
var isSeparateWindow; // used currrently to determine if the window size/pos should be remembered
|
||||||
|
|
||||||
|
// direct & reverse mapping of @-moz-document keywords and internal property names
|
||||||
|
var propertyToCss = {urls: "url", urlPrefixes: "url-prefix", domains: "domain", regexps: "regexp"};
|
||||||
|
var CssToProperty = {"url": "urls", "url-prefix": "urlPrefixes", "domain": "domains", "regexp": "regexps"};
|
||||||
|
|
||||||
|
// templates
|
||||||
var appliesToTemplate = document.createElement("li");
|
var appliesToTemplate = document.createElement("li");
|
||||||
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>';
|
appliesToTemplate.innerHTML = '<select name="applies-type" class="applies-type style-contributor"><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 style-contributor"><button class="remove-applies-to">' + t("appliesRemove") + '</button><button class="add-applies-to">' + t("appliesAdd") + '</button>';
|
||||||
|
|
||||||
var appliesToEverythingTemplate = document.createElement("li");
|
var appliesToEverythingTemplate = document.createElement("li");
|
||||||
appliesToEverythingTemplate.className = "applies-to-everything";
|
appliesToEverythingTemplate.className = "applies-to-everything";
|
||||||
appliesToEverythingTemplate.innerHTML = t("appliesToEverything") + ' <button class="add-applies-to">' + t("appliesSpecify") + '</button>'
|
appliesToEverythingTemplate.innerHTML = t("appliesToEverything") + ' <button class="add-applies-to">' + t("appliesSpecify") + '</button>';
|
||||||
|
|
||||||
var sectionTemplate = document.createElement("div");
|
var sectionTemplate = document.createElement("div");
|
||||||
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>';
|
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>';
|
||||||
|
|
||||||
document.addEventListener("change", function(event) {
|
|
||||||
var node = event.target;
|
// make querySelectorAll enumeration code readable
|
||||||
if (node.type && !node.form) { // INPUTs that aren't in a FORM are stylesheet
|
["forEach", "some", "indexOf"].forEach(function(method) {
|
||||||
switch (node.type) {
|
NodeList.prototype[method]= Array.prototype[method];
|
||||||
case "checkbox":
|
|
||||||
setCleanItem(node, node.checked === node.defaultChecked);
|
|
||||||
break;
|
|
||||||
case "text":
|
|
||||||
case "select-one":
|
|
||||||
case "select-multiple":
|
|
||||||
setCleanItem(node, node.value === node.defaultValue);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function onChange(event) {
|
||||||
|
var node = event.target;
|
||||||
|
if ("savedValue" in node) {
|
||||||
|
var currentValue = "checkbox" === node.type ? node.checked : node.value;
|
||||||
|
setCleanItem(node, node.savedValue === currentValue);
|
||||||
|
} else {
|
||||||
|
// the manually added section's applies-to is dirty only when the value is non-empty
|
||||||
|
setCleanItem(node, node.localName != "input" || !node.value.trim());
|
||||||
|
delete node.savedValue; // only valid when actually saved
|
||||||
|
}
|
||||||
|
updateTitle();
|
||||||
|
}
|
||||||
|
|
||||||
// Set .dirty on stylesheet contributors that have changed
|
// Set .dirty on stylesheet contributors that have changed
|
||||||
var items = {};
|
function setDirtyClass(node, isDirty) {
|
||||||
function isCleanItem(node) {
|
node.classList.toggle("dirty", isDirty);
|
||||||
return items[node.id];
|
|
||||||
}
|
}
|
||||||
function setCleanItem(node, clean) {
|
|
||||||
var id = node.id;
|
|
||||||
if (!id) id = node.id = Date.now().toString(32).substr(-6);
|
|
||||||
items[id] = clean;
|
|
||||||
|
|
||||||
if (clean) node.classList.remove("dirty");
|
function setCleanItem(node, isClean) {
|
||||||
else node.classList.add("dirty");
|
if (!node.id) {
|
||||||
|
node.id = Date.now().toString(32).substr(-6);
|
||||||
initTitle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isClean) {
|
||||||
|
delete dirty[node.id];
|
||||||
|
node.savedValue = "checkbox" === node.type ? node.checked : node.value;
|
||||||
|
} else {
|
||||||
|
dirty[node.id] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDirtyClass(node, !isClean);
|
||||||
|
}
|
||||||
|
|
||||||
function isCleanGlobal() {
|
function isCleanGlobal() {
|
||||||
var clean = Object.keys(items)
|
var clean = Object.keys(dirty).length == 0;
|
||||||
.every(function(item) { return items[item] });
|
setDirtyClass(document.body, !clean);
|
||||||
|
|
||||||
if (clean) document.body.classList.remove("dirty");
|
|
||||||
else document.body.classList.add("dirty");
|
|
||||||
|
|
||||||
return clean;
|
return clean;
|
||||||
}
|
}
|
||||||
function setCleanGlobal(form) {
|
|
||||||
if (!form) form = null;
|
function setCleanGlobal() {
|
||||||
Array.prototype.forEach.call(document.querySelectorAll("input, select"), function(node) {
|
document.querySelectorAll("#header, #sections > div").forEach(setCleanSection);
|
||||||
if (node.form === form) {
|
dirty = {}; // forget the dirty applies-to ids from a deleted section after the style was saved
|
||||||
if ("checkbox" === node.type) {
|
|
||||||
node.defaultChecked = node.checked;
|
|
||||||
} else {
|
|
||||||
node.defaultValue = node.value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
node.classList.remove("dirty");
|
function setCleanSection(section) {
|
||||||
delete items[node.id];
|
section.querySelectorAll(".style-contributor").forEach(function(node) { setCleanItem(node, true) });
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
editors.forEach(function(cm) {
|
// #header section has no codemirror
|
||||||
cm.lastChange = cm.changeGeneration();
|
var wrapper = section.querySelector(".CodeMirror");
|
||||||
cm.getTextArea().parentNode.defaultValue = cm.lastChange;
|
if (wrapper) {
|
||||||
|
var cm = wrapper.CodeMirror;
|
||||||
|
section.savedValue = cm.changeGeneration();
|
||||||
indicateCodeChange(cm);
|
indicateCodeChange(cm);
|
||||||
});
|
}
|
||||||
|
|
||||||
initTitle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var editors = []; // array of all CodeMirror instances
|
|
||||||
function initCodeMirror() {
|
function initCodeMirror() {
|
||||||
var CM = CodeMirror;
|
var CM = CodeMirror;
|
||||||
// default option values
|
// default option values
|
||||||
|
@ -93,7 +97,7 @@ function initCodeMirror() {
|
||||||
lint: CodeMirror.lint.css,
|
lint: CodeMirror.lint.css,
|
||||||
keyMap: "sublime",
|
keyMap: "sublime",
|
||||||
extraKeys: {"Ctrl-Space": "autocomplete"}
|
extraKeys: {"Ctrl-Space": "autocomplete"}
|
||||||
};
|
}
|
||||||
mergeOptions(stylishOptions, CM.defaults);
|
mergeOptions(stylishOptions, CM.defaults);
|
||||||
mergeOptions(userOptions, CM.defaults);
|
mergeOptions(userOptions, CM.defaults);
|
||||||
|
|
||||||
|
@ -105,9 +109,22 @@ function initCodeMirror() {
|
||||||
// additional commands
|
// additional commands
|
||||||
var cc = CM.commands;
|
var cc = CM.commands;
|
||||||
cc.jumpToLine = jumpToLine;
|
cc.jumpToLine = jumpToLine;
|
||||||
cc.nextBuffer = nextBuffer;
|
cc.nextBuffer = function(cm) { nextPrevBuffer(cm, 1) };
|
||||||
cc.prevBuffer = prevBuffer;
|
cc.prevBuffer = function(cm) { nextPrevBuffer(cm, -1) };
|
||||||
// cc.save = save;
|
|
||||||
|
var cssHintHandler = CM.hint.css;
|
||||||
|
CM.hint.css = function(cm) {
|
||||||
|
var cursor = cm.getCursor();
|
||||||
|
var token = cm.getTokenAt(cursor);
|
||||||
|
if (token.state.state === "prop" && "!important".indexOf(token.string) === 0) {
|
||||||
|
return {
|
||||||
|
from: CM.Pos(cursor.line, token.start),
|
||||||
|
to: CM.Pos(cursor.line, token.end),
|
||||||
|
list: ["!important"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cssHintHandler(cm);
|
||||||
|
}
|
||||||
|
|
||||||
// user option values
|
// user option values
|
||||||
CM.getOption = function (o) {
|
CM.getOption = function (o) {
|
||||||
|
@ -149,7 +166,7 @@ function acmeEventListener(event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace given textarea with the CodeMirror editor
|
// replace given textarea with the CodeMirror editor
|
||||||
function setupCodeMirror(textarea) {
|
function setupCodeMirror(textarea, index) {
|
||||||
var cm = CodeMirror.fromTextArea(textarea);
|
var cm = CodeMirror.fromTextArea(textarea);
|
||||||
cm.addKeyMap({
|
cm.addKeyMap({
|
||||||
"Ctrl-G": "jumpToLine",
|
"Ctrl-G": "jumpToLine",
|
||||||
|
@ -159,35 +176,6 @@ function setupCodeMirror(textarea) {
|
||||||
cm.lastChange = cm.changeGeneration();
|
cm.lastChange = cm.changeGeneration();
|
||||||
cm.on("change", indicateCodeChange);
|
cm.on("change", indicateCodeChange);
|
||||||
|
|
||||||
// ensure the entire section is visible on focus
|
|
||||||
cm.on("focus", function(cm) {
|
|
||||||
var section = cm.display.wrapper.parentNode;
|
|
||||||
var bounds = section.getBoundingClientRect();
|
|
||||||
if ((bounds.bottom > window.innerHeight && bounds.top > 0) || (bounds.top < 0 && bounds.bottom < window.innerHeight)) {
|
|
||||||
lockScroll = null;
|
|
||||||
if (bounds.top < 0) {
|
|
||||||
window.scrollBy(0, bounds.top - 1);
|
|
||||||
} else {
|
|
||||||
window.scrollBy(0, bounds.bottom - window.innerHeight + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// prevent possible double fire of selection change event induced by window.scrollBy
|
|
||||||
var selectionChangeCount = 0, selection;
|
|
||||||
function beforeSelectionChange(cm, obj) {
|
|
||||||
if (++selectionChangeCount == 1) {
|
|
||||||
selection = obj.ranges;
|
|
||||||
} else {
|
|
||||||
obj.update(selection);
|
|
||||||
cm.off("beforeSelectionChange", beforeSelectionChange);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cm.on("beforeSelectionChange", beforeSelectionChange);
|
|
||||||
setTimeout(function() {
|
|
||||||
cm.off("beforeSelectionChange", beforeSelectionChange)
|
|
||||||
}, 200);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// ensure the section doesn't jump when clicking selected text
|
// ensure the section doesn't jump when clicking selected text
|
||||||
cm.on("cursorActivity", function(cm) {
|
cm.on("cursorActivity", function(cm) {
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
|
@ -199,7 +187,14 @@ function setupCodeMirror(textarea) {
|
||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
editors.push(cm);
|
editors.splice(index || editors.length, 0, cm);
|
||||||
|
return cm;
|
||||||
|
}
|
||||||
|
|
||||||
|
function indicateCodeChange(cm) {
|
||||||
|
var section = cm.getTextArea().parentNode;
|
||||||
|
setCleanItem(section, cm.isClean(section.savedValue));
|
||||||
|
updateTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure the section doesn't jump when clicking selected text
|
// ensure the section doesn't jump when clicking selected text
|
||||||
|
@ -211,28 +206,30 @@ document.addEventListener("scroll", function(e) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener("keydown", function(e) {
|
window.addEventListener("keydown", function(e) {
|
||||||
if (e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey && e.keyCode == 83) {
|
if (e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey && e.keyCode == 83) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
chrome.tabs.query({currentWindow: true}, function(tabs) {
|
||||||
|
isSeparateWindow = tabs.length == 1;
|
||||||
|
});
|
||||||
|
|
||||||
window.onbeforeunload = function() {
|
window.onbeforeunload = function() {
|
||||||
|
if (isSeparateWindow) {
|
||||||
prefs.setPref('windowPosition', {
|
prefs.setPref('windowPosition', {
|
||||||
left: screenLeft,
|
left: screenLeft,
|
||||||
top: screenTop,
|
top: screenTop,
|
||||||
width: outerWidth,
|
width: outerWidth,
|
||||||
height: outerHeight
|
height: outerHeight
|
||||||
});
|
});
|
||||||
|
}
|
||||||
document.activeElement.blur();
|
document.activeElement.blur();
|
||||||
return !isCleanGlobal() ? t('styleChangesNotSaved') : null;
|
return !isCleanGlobal() ? t('styleChangesNotSaved') : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function indicateCodeChange(cm) {
|
|
||||||
setCleanItem(cm.getTextArea().parentNode, cm.isClean(cm.lastChange));
|
|
||||||
}
|
|
||||||
|
|
||||||
function addAppliesTo(list, name, value) {
|
function addAppliesTo(list, name, value) {
|
||||||
var showingEverything = list.querySelector(".applies-to-everything") != null;
|
var showingEverything = list.querySelector(".applies-to-everything") != null;
|
||||||
// blow away "Everything" if it's there
|
// blow away "Everything" if it's there
|
||||||
|
@ -264,83 +261,85 @@ function addSection(event, section) {
|
||||||
div.querySelector(".remove-section").addEventListener("click", removeSection, false);
|
div.querySelector(".remove-section").addEventListener("click", removeSection, false);
|
||||||
div.querySelector(".add-section").addEventListener("click", addSection, false);
|
div.querySelector(".add-section").addEventListener("click", addSection, false);
|
||||||
|
|
||||||
|
var codeElement = div.querySelector(".code");
|
||||||
var appliesTo = div.querySelector(".applies-to-list");
|
var appliesTo = div.querySelector(".applies-to-list");
|
||||||
|
var appliesToAdded = false;
|
||||||
|
|
||||||
if (section) {
|
if (section) {
|
||||||
var codeElement = div.querySelector(".code");
|
|
||||||
codeElement.value = section.code;
|
codeElement.value = section.code;
|
||||||
// codeElement.addEventListener("change", makeDirty, false);
|
for (var i in propertyToCss) {
|
||||||
// // Why is this here? Is it possible for CM to not load?
|
if (section[i]) {
|
||||||
if (section.urls) {
|
section[i].forEach(function(url) {
|
||||||
section.urls.forEach(function(url) {
|
addAppliesTo(appliesTo, propertyToCss[i], url);
|
||||||
addAppliesTo(appliesTo, "url", url);
|
appliesToAdded = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (section.urlPrefixes) {
|
|
||||||
section.urlPrefixes.forEach(function(url) {
|
|
||||||
addAppliesTo(appliesTo, "url-prefix", url);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if (section.domains) {
|
|
||||||
section.domains.forEach(function(d) {
|
|
||||||
addAppliesTo(appliesTo, "domain", d);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if (section.regexps) {
|
if (!appliesToAdded) {
|
||||||
section.regexps.forEach(function(d) {
|
|
||||||
addAppliesTo(appliesTo, "regexp", d);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!section.urls && !section.urlPrefixes && !section.domains && !section.regexps) {
|
|
||||||
addAppliesTo(appliesTo);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
addAppliesTo(appliesTo);
|
addAppliesTo(appliesTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
appliesTo.addEventListener("change", onChange);
|
||||||
|
appliesTo.addEventListener("input", onChange);
|
||||||
|
|
||||||
var sections = document.getElementById("sections");
|
var sections = document.getElementById("sections");
|
||||||
var section = event ? event.target.parentNode : null;
|
if (event) {
|
||||||
if (event && section.nextElementSibling) {
|
var clickedSection = event.target.parentNode;
|
||||||
sections.insertBefore(div, section.nextElementSibling);
|
sections.insertBefore(div, clickedSection.nextElementSibling);
|
||||||
|
var newIndex = document.querySelectorAll("#sections > div").indexOf(clickedSection) + 1;
|
||||||
|
setupCodeMirror(codeElement, newIndex).focus();
|
||||||
} else {
|
} else {
|
||||||
sections.appendChild(div);
|
sections.appendChild(div);
|
||||||
|
setupCodeMirror(codeElement);
|
||||||
}
|
}
|
||||||
setupCodeMirror(div.querySelector('.code'));
|
|
||||||
if (section) {
|
setCleanSection(div);
|
||||||
var index = Array.prototype.indexOf.call(sections.children, section);
|
|
||||||
var cm = editors.pop();
|
|
||||||
editors.splice(index, 0, cm);
|
|
||||||
cm.focus();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeAppliesTo(event) {
|
function removeAppliesTo(event) {
|
||||||
var appliesTo = event.target.parentNode,
|
var appliesTo = event.target.parentNode,
|
||||||
appliesToList = appliesTo.parentNode;
|
appliesToList = appliesTo.parentNode;
|
||||||
appliesToList.removeChild(appliesTo);
|
removeAreaAndSetDirty(appliesTo);
|
||||||
if (!appliesToList.hasChildNodes()) {
|
if (!appliesToList.hasChildNodes()) {
|
||||||
var e = appliesToEverythingTemplate.cloneNode(true);
|
addAppliesTo(appliesToList);
|
||||||
e.querySelector(".add-applies-to").addEventListener("click", function() {addAppliesTo(this.parentNode.parentNode)}, false);
|
|
||||||
appliesToList.appendChild(e);
|
|
||||||
}
|
}
|
||||||
Array.prototype.forEach.call(appliesTo.querySelectorAll("input, select"), function(node) {
|
|
||||||
setCleanItem(node, !node.defaultValue);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeSection(event) {
|
function removeSection(event) {
|
||||||
var section = event.target.parentNode;
|
var section = event.target.parentNode;
|
||||||
var wrapper = section.querySelector(".CodeMirror-wrap");
|
var cm = section.querySelector(".CodeMirror").CodeMirror;
|
||||||
var idx = editors.indexOf(wrapper && wrapper.CodeMirror);
|
removeAreaAndSetDirty(section);
|
||||||
if (idx >= 0) {
|
editors.splice(editors.indexOf(cm), 1);
|
||||||
editors.splice(idx, 1);
|
}
|
||||||
setCleanItem(wrapper.parentNode, true);
|
|
||||||
|
function removeAreaAndSetDirty(area) {
|
||||||
|
area.querySelectorAll('.style-contributor').some(function(node) {
|
||||||
|
if (node.savedValue) {
|
||||||
|
// it's a saved section, so make it dirty and stop the enumeration
|
||||||
|
setCleanItem(area, false);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// it's an empty section, so undirty the applies-to items,
|
||||||
|
// otherwise orphaned ids would keep the style dirty
|
||||||
|
setCleanItem(node, true);
|
||||||
}
|
}
|
||||||
section.parentNode.removeChild(section);
|
|
||||||
Array.prototype.forEach.call(section.querySelectorAll("input, select"), function(node) {
|
|
||||||
setCleanItem(node, !node.defaultValue);
|
|
||||||
});
|
});
|
||||||
setCleanItem(section, !section.defaultValue);
|
updateTitle();
|
||||||
|
area.parentNode.removeChild(area);
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeSectionVisible(cm) {
|
||||||
|
var section = cm.display.wrapper.parentNode;
|
||||||
|
var bounds = section.getBoundingClientRect();
|
||||||
|
if ((bounds.bottom > window.innerHeight && bounds.top > 0) || (bounds.top < 0 && bounds.bottom < window.innerHeight)) {
|
||||||
|
lockScroll = null;
|
||||||
|
if (bounds.top < 0) {
|
||||||
|
window.scrollBy(0, bounds.top - 1);
|
||||||
|
} else {
|
||||||
|
window.scrollBy(0, bounds.bottom - window.innerHeight + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupGlobalSearch() {
|
function setupGlobalSearch() {
|
||||||
|
@ -404,8 +403,9 @@ function setupGlobalSearch() {
|
||||||
pos = reverse ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(0, 0);
|
pos = reverse ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(0, 0);
|
||||||
}
|
}
|
||||||
var searchCursor = cm.getSearchCursor(state.query, pos, shouldIgnoreCase(state.query));
|
var searchCursor = cm.getSearchCursor(state.query, pos, shouldIgnoreCase(state.query));
|
||||||
if (searchCursor.find(reverse) || editors.length == 1) {
|
if (searchCursor.find(reverse)) {
|
||||||
if (editors.length > 1) {
|
if (editors.length > 1) {
|
||||||
|
makeSectionVisible(cm);
|
||||||
cm.focus();
|
cm.focus();
|
||||||
}
|
}
|
||||||
// speedup the original findNext
|
// speedup the original findNext
|
||||||
|
@ -435,11 +435,10 @@ function jumpToLine(cm) {
|
||||||
}, {value: cur.line+1});
|
}, {value: cur.line+1});
|
||||||
}
|
}
|
||||||
|
|
||||||
function nextBuffer(cm) {
|
function nextPrevBuffer(cm, direction) {
|
||||||
editors[(editors.indexOf(cm) + 1) % editors.length].focus();
|
cm = editors[(editors.indexOf(cm) + direction + editors.length) % editors.length];
|
||||||
}
|
makeSectionVisible(cm);
|
||||||
function prevBuffer(cm) {
|
cm.focus();
|
||||||
editors[(editors.indexOf(cm) - 1 + editors.length) % editors.length].focus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("load", init, false);
|
window.addEventListener("load", init, false);
|
||||||
|
@ -450,20 +449,16 @@ function init() {
|
||||||
if (!params.id) { // match should be 2 - one for the whole thing, one for the parentheses
|
if (!params.id) { // match should be 2 - one for the whole thing, one for the parentheses
|
||||||
// This is an add
|
// This is an add
|
||||||
var section = {code: ""}
|
var section = {code: ""}
|
||||||
if (params.domain) {
|
for (var i in CssToProperty) {
|
||||||
section.domains = [params.domain];
|
if (params[i]) {
|
||||||
} else if (params.url) {
|
section[CssToProperty[i]] = [params[i]];
|
||||||
section.urls = [params.url];
|
}
|
||||||
} else if (params["url-prefix"]) {
|
|
||||||
section.urlPrefixes = [params["url-prefix"]];
|
|
||||||
}
|
}
|
||||||
addSection(null, section);
|
addSection(null, section);
|
||||||
// default to enabled
|
// default to enabled
|
||||||
document.getElementById("enabled").checked = true
|
document.getElementById("enabled").checked = true
|
||||||
tE("heading", "addStyleTitle");
|
tE("heading", "addStyleTitle");
|
||||||
setupGlobalSearch();
|
initHooks();
|
||||||
setCleanGlobal(null);
|
|
||||||
initTitle();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// This is an edit
|
// This is an edit
|
||||||
|
@ -479,22 +474,35 @@ function initWithStyle(style) {
|
||||||
document.getElementById("enabled").checked = style.enabled == "true";
|
document.getElementById("enabled").checked = style.enabled == "true";
|
||||||
document.getElementById("heading").innerHTML = t("editStyleHeading");
|
document.getElementById("heading").innerHTML = t("editStyleHeading");
|
||||||
// if this was done in response to an update, we need to clear existing sections
|
// 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) {
|
document.querySelectorAll("#sections > div").forEach(function(div) {
|
||||||
div.parentNode.removeChild(div);
|
div.parentNode.removeChild(div);
|
||||||
});
|
});
|
||||||
style.sections.forEach(function(section) { addSection(null, section) });
|
style.sections.forEach(function(section) {
|
||||||
setupGlobalSearch();
|
setTimeout(function() {
|
||||||
setCleanGlobal(null);
|
addSection(null, section)
|
||||||
initTitle();
|
}, 0);
|
||||||
|
});
|
||||||
|
initHooks();
|
||||||
}
|
}
|
||||||
|
|
||||||
function initTitle() {
|
function initHooks() {
|
||||||
|
document.querySelectorAll("#header .style-contributor").forEach(function(node) {
|
||||||
|
node.addEventListener("change", onChange);
|
||||||
|
node.addEventListener("input", onChange);
|
||||||
|
});
|
||||||
|
|
||||||
|
setupGlobalSearch();
|
||||||
|
setCleanGlobal();
|
||||||
|
updateTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTitle() {
|
||||||
const DIRTY_TITLE = "* $";
|
const DIRTY_TITLE = "* $";
|
||||||
|
|
||||||
var name = document.getElementById("name").defaultValue;
|
var name = document.getElementById("name").savedValue;
|
||||||
var dirty = !isCleanGlobal();
|
var clean = isCleanGlobal();
|
||||||
var title = styleId === null ? t("addStyleTitle") : t('editStyleTitle', [name]);
|
var title = styleId === null ? t("addStyleTitle") : t('editStyleTitle', [name]);
|
||||||
document.title = !dirty ? title : DIRTY_TITLE.replace("$", title);
|
document.title = clean ? title : DIRTY_TITLE.replace("$", title);
|
||||||
}
|
}
|
||||||
|
|
||||||
function validate() {
|
function validate() {
|
||||||
|
@ -503,18 +511,18 @@ function validate() {
|
||||||
return t("styleMissingName");
|
return t("styleMissingName");
|
||||||
}
|
}
|
||||||
// validate the regexps
|
// validate the regexps
|
||||||
if (Array.prototype.some.call(document.querySelectorAll(".applies-to-list"), function(list) {
|
if (document.querySelectorAll(".applies-to-list").some(function(list) {
|
||||||
return Array.prototype.some.call(list.childNodes, function(li) {
|
return list.childNodes.some(function(li) {
|
||||||
if (li.className == appliesToEverythingTemplate.className) {
|
if (li.className == appliesToEverythingTemplate.className) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var valueElement = li.querySelector("[name=applies-value]");
|
var valueElement = li.querySelector("[name=applies-value]");
|
||||||
var a = li.querySelector("[name=applies-type]").value;
|
var type = li.querySelector("[name=applies-type]").value;
|
||||||
var b = valueElement.value;
|
var value = valueElement.value;
|
||||||
if (a && b) {
|
if (type && value) {
|
||||||
if (a == "regexp") {
|
if (type == "regexp") {
|
||||||
try {
|
try {
|
||||||
new RegExp(b);
|
new RegExp(value);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
valueElement.focus();
|
valueElement.focus();
|
||||||
return true;
|
return true;
|
||||||
|
@ -547,19 +555,19 @@ function save() {
|
||||||
id: styleId,
|
id: styleId,
|
||||||
name: name,
|
name: name,
|
||||||
enabled: enabled,
|
enabled: enabled,
|
||||||
sections: getSections(),
|
sections: getSections()
|
||||||
};
|
};
|
||||||
chrome.extension.sendMessage(request, saveComplete);
|
chrome.extension.sendMessage(request, saveComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSections() {
|
function getSections() {
|
||||||
var sections = [];
|
var sections = [];
|
||||||
Array.prototype.forEach.call(document.querySelectorAll("#sections > div"), function(div) {
|
document.querySelectorAll("#sections > div").forEach(function(div) {
|
||||||
var code = div.querySelector(".code").value;
|
var meta = getMeta(div);
|
||||||
if (/^\s*$/.test(code)) {
|
var code = div.querySelector(".CodeMirror").CodeMirror.getValue();
|
||||||
|
if (/^\s*$/.test(code) && Object.keys(meta).length == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var meta = getMeta(div);
|
|
||||||
meta.code = code;
|
meta.code = code;
|
||||||
sections.push(meta);
|
sections.push(meta);
|
||||||
});
|
});
|
||||||
|
@ -567,28 +575,16 @@ function getSections() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMeta(e) {
|
function getMeta(e) {
|
||||||
var meta = {urls: [], urlPrefixes: [], domains: [], regexps: []};
|
var meta = {};
|
||||||
Array.prototype.forEach.call(e.querySelector(".applies-to-list").childNodes, function(li) {
|
e.querySelector(".applies-to-list").childNodes.forEach(function(li) {
|
||||||
if (li.className == appliesToEverythingTemplate.className) {
|
if (li.className == appliesToEverythingTemplate.className) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var a = li.querySelector("[name=applies-type]").value;
|
var type = li.querySelector("[name=applies-type]").value;
|
||||||
var b = li.querySelector("[name=applies-value]").value;
|
var value = li.querySelector("[name=applies-value]").value;
|
||||||
if (a && b) {
|
if (type && value) {
|
||||||
switch (a) {
|
var property = CssToProperty[type];
|
||||||
case "url":
|
meta[property] ? meta[property].push(value) : meta[property] = [value];
|
||||||
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;
|
return meta;
|
||||||
|
@ -596,34 +592,32 @@ function getMeta(e) {
|
||||||
|
|
||||||
function saveComplete(style) {
|
function saveComplete(style) {
|
||||||
styleId = style.id;
|
styleId = style.id;
|
||||||
setCleanGlobal(null);
|
setCleanGlobal();
|
||||||
|
|
||||||
// Go from new style URL to edit style URL
|
// Go from new style URL to edit style URL
|
||||||
if (location.href.indexOf("id=") == -1) {
|
if (location.href.indexOf("id=") == -1) {
|
||||||
// give the code above a moment before we kill the page
|
// give the code above a moment before we kill the page
|
||||||
setTimeout(function() {location.href = "edit.html?id=" + style.id;}, 200);
|
setTimeout(function() {location.href = "edit.html?id=" + style.id;}, 200);
|
||||||
} else {
|
} else {
|
||||||
initTitle();
|
updateTitle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showMozillaFormat() {
|
function showMozillaFormat() {
|
||||||
var w = window.open("data:text/plain;charset=UTF-8," + encodeURIComponent(toMozillaFormat()));
|
window.open("data:text/plain;charset=UTF-8," + encodeURIComponent(toMozillaFormat()));
|
||||||
}
|
}
|
||||||
|
|
||||||
function toMozillaFormat() {
|
function toMozillaFormat() {
|
||||||
return getSections().map(function(section) {
|
return getSections().map(function(section) {
|
||||||
if (section.urls.length == 0 && section.urlPrefixes.length == 0 && section.domains.length == 0 && section.regexps.length == 0) {
|
|
||||||
return section.code;
|
|
||||||
}
|
|
||||||
var propertyToCss = {"urls": "url", "urlPrefixes": "url-prefix", "domains": "domain", "regexps": "regexp"};
|
|
||||||
var cssMds = [];
|
var cssMds = [];
|
||||||
for (var i in propertyToCss) {
|
for (var i in propertyToCss) {
|
||||||
|
if (section[i]) {
|
||||||
cssMds = cssMds.concat(section[i].map(function (v){
|
cssMds = cssMds.concat(section[i].map(function (v){
|
||||||
return propertyToCss[i] + "(\"" + v.replace(/\\/g, "\\\\") + "\")";
|
return propertyToCss[i] + "(\"" + v.replace(/\\/g, "\\\\") + "\")";
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return "@-moz-document " + cssMds.join(", ") + " {\n" + section.code + "\n}";
|
}
|
||||||
|
return cssMds.length ? "@-moz-document " + cssMds.join(", ") + " {\n" + section.code + "\n}" : section.code;
|
||||||
}).join("\n\n");
|
}).join("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,7 +656,6 @@ chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
|
||||||
case "styleUpdated":
|
case "styleUpdated":
|
||||||
if (styleId == request.id) {
|
if (styleId == request.id) {
|
||||||
initWithStyle(request.style);
|
initWithStyle(request.style);
|
||||||
dirty = false;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "styleDeleted":
|
case "styleDeleted":
|
||||||
|
|
16
manage.html
16
manage.html
|
@ -3,7 +3,7 @@
|
||||||
<title></title>
|
<title></title>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
font: 12px arial,sans-serif;
|
font: 12px arial,sans-serif;
|
||||||
}
|
}
|
||||||
a, a:visited {
|
a, a:visited {
|
||||||
|
@ -17,12 +17,12 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0px;
|
top: 0;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
border-right: 1px dashed #AAA;
|
border-right: 1px dashed #AAA;
|
||||||
}
|
}
|
||||||
#header {
|
#header {
|
||||||
-webkit-box-shadow: 0px 0px 50px -18px black;
|
-webkit-box-shadow: 0 0 50px -18px black;
|
||||||
}
|
}
|
||||||
#installed {
|
#installed {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
}
|
}
|
||||||
[style-id] {
|
[style-id] {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
padding: 0px 15px;
|
padding: 0 15px;
|
||||||
}
|
}
|
||||||
[style-id] {
|
[style-id] {
|
||||||
border-top: 2px solid gray;
|
border-top: 2px solid gray;
|
||||||
|
@ -102,11 +102,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#installed {
|
#installed {
|
||||||
margin-left: 0px;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[style-id] {
|
[style-id] {
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,6 +140,10 @@
|
||||||
<div><input id="manage.onlyEdited" type="checkbox"><label id="manage.onlyEdited-label" for="manage.onlyEdited"></label></div>
|
<div><input id="manage.onlyEdited" type="checkbox"><label id="manage.onlyEdited-label" for="manage.onlyEdited"></label></div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<p><button id="check-all-updates"></button></p>
|
<p><button id="check-all-updates"></button></p>
|
||||||
|
<p>
|
||||||
|
<button id="apply-all-updates" class="hidden"></button>
|
||||||
|
<span id="update-all-no-updates" class="hidden"></span>
|
||||||
|
</p>
|
||||||
<p><a href="edit.html"><button id="add-style-label"></button></a></p>
|
<p><a href="edit.html"><button id="add-style-label"></button></a></p>
|
||||||
<div id="options">
|
<div id="options">
|
||||||
<h2 id="options-heading"></h2>
|
<h2 id="options-heading"></h2>
|
||||||
|
|
86
manage.js
86
manage.js
|
@ -93,6 +93,31 @@ 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) {
|
||||||
|
if (!event.altKey) {
|
||||||
|
var left = event.button == 0, middle = event.button == 1,
|
||||||
|
shift = event.shiftKey, ctrl = event.ctrlKey;
|
||||||
|
var openWindow = left && shift && !ctrl;
|
||||||
|
var openBackgroundTab = (middle && !shift) || (left && ctrl && !shift);
|
||||||
|
var openForegroundTab = (middle && shift) || (left && ctrl && shift);
|
||||||
|
if (openWindow || openBackgroundTab || openForegroundTab) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
var url = event.target.href || event.target.parentNode.href;
|
||||||
|
if (openWindow) {
|
||||||
|
var options = prefs.getPref('windowPosition', {});
|
||||||
|
options.url = url;
|
||||||
|
chrome.windows.create(options);
|
||||||
|
} else {
|
||||||
|
chrome.extension.sendMessage({
|
||||||
|
method: "openURL",
|
||||||
|
url: url,
|
||||||
|
active: openForegroundTab
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
e.querySelector(".enable").addEventListener("click", function(event) { enable(event, true); }, false);
|
e.querySelector(".enable").addEventListener("click", function(event) { enable(event, true); }, false);
|
||||||
e.querySelector(".disable").addEventListener("click", function(event) { enable(event, false); }, 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);
|
||||||
|
@ -163,11 +188,52 @@ function doCheckUpdate(event) {
|
||||||
checkUpdate(getStyleElement(event));
|
checkUpdate(getStyleElement(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkUpdateAll() {
|
function applyUpdateAll() {
|
||||||
Array.prototype.forEach.call(document.querySelectorAll("[style-update-url]"), checkUpdate);
|
var btnApply = document.getElementById("apply-all-updates");
|
||||||
|
btnApply.disabled = true;
|
||||||
|
setTimeout(function() {
|
||||||
|
btnApply.style.display = "none";
|
||||||
|
btnApply.disabled = false;
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
Array.prototype.forEach.call(document.querySelectorAll(".can-update .update"), function(button) {
|
||||||
|
button.click();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkUpdate(element) {
|
function checkUpdateAll() {
|
||||||
|
var btnCheck = document.getElementById("check-all-updates");
|
||||||
|
var btnApply = document.getElementById("apply-all-updates");
|
||||||
|
var noUpdates = document.getElementById("update-all-no-updates");
|
||||||
|
|
||||||
|
btnCheck.disabled = true;
|
||||||
|
btnApply.classList.add("hidden");
|
||||||
|
noUpdates.classList.add("hidden");
|
||||||
|
|
||||||
|
var elements = document.querySelectorAll("[style-update-url]");
|
||||||
|
var toCheckCount = elements.length;
|
||||||
|
var updatableCount = 0;
|
||||||
|
Array.prototype.forEach.call(elements, function(element) {
|
||||||
|
checkUpdate(element, function(success) {
|
||||||
|
if (success) {
|
||||||
|
++updatableCount;
|
||||||
|
}
|
||||||
|
if (--toCheckCount == 0) {
|
||||||
|
btnCheck.disabled = false;
|
||||||
|
if (updatableCount) {
|
||||||
|
btnApply.classList.remove("hidden");
|
||||||
|
} else {
|
||||||
|
noUpdates.classList.remove("hidden");
|
||||||
|
setTimeout(function() {
|
||||||
|
noUpdates.classList.add("hidden");
|
||||||
|
}, 10000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkUpdate(element, callback) {
|
||||||
element.querySelector(".update-note").innerHTML = t('checkingForUpdate');
|
element.querySelector(".update-note").innerHTML = t('checkingForUpdate');
|
||||||
element.className = element.className.replace("checking-update", "").replace("no-update", "").replace("can-update", "") + " checking-update";
|
element.className = element.className.replace("checking-update", "").replace("no-update", "").replace("can-update", "") + " checking-update";
|
||||||
var id = element.getAttribute("style-id");
|
var id = element.getAttribute("style-id");
|
||||||
|
@ -178,10 +244,15 @@ function checkUpdate(element) {
|
||||||
function handleSuccess(forceUpdate, serverJson) {
|
function handleSuccess(forceUpdate, serverJson) {
|
||||||
chrome.extension.sendMessage({method: "getStyles", id: id}, function(styles) {
|
chrome.extension.sendMessage({method: "getStyles", id: id}, function(styles) {
|
||||||
var style = styles[0];
|
var style = styles[0];
|
||||||
|
var needsUpdate = false;
|
||||||
if (!forceUpdate && codeIsEqual(style.sections, serverJson.sections)) {
|
if (!forceUpdate && codeIsEqual(style.sections, serverJson.sections)) {
|
||||||
handleNeedsUpdate("no", id, serverJson);
|
handleNeedsUpdate("no", id, serverJson);
|
||||||
} else {
|
} else {
|
||||||
handleNeedsUpdate("yes", id, serverJson);
|
handleNeedsUpdate("yes", id, serverJson);
|
||||||
|
needsUpdate = true;
|
||||||
|
}
|
||||||
|
if (callback) {
|
||||||
|
callback(needsUpdate);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -192,6 +263,9 @@ function checkUpdate(element) {
|
||||||
} else {
|
} else {
|
||||||
handleNeedsUpdate(t('updateCheckFailBadResponseCode', [status]), id, null);
|
handleNeedsUpdate(t('updateCheckFailBadResponseCode', [status]), id, null);
|
||||||
}
|
}
|
||||||
|
if (callback) {
|
||||||
|
callback(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!md5Url || !originalMd5) {
|
if (!md5Url || !originalMd5) {
|
||||||
|
@ -203,6 +277,9 @@ function checkUpdate(element) {
|
||||||
checkUpdateFullCode(url, true, handleSuccess, handleFailure);
|
checkUpdateFullCode(url, true, handleSuccess, handleFailure);
|
||||||
} else {
|
} else {
|
||||||
handleNeedsUpdate("no", id, null);
|
handleNeedsUpdate("no", id, null);
|
||||||
|
if (callback) {
|
||||||
|
callback(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, handleFailure);
|
}, handleFailure);
|
||||||
}
|
}
|
||||||
|
@ -342,6 +419,8 @@ document.title = t("manageTitle");
|
||||||
tE("manage-heading", "manageHeading");
|
tE("manage-heading", "manageHeading");
|
||||||
tE("manage-text", "manageText", null, false);
|
tE("manage-text", "manageText", null, false);
|
||||||
tE("check-all-updates", "checkAllUpdates");
|
tE("check-all-updates", "checkAllUpdates");
|
||||||
|
tE("apply-all-updates", "applyAllUpdates");
|
||||||
|
tE("update-all-no-updates", "updateAllCheckSucceededNoUpdate");
|
||||||
tE("add-style-label", "addStyleLabel");
|
tE("add-style-label", "addStyleLabel");
|
||||||
tE("options-heading", "optionsHeading");
|
tE("options-heading", "optionsHeading");
|
||||||
tE("show-badge-label", "prefShowBadge");
|
tE("show-badge-label", "prefShowBadge");
|
||||||
|
@ -351,6 +430,7 @@ tE("filters", "manageFilters");
|
||||||
tE("stylesFirst-label", "popupStylesFirst");
|
tE("stylesFirst-label", "popupStylesFirst");
|
||||||
|
|
||||||
document.getElementById("check-all-updates").addEventListener("click", checkUpdateAll, false);
|
document.getElementById("check-all-updates").addEventListener("click", checkUpdateAll, false);
|
||||||
|
document.getElementById("apply-all-updates").addEventListener("click", applyUpdateAll, false);
|
||||||
|
|
||||||
function onFilterChange (className, event) {
|
function onFilterChange (className, event) {
|
||||||
var container = document.getElementById("installed"),
|
var container = document.getElementById("installed"),
|
||||||
|
|
10
popup.js
10
popup.js
|
@ -156,14 +156,8 @@ function openLinkInTabOrWindow(event) {
|
||||||
|
|
||||||
function openLink(event) {
|
function openLink(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
chrome.tabs.query({currentWindow: true, active: true}, function (tabs) {
|
chrome.extension.sendMessage({method: "openURL", url: event.target.href});
|
||||||
if (tabs && tabs.length && tabs[0].url.match(/^chrome:\/\/newtab\/?$/)) {
|
close();
|
||||||
chrome.tabs.update({url: event.target.href});
|
|
||||||
close(); // close the popup
|
|
||||||
} else {
|
|
||||||
chrome.tabs.create({url: event.target.href});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleUpdate(style) {
|
function handleUpdate(style) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user