Merge pull request #130 from tophf/global-replace
Editor: global replace
This commit is contained in:
commit
fd91bba559
|
@ -100,6 +100,18 @@
|
||||||
"message": "Theme",
|
"message": "Theme",
|
||||||
"description": "Label for the style editor's CSS theme."
|
"description": "Label for the style editor's CSS theme."
|
||||||
},
|
},
|
||||||
|
"confirmNo": {
|
||||||
|
"message": "No",
|
||||||
|
"description": "'No' button in a confirm dialog"
|
||||||
|
},
|
||||||
|
"confirmStop": {
|
||||||
|
"message": "Stop",
|
||||||
|
"description": "'Stop' button in a confirm dialog"
|
||||||
|
},
|
||||||
|
"confirmYes": {
|
||||||
|
"message": "Yes",
|
||||||
|
"description": "'Yes' button in a confirm dialog"
|
||||||
|
},
|
||||||
"dbError": {
|
"dbError": {
|
||||||
"message": "An error has occurred using the Stylish database. Would you like to visit a web page with possible solutions?",
|
"message": "An error has occurred using the Stylish database. Would you like to visit a web page with possible solutions?",
|
||||||
"description": "Prompt when a DB error is encountered"
|
"description": "Prompt when a DB error is encountered"
|
||||||
|
@ -229,6 +241,18 @@
|
||||||
"message": "Show number of styles active for the current site on the toolbar button",
|
"message": "Show number of styles active for the current site on the toolbar button",
|
||||||
"description": "Label for the checkbox controlling toolbar badge text."
|
"description": "Label for the checkbox controlling toolbar badge text."
|
||||||
},
|
},
|
||||||
|
"replace": {
|
||||||
|
"message": "Replace",
|
||||||
|
"description": "Label before the replace input field in the editor shown on Ctrl-H"
|
||||||
|
},
|
||||||
|
"replaceAll": {
|
||||||
|
"message": "Replace all",
|
||||||
|
"description": "Label before the replace input field in the editor shown on 'replaceAll' hotkey"
|
||||||
|
},
|
||||||
|
"replaceWith": {
|
||||||
|
"message": "Replace with",
|
||||||
|
"description": "Label before the replace-with input field in the editor shown on Ctrl-H etc."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"message": "Search",
|
"message": "Search",
|
||||||
"description": "Label before the search input field in the editor shown on Ctrl-F"
|
"description": "Label before the search input field in the editor shown on Ctrl-F"
|
||||||
|
|
80
edit.html
80
edit.html
|
@ -125,7 +125,7 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
#sections > div > button:not(:first-of-type) {
|
#sections > div > button:not(:first-of-type) {
|
||||||
margin-left: 0.4rem;
|
margin-left: 0.2rem;
|
||||||
}
|
}
|
||||||
.dirty > label::before {
|
.dirty > label::before {
|
||||||
content: "*";
|
content: "*";
|
||||||
|
@ -153,19 +153,28 @@
|
||||||
.CodeMirror-vscrollbar {
|
.CodeMirror-vscrollbar {
|
||||||
margin-bottom: 8px; /* make space for resize-grip */
|
margin-bottom: 8px; /* make space for resize-grip */
|
||||||
}
|
}
|
||||||
.CodeMirror-search-field, .CodeMirror-jump-field {
|
.CodeMirror-dialog {
|
||||||
-webkit-animation: highlight 3s ease-out;
|
-webkit-animation: highlight 3s ease-out;
|
||||||
}
|
}
|
||||||
.CodeMirror-focused {
|
.CodeMirror-focused {
|
||||||
outline: -webkit-focus-ring-color auto 5px;
|
outline: -webkit-focus-ring-color auto 5px;
|
||||||
outline-offset: -2px;
|
outline-offset: -2px;
|
||||||
}
|
}
|
||||||
|
.CodeMirror-search-field {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
.CodeMirror-jump-field {
|
||||||
|
width: 5em;
|
||||||
|
}
|
||||||
|
.CodeMirror-search-hint {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
@-webkit-keyframes highlight {
|
@-webkit-keyframes highlight {
|
||||||
from {
|
from {
|
||||||
background-color: #ff9;
|
background-color: #ff9;
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
background-color: transparent;
|
background-color: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.resize-grip {
|
.resize-grip {
|
||||||
|
@ -434,6 +443,71 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<link id="cm-theme" rel="stylesheet">
|
<link id="cm-theme" rel="stylesheet">
|
||||||
|
|
||||||
|
<template data-id="appliesTo">
|
||||||
|
<li>
|
||||||
|
<select name="applies-type" class="applies-type style-contributor">
|
||||||
|
<option value="url" i18n-text="appliesUrlOption"></option>
|
||||||
|
<option value="url-prefix" i18n-text="appliesUrlPrefixOption"></option>
|
||||||
|
<option value="domain" i18n-text="appliesDomainOption"></option>
|
||||||
|
<option value="regexp" i18n-text="appliesRegexpOption"></option>
|
||||||
|
</select>
|
||||||
|
<input name="applies-value" class="applies-value style-contributor">
|
||||||
|
<button class="remove-applies-to" i18n-text="appliesRemove"></button>
|
||||||
|
<button class="add-applies-to" i18n-text="appliesAdd"></button>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
<template data-id="appliesToEverything">
|
||||||
|
<li class="applies-to-everything" i18n-html="appliesToEverything">
|
||||||
|
<button class="add-applies-to" i18n-text="appliesSpecify"></button>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
<template data-id="section">
|
||||||
|
<div>
|
||||||
|
<label i18n-text="sectionCode"></label>
|
||||||
|
<textarea class="code"></textarea>
|
||||||
|
<br>
|
||||||
|
<div class="applies-to">
|
||||||
|
<label i18n-text="appliesLabel">
|
||||||
|
<img class="applies-to-help" src="help.png" i18n-alt="helpAlt">
|
||||||
|
</label>
|
||||||
|
<ul class="applies-to-list"></ul>
|
||||||
|
</div>
|
||||||
|
<button class="remove-section" i18n-text="sectionRemove"></button>
|
||||||
|
<button class="add-section" i18n-text="sectionAdd"></button>
|
||||||
|
<button class="beautify-section" i18n-text="styleBeautify"></button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template data-id="find">
|
||||||
|
<span i18n-text="search">: <input type="text" class="CodeMirror-search-field">
|
||||||
|
<span class="CodeMirror-search-hint">(<span i18n-text="searchRegexp"></span>)</span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template data-id="replace">
|
||||||
|
<span i18n-text="replace">: <input type="text" class="CodeMirror-search-field">
|
||||||
|
<span class="CodeMirror-search-hint">(<span i18n-text="searchRegexp"></span>)</span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template data-id="replaceAll">
|
||||||
|
<span i18n-text="replaceAll">: <input type="text" class="CodeMirror-search-field">
|
||||||
|
<span class="CodeMirror-search-hint">(<span i18n-text="searchRegexp"></span>)</span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template data-id="replaceWith">
|
||||||
|
<span i18n-text="replaceWith">: <input type="text" class="CodeMirror-search-field">
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template data-id="replaceConfirm">
|
||||||
|
<span i18n-text="replace">?
|
||||||
|
<button i18n-text="confirmYes"></button>
|
||||||
|
<button i18n-text="confirmNo"></button>
|
||||||
|
<button i18n-text="confirmStop"></button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template data-id="jumpToLine">
|
||||||
|
<span i18n-text="editGotoLine">: <input class="CodeMirror-jump-field" type="text"></span>
|
||||||
|
</template>
|
||||||
|
|
||||||
<script src="storage.js"></script>
|
<script src="storage.js"></script>
|
||||||
<script src="messaging.js"></script>
|
<script src="messaging.js"></script>
|
||||||
<script src="localization.js"></script>
|
<script src="localization.js"></script>
|
||||||
|
|
199
edit.js
199
edit.js
|
@ -10,49 +10,6 @@ var useHistoryBack; // use browser history back when "back to manage" is click
|
||||||
var propertyToCss = {urls: "url", urlPrefixes: "url-prefix", domains: "domain", regexps: "regexp"};
|
var propertyToCss = {urls: "url", urlPrefixes: "url-prefix", domains: "domain", regexps: "regexp"};
|
||||||
var CssToProperty = {"url": "urls", "url-prefix": "urlPrefixes", "domain": "domains", "regexp": "regexps"};
|
var CssToProperty = {"url": "urls", "url-prefix": "urlPrefixes", "domain": "domains", "regexp": "regexps"};
|
||||||
|
|
||||||
// templates
|
|
||||||
var appliesToTemplate = tHTML('\
|
|
||||||
<li>\
|
|
||||||
<select name="applies-type" class="applies-type style-contributor">\
|
|
||||||
<option value="url" i18n-text="appliesUrlOption"></option>\
|
|
||||||
<option value="url-prefix" i18n-text="appliesUrlPrefixOption"></option>\
|
|
||||||
<option value="domain" i18n-text="appliesDomainOption"></option>\
|
|
||||||
<option value="regexp" i18n-text="appliesRegexpOption"></option>\
|
|
||||||
</select>\
|
|
||||||
<input name="applies-value" class="applies-value style-contributor">\
|
|
||||||
<button class="remove-applies-to" i18n-text="appliesRemove"></button>\
|
|
||||||
<button class="add-applies-to" i18n-text="appliesAdd"></button>\
|
|
||||||
</li>\
|
|
||||||
');
|
|
||||||
|
|
||||||
var appliesToEverythingTemplate = tHTML('\
|
|
||||||
<li class="applies-to-everything" i18n-html="appliesToEverything")>\
|
|
||||||
<button class="add-applies-to" i18n-text="appliesSpecify"></button>\
|
|
||||||
</li>\
|
|
||||||
');
|
|
||||||
|
|
||||||
var sectionTemplate = tHTML('\
|
|
||||||
<div>\
|
|
||||||
<label i18n-text="sectionCode"></label>\
|
|
||||||
<textarea class="code"></textarea>\
|
|
||||||
<br>\
|
|
||||||
<div class="applies-to">\
|
|
||||||
<label i18n-text="appliesLabel">\
|
|
||||||
<img class="applies-to-help" src="help.png" i18n-alt="helpAlt">\
|
|
||||||
</label>\
|
|
||||||
<ul class="applies-to-list"></ul>\
|
|
||||||
</div>\
|
|
||||||
<button class="remove-section" i18n-text="sectionRemove"></button>\
|
|
||||||
<button class="add-section" i18n-text="sectionAdd"></button>\
|
|
||||||
<button class="beautify-section" i18n-text="styleBeautify"></button>\
|
|
||||||
</div>\
|
|
||||||
');
|
|
||||||
|
|
||||||
var findTemplate = t("search") + ': <input type="text" style="width: 10em" class="CodeMirror-search-field"/> ' +
|
|
||||||
'<span style="color: #888" class="CodeMirror-search-hint">(' + t("searchRegexp") + ')</span>';
|
|
||||||
|
|
||||||
var jumpToLineTemplate = t('editGotoLine') + ': <input class="CodeMirror-jump-field" type="text" style="width: 5em"/>';
|
|
||||||
|
|
||||||
// make querySelectorAll enumeration code readable
|
// make querySelectorAll enumeration code readable
|
||||||
["forEach", "some", "indexOf"].forEach(function(method) {
|
["forEach", "some", "indexOf"].forEach(function(method) {
|
||||||
NodeList.prototype[method]= Array.prototype[method];
|
NodeList.prototype[method]= Array.prototype[method];
|
||||||
|
@ -61,6 +18,12 @@ var jumpToLineTemplate = t('editGotoLine') + ': <input class="CodeMirror-jump-fi
|
||||||
// Chrome pre-34
|
// Chrome pre-34
|
||||||
Element.prototype.matches = Element.prototype.matches || Element.prototype.webkitMatchesSelector;
|
Element.prototype.matches = Element.prototype.matches || Element.prototype.webkitMatchesSelector;
|
||||||
|
|
||||||
|
Array.prototype.rotate = function(amount) { // negative amount == rotate left
|
||||||
|
var r = this.slice(-amount, this.length);
|
||||||
|
Array.prototype.push.apply(r, this.slice(0, this.length - r.length));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
// reroute handling to nearest editor when keypress resolves to one of these commands
|
// reroute handling to nearest editor when keypress resolves to one of these commands
|
||||||
var hotkeyRerouter = {
|
var hotkeyRerouter = {
|
||||||
commands: {
|
commands: {
|
||||||
|
@ -476,25 +439,25 @@ function addAppliesTo(list, name, value) {
|
||||||
}
|
}
|
||||||
var e;
|
var e;
|
||||||
if (name && value) {
|
if (name && value) {
|
||||||
e = appliesToTemplate.cloneNode(true);
|
e = template.appliesTo.cloneNode(true);
|
||||||
e.querySelector("[name=applies-type]").value = name;
|
e.querySelector("[name=applies-type]").value = name;
|
||||||
e.querySelector("[name=applies-value]").value = value;
|
e.querySelector("[name=applies-value]").value = value;
|
||||||
e.querySelector(".remove-applies-to").addEventListener("click", removeAppliesTo, false);
|
e.querySelector(".remove-applies-to").addEventListener("click", removeAppliesTo, false);
|
||||||
} else if (showingEverything || list.hasChildNodes()) {
|
} else if (showingEverything || list.hasChildNodes()) {
|
||||||
e = appliesToTemplate.cloneNode(true);
|
e = template.appliesTo.cloneNode(true);
|
||||||
if (list.hasChildNodes()) {
|
if (list.hasChildNodes()) {
|
||||||
e.querySelector("[name=applies-type]").value = list.querySelector("li:last-child [name='applies-type']").value;
|
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(".remove-applies-to").addEventListener("click", removeAppliesTo, false);
|
||||||
} else {
|
} else {
|
||||||
e = appliesToEverythingTemplate.cloneNode(true);
|
e = template.appliesToEverything.cloneNode(true);
|
||||||
}
|
}
|
||||||
e.querySelector(".add-applies-to").addEventListener("click", function() {addAppliesTo(this.parentNode.parentNode)}, false);
|
e.querySelector(".add-applies-to").addEventListener("click", function() {addAppliesTo(this.parentNode.parentNode)}, false);
|
||||||
list.appendChild(e);
|
list.appendChild(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSection(event, section) {
|
function addSection(event, section) {
|
||||||
var div = sectionTemplate.cloneNode(true);
|
var div = template.section.cloneNode(true);
|
||||||
div.querySelector(".applies-to-help").addEventListener("click", showAppliesToHelp, false);
|
div.querySelector(".applies-to-help").addEventListener("click", showAppliesToHelp, false);
|
||||||
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);
|
||||||
|
@ -589,8 +552,11 @@ function setupGlobalSearch() {
|
||||||
var originalCommand = {
|
var originalCommand = {
|
||||||
find: CodeMirror.commands.find,
|
find: CodeMirror.commands.find,
|
||||||
findNext: CodeMirror.commands.findNext,
|
findNext: CodeMirror.commands.findNext,
|
||||||
findPrev: CodeMirror.commands.findPrev
|
findPrev: CodeMirror.commands.findPrev,
|
||||||
|
replace: CodeMirror.commands.replace
|
||||||
}
|
}
|
||||||
|
var originalOpenDialog = CodeMirror.prototype.openDialog;
|
||||||
|
var originalOpenConfirm = CodeMirror.prototype.openConfirm;
|
||||||
|
|
||||||
var curState; // cm.state.search for last used 'find'
|
var curState; // cm.state.search for last used 'find'
|
||||||
|
|
||||||
|
@ -614,33 +580,43 @@ function setupGlobalSearch() {
|
||||||
return cm.state.search;
|
return cm.state.search;
|
||||||
}
|
}
|
||||||
|
|
||||||
function find(activeCM) {
|
// temporarily overrides the original openDialog with the provided template's innerHTML
|
||||||
|
function customizeOpenDialog(cm, template, callback) {
|
||||||
|
cm.openDialog = function(tmpl, cb, opt) {
|
||||||
|
// invoke 'callback' and bind 'this' to the original callback
|
||||||
|
originalOpenDialog.call(cm, template.innerHTML, callback.bind(cb), opt);
|
||||||
|
};
|
||||||
|
setTimeout(function() { cm.openDialog = originalOpenDialog; }, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function focusClosestCM(activeCM) {
|
||||||
editors.lastActive = activeCM;
|
editors.lastActive = activeCM;
|
||||||
var cm = getEditorInSight();
|
var cm = getEditorInSight();
|
||||||
if (cm != activeCM) {
|
if (cm != activeCM) {
|
||||||
cm.focus();
|
cm.focus();
|
||||||
activeCM = cm;
|
|
||||||
}
|
}
|
||||||
var originalOpenDialog = activeCM.openDialog;
|
return cm;
|
||||||
activeCM.openDialog = function(template, callback, options) {
|
|
||||||
originalOpenDialog.call(activeCM, findTemplate, function(query) {
|
}
|
||||||
activeCM.openDialog = originalOpenDialog;
|
|
||||||
callback(query);
|
function find(activeCM) {
|
||||||
curState = activeCM.state.search;
|
activeCM = focusClosestCM(activeCM);
|
||||||
if (editors.length == 1 || !curState.query) {
|
customizeOpenDialog(activeCM, template.find, function(query) {
|
||||||
return;
|
this(query);
|
||||||
|
curState = activeCM.state.search;
|
||||||
|
if (editors.length == 1 || !curState.query) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
editors.forEach(function(cm) {
|
||||||
|
if (cm != activeCM) {
|
||||||
|
cm.execCommand("clearSearch");
|
||||||
|
updateState(cm, curState);
|
||||||
}
|
}
|
||||||
editors.forEach(function(cm) {
|
});
|
||||||
if (cm != activeCM) {
|
if (CodeMirror.cmpPos(curState.posFrom, curState.posTo) == 0) {
|
||||||
cm.execCommand("clearSearch");
|
findNext(activeCM);
|
||||||
updateState(cm, curState);
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
if (CodeMirror.cmpPos(curState.posFrom, curState.posTo) == 0) {
|
|
||||||
findNext(activeCM);
|
|
||||||
}
|
|
||||||
}, options);
|
|
||||||
}
|
|
||||||
originalCommand.find(activeCM);
|
originalCommand.find(activeCM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -714,14 +690,90 @@ function setupGlobalSearch() {
|
||||||
findNext(cm, true);
|
findNext(cm, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function replace(activeCM, all) {
|
||||||
|
var queue, query, replacement;
|
||||||
|
activeCM = focusClosestCM(activeCM);
|
||||||
|
customizeOpenDialog(activeCM, template[all ? "replaceAll" : "replace"], function(txt) {
|
||||||
|
query = txt;
|
||||||
|
customizeOpenDialog(activeCM, template.replaceWith, function(txt) {
|
||||||
|
replacement = txt;
|
||||||
|
queue = editors.rotate(-editors.indexOf(activeCM));
|
||||||
|
all ? editors.forEach(doReplace) : doReplace();
|
||||||
|
});
|
||||||
|
this(query);
|
||||||
|
});
|
||||||
|
originalCommand.replace(activeCM, all);
|
||||||
|
|
||||||
|
function doReplace() {
|
||||||
|
var cm = queue.shift();
|
||||||
|
if (!cm) {
|
||||||
|
if (!all) {
|
||||||
|
editors.lastActive.focus();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// hide the first two dialogs (replace, replaceWith)
|
||||||
|
cm.openDialog = function(tmpl, callback, opt) {
|
||||||
|
cm.openDialog = function(tmpl, callback, opt) {
|
||||||
|
cm.openDialog = originalOpenDialog;
|
||||||
|
if (all) {
|
||||||
|
callback(replacement);
|
||||||
|
} else {
|
||||||
|
doConfirm(cm);
|
||||||
|
callback(replacement);
|
||||||
|
if (!cm.getWrapperElement().querySelector(".CodeMirror-dialog")) {
|
||||||
|
// no dialog == nothing found in the current CM, move to the next
|
||||||
|
doReplace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
callback(query);
|
||||||
|
};
|
||||||
|
originalCommand.replace(cm, all);
|
||||||
|
}
|
||||||
|
function doConfirm(cm) {
|
||||||
|
var wrapAround = false;
|
||||||
|
var origPos = cm.getCursor();
|
||||||
|
cm.openConfirm = function overrideConfirm(tmpl, callbacks, opt) {
|
||||||
|
var ovrCallbacks = callbacks.map(function(callback) {
|
||||||
|
return function() {
|
||||||
|
makeSectionVisible(cm);
|
||||||
|
cm.openConfirm = overrideConfirm;
|
||||||
|
setTimeout(function() { cm.openConfirm = originalOpenConfirm; }, 0);
|
||||||
|
|
||||||
|
var pos = cm.getCursor();
|
||||||
|
callback();
|
||||||
|
var cmp = CodeMirror.cmpPos(cm.getCursor(), pos);
|
||||||
|
wrapAround |= cmp <= 0;
|
||||||
|
|
||||||
|
var dlg = cm.getWrapperElement().querySelector(".CodeMirror-dialog");
|
||||||
|
if (!dlg || cmp == 0 || wrapAround && CodeMirror.cmpPos(cm.getCursor(), origPos) >= 0) {
|
||||||
|
if (dlg) {
|
||||||
|
dlg.remove();
|
||||||
|
}
|
||||||
|
doReplace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
originalOpenConfirm.call(cm, template.replaceConfirm.innerHTML, ovrCallbacks, opt);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function replaceAll(cm) {
|
||||||
|
replace(cm, true);
|
||||||
|
}
|
||||||
|
|
||||||
CodeMirror.commands.find = find;
|
CodeMirror.commands.find = find;
|
||||||
CodeMirror.commands.findNext = findNext;
|
CodeMirror.commands.findNext = findNext;
|
||||||
CodeMirror.commands.findPrev = findPrev;
|
CodeMirror.commands.findPrev = findPrev;
|
||||||
|
CodeMirror.commands.replace = replace;
|
||||||
|
CodeMirror.commands.replaceAll = replaceAll;
|
||||||
}
|
}
|
||||||
|
|
||||||
function jumpToLine(cm) {
|
function jumpToLine(cm) {
|
||||||
var cur = cm.getCursor();
|
var cur = cm.getCursor();
|
||||||
cm.openDialog(jumpToLineTemplate, function(str) {
|
cm.openDialog(template.jumpToLine.innerHTML, function(str) {
|
||||||
var m = str.match(/^\s*(\d+)(?:\s*:\s*(\d+))?\s*$/);
|
var m = str.match(/^\s*(\d+)(?:\s*:\s*(\d+))?\s*$/);
|
||||||
if (m) {
|
if (m) {
|
||||||
cm.setCursor(m[1] - 1, m[2] ? m[2] - 1 : cur.ch);
|
cm.setCursor(m[1] - 1, m[2] ? m[2] - 1 : cur.ch);
|
||||||
|
@ -961,6 +1013,7 @@ function init() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// This is an edit
|
// This is an edit
|
||||||
|
tE("heading", "editStyleHeading", null, false);
|
||||||
requestStyle();
|
requestStyle();
|
||||||
function requestStyle() {
|
function requestStyle() {
|
||||||
chrome.extension.sendMessage({method: "getStyles", id: params.id}, function callback(styles) {
|
chrome.extension.sendMessage({method: "getStyles", id: params.id}, function callback(styles) {
|
||||||
|
@ -979,7 +1032,6 @@ function initWithStyle(style) {
|
||||||
document.getElementById("name").value = style.name;
|
document.getElementById("name").value = style.name;
|
||||||
document.getElementById("enabled").checked = style.enabled == "true";
|
document.getElementById("enabled").checked = style.enabled == "true";
|
||||||
document.getElementById("url").href = style.url;
|
document.getElementById("url").href = style.url;
|
||||||
tE("heading", "editStyleHeading", null, false);
|
|
||||||
// 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
|
||||||
document.querySelectorAll("#sections > div").forEach(function(div) {
|
document.querySelectorAll("#sections > div").forEach(function(div) {
|
||||||
div.parentNode.removeChild(div);
|
div.parentNode.removeChild(div);
|
||||||
|
@ -1087,7 +1139,7 @@ function validate() {
|
||||||
// validate the regexps
|
// validate the regexps
|
||||||
if (document.querySelectorAll(".applies-to-list").some(function(list) {
|
if (document.querySelectorAll(".applies-to-list").some(function(list) {
|
||||||
return list.childNodes.some(function(li) {
|
return list.childNodes.some(function(li) {
|
||||||
if (li.className == appliesToEverythingTemplate.className) {
|
if (li.className == template.appliesToEverything.className) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var valueElement = li.querySelector("[name=applies-value]");
|
var valueElement = li.querySelector("[name=applies-value]");
|
||||||
|
@ -1153,7 +1205,7 @@ function getSections() {
|
||||||
function getMeta(e) {
|
function getMeta(e) {
|
||||||
var meta = {};
|
var meta = {};
|
||||||
e.querySelector(".applies-to-list").childNodes.forEach(function(li) {
|
e.querySelector(".applies-to-list").childNodes.forEach(function(li) {
|
||||||
if (li.className == appliesToEverythingTemplate.className) {
|
if (li.className == template.appliesToEverything.className) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var type = li.querySelector("[name=applies-type]").value;
|
var type = li.querySelector("[name=applies-type]").value;
|
||||||
|
@ -1173,6 +1225,7 @@ function saveComplete(style) {
|
||||||
// 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) {
|
||||||
history.replaceState({}, document.title, "edit.html?id=" + style.id);
|
history.replaceState({}, document.title, "edit.html?id=" + style.id);
|
||||||
|
tE("heading", "editStyleHeading", null, false);
|
||||||
}
|
}
|
||||||
updateTitle();
|
updateTitle();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
var template = {};
|
||||||
tDocLoader();
|
tDocLoader();
|
||||||
|
|
||||||
function t(key, params) {
|
function t(key, params) {
|
||||||
|
@ -35,6 +36,11 @@ function tNodeList(nodes) {
|
||||||
if (node.nodeType != 1) { // not an ELEMENT_NODE
|
if (node.nodeType != 1) { // not an ELEMENT_NODE
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (node.localName == "template") {
|
||||||
|
tNodeList(node.content.querySelectorAll("*"));
|
||||||
|
template[node.dataset.id] = node.content.firstElementChild;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for (var a = node.attributes.length - 1; a >= 0; a--) {
|
for (var a = node.attributes.length - 1; a >= 0; a--) {
|
||||||
var attr = node.attributes[a];
|
var attr = node.attributes[a];
|
||||||
var name = attr.nodeName;
|
var name = attr.nodeName;
|
||||||
|
|
20
manage.html
20
manage.html
|
@ -46,9 +46,6 @@
|
||||||
.applies-to, .actions {
|
.applies-to, .actions {
|
||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
}
|
}
|
||||||
.actions > * {
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
.applies-to-extra {
|
.applies-to-extra {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
@ -129,6 +126,23 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<template data-id="style">
|
||||||
|
<div>
|
||||||
|
<h2 class="style-name"></h2>
|
||||||
|
<p class="applies-to"></p>
|
||||||
|
<p class="actions">
|
||||||
|
<a class="style-edit-link" href="edit.html?id="><button i18n-text="editStyleLabel"></button></a>
|
||||||
|
<button class="enable" i18n-text="enableStyleLabel"></button>
|
||||||
|
<button class="disable" i18n-text="disableStyleLabel"></button>
|
||||||
|
<button class="delete" i18n-text="deleteStyleLabel"></button>
|
||||||
|
<button class="check-update" i18n-text="checkForUpdate"></button>
|
||||||
|
<button class="update" i18n-text="installUpdate"></button>
|
||||||
|
<span class="update-note"></span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<script src="localization.js"></script>
|
<script src="localization.js"></script>
|
||||||
<script src="health.js"></script>
|
<script src="health.js"></script>
|
||||||
<script src="storage.js"></script>
|
<script src="storage.js"></script>
|
||||||
|
|
18
manage.js
18
manage.js
|
@ -1,19 +1,3 @@
|
||||||
var styleTemplate = tHTML('\
|
|
||||||
<div>\
|
|
||||||
<h2 class="style-name"></h2>\
|
|
||||||
<p class="applies-to"></p>\
|
|
||||||
<p class="actions">\
|
|
||||||
<a class="style-edit-link" href="edit.html?id="><button i18n-text="editStyleLabel"></button></a>\
|
|
||||||
<button class="enable" i18n-text="enableStyleLabel"></button>\
|
|
||||||
<button class="disable" i18n-text="disableStyleLabel"></button>\
|
|
||||||
<button class="delete" i18n-text="deleteStyleLabel"></button>\
|
|
||||||
<button class="check-update" i18n-text="checkForUpdate"></button>\
|
|
||||||
<button class="update" i18n-text="installUpdate"></button>\
|
|
||||||
<span class="update-note"></span>\
|
|
||||||
</p>\
|
|
||||||
</div>\
|
|
||||||
');
|
|
||||||
|
|
||||||
var lastUpdatedStyleId = null;
|
var lastUpdatedStyleId = null;
|
||||||
var installed;
|
var installed;
|
||||||
|
|
||||||
|
@ -44,7 +28,7 @@ function showStyles(styles) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function createStyleElement(style) {
|
function createStyleElement(style) {
|
||||||
var e = styleTemplate.cloneNode(true);
|
var e = template.style.cloneNode(true);
|
||||||
e.setAttribute("class", style.enabled == "true" ? "enabled" : "disabled");
|
e.setAttribute("class", style.enabled == "true" ? "enabled" : "disabled");
|
||||||
e.setAttribute("style-id", style.id);
|
e.setAttribute("style-id", style.id);
|
||||||
if (style.updateUrl) {
|
if (style.updateUrl) {
|
||||||
|
|
21
popup.html
21
popup.html
|
@ -61,7 +61,7 @@
|
||||||
text-decoration: line-through;
|
text-decoration: line-through;
|
||||||
}
|
}
|
||||||
#installed .actions a {
|
#installed .actions a {
|
||||||
margin-right: 0.5em;
|
margin-right: 0.2em;
|
||||||
}
|
}
|
||||||
body > .actions {
|
body > .actions {
|
||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
|
@ -115,7 +115,7 @@
|
||||||
.breadcrumbs > .write-style-link:last-child::before {content: "\200b/"}
|
.breadcrumbs > .write-style-link:last-child::before {content: "\200b/"}
|
||||||
.breadcrumbs > .write-style-link:last-child:first-child::before,
|
.breadcrumbs > .write-style-link:last-child:first-child::before,
|
||||||
.breadcrumbs > .write-style-link[subdomain=""] + .write-style-link::before {content: none}
|
.breadcrumbs > .write-style-link[subdomain=""] + .write-style-link::before {content: none}
|
||||||
|
|
||||||
/* suppress TLD-only link */
|
/* suppress TLD-only link */
|
||||||
.breadcrumbs > .write-style-link[subdomain=""] {display: none}
|
.breadcrumbs > .write-style-link[subdomain=""] {display: none}
|
||||||
|
|
||||||
|
@ -130,6 +130,23 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<template data-id="style">
|
||||||
|
<div>
|
||||||
|
<div class="left-gutter">
|
||||||
|
<input class="checker" type="checkbox">
|
||||||
|
</div>
|
||||||
|
<div class="main-controls">
|
||||||
|
<label class="style-name"></label>
|
||||||
|
<div class="actions">
|
||||||
|
<a href="#" class="enable" i18n-text="enableStyleLabel"></a>
|
||||||
|
<a href="#" class="disable" i18n-text="disableStyleLabel"></a>
|
||||||
|
<a class="style-edit-link" href="edit.html?id=" i18n-text="editStyleLabel"></a>
|
||||||
|
<a href="#" class="delete" i18n-text="deleteStyleLabel"></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<script src="localization.js"></script>
|
<script src="localization.js"></script>
|
||||||
<script src="health.js"></script>
|
<script src="health.js"></script>
|
||||||
<script src="storage.js"></script>
|
<script src="storage.js"></script>
|
||||||
|
|
19
popup.js
19
popup.js
|
@ -1,20 +1,3 @@
|
||||||
var styleTemplate = tHTML('\
|
|
||||||
<div>\
|
|
||||||
<div class="left-gutter">\
|
|
||||||
<input class="checker" type="checkbox">\
|
|
||||||
</div>\
|
|
||||||
<div class="main-controls">\
|
|
||||||
<label class="style-name"></label>\
|
|
||||||
<div class="actions">\
|
|
||||||
<a href="#" class="enable" i18n-text="enableStyleLabel"></a>\
|
|
||||||
<a href="#" class="disable" i18n-text="disableStyleLabel"></a>\
|
|
||||||
<a class="style-edit-link" href="edit.html?id=" i18n-text="editStyleLabel"></a>\
|
|
||||||
<a href="#" class="delete" i18n-text="deleteStyleLabel"></a>\
|
|
||||||
</div>\
|
|
||||||
</div>\
|
|
||||||
</div>\
|
|
||||||
');
|
|
||||||
|
|
||||||
var writeStyleTemplate = document.createElement("a");
|
var writeStyleTemplate = document.createElement("a");
|
||||||
writeStyleTemplate.className = "write-style-link";
|
writeStyleTemplate.className = "write-style-link";
|
||||||
|
|
||||||
|
@ -102,7 +85,7 @@ function showStyles(styles) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function createStyleElement(style) {
|
function createStyleElement(style) {
|
||||||
var e = styleTemplate.cloneNode(true);
|
var e = template.style.cloneNode(true);
|
||||||
var checkbox = e.querySelector(".checker");
|
var checkbox = e.querySelector(".checker");
|
||||||
checkbox.id = "style-" + style.id;
|
checkbox.id = "style-" + style.id;
|
||||||
checkbox.checked = style.enabled == "true";
|
checkbox.checked = style.enabled == "true";
|
||||||
|
|
Loading…
Reference in New Issue
Block a user