mirror of https://github.com/gorhill/uBlock.git
add ability to filter out rules in "My rules" pane
This commit is contained in:
parent
4f2d071137
commit
6871d9aed4
|
@ -34,7 +34,7 @@ body {
|
|||
font-weight: normal;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
#diff .ruleFilter {
|
||||
#ruleFilter {
|
||||
text-align: center;
|
||||
}
|
||||
body[dir="ltr"] #revertButton:after {
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>uBlock — Dynamic filtering rules</title>
|
||||
<link rel="stylesheet" type="text/css" href="lib/codemirror/lib/codemirror.css">
|
||||
<link rel="stylesheet" type="text/css" href="lib/codemirror/addon/dialog/dialog.css">
|
||||
<link rel="stylesheet" type="text/css" href="lib/codemirror/addon/merge/merge.css">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="css/common.css">
|
||||
|
@ -33,7 +32,7 @@
|
|||
<button type="button" class="custom" id="importButton" data-i18n="rulesImport"></button>
|
||||
<button type="button" class="custom" id="editSaveButton" data-i18n="rulesEditSave"></button>
|
||||
</div>
|
||||
<!-- TO BE IMPLEMENTED: <div class="ruleFilter"><span class="fa"></span> <input type="text" size="32"></div> -->
|
||||
<div id="ruleFilter"><span class="fa"></span> <input type="text" size="32"></div>
|
||||
</div>
|
||||
<div class="codeMirrorContainer codeMirrorMergeContainer"></div>
|
||||
</div>
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
|
||||
var searchWidgetHtml =
|
||||
'<div class="cm-search-widget">' +
|
||||
'<span class="fa"></span> ' +
|
||||
'<span class="fa"></span> ' +
|
||||
'<span>' +
|
||||
'<input type="text" size="32">' +
|
||||
'<span class="cm-search-widget-count">' +
|
||||
|
|
|
@ -36,6 +36,7 @@ var mergeView = new CodeMirror.MergeView(
|
|||
{
|
||||
allowEditingOriginals: true,
|
||||
connect: 'align',
|
||||
inputStyle: 'contenteditable',
|
||||
lineNumbers: true,
|
||||
lineWrapping: false,
|
||||
origLeft: '',
|
||||
|
@ -47,21 +48,63 @@ mergeView.editor().setOption('styleActiveLine', true);
|
|||
mergeView.editor().setOption('lineNumbers', false);
|
||||
mergeView.leftOriginal().setOption('readOnly', 'nocursor');
|
||||
|
||||
var cleanToken = 0;
|
||||
var unfilteredRules = {
|
||||
orig: { doc: mergeView.leftOriginal(), rules: [] },
|
||||
edit: { doc: mergeView.editor(), rules: [] }
|
||||
};
|
||||
|
||||
var cleanEditToken = 0;
|
||||
var cleanEditText = '';
|
||||
|
||||
var differ;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Borrowed from...
|
||||
// https://github.com/codemirror/CodeMirror/blob/3e1bb5fff682f8f6cbfaef0e56c61d62403d4798/addon/search/search.js#L22
|
||||
// ... and modified as needed.
|
||||
|
||||
var updateOverlay = (function() {
|
||||
var reFilter;
|
||||
var mode = {
|
||||
token: function(stream) {
|
||||
if ( reFilter !== undefined ) {
|
||||
reFilter.lastIndex = stream.pos;
|
||||
var match = reFilter.exec(stream.string);
|
||||
if ( match !== null ) {
|
||||
if ( match.index === stream.pos ) {
|
||||
stream.pos += match[0].length || 1;
|
||||
return 'searching';
|
||||
}
|
||||
stream.pos = match.index;
|
||||
return;
|
||||
}
|
||||
}
|
||||
stream.skipToEnd();
|
||||
}
|
||||
};
|
||||
return function(filter) {
|
||||
reFilter = typeof filter === 'string' && filter !== '' ?
|
||||
new RegExp(filter.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi') :
|
||||
undefined;
|
||||
return mode;
|
||||
};
|
||||
})();
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Incrementally update text in a CodeMirror editor for best user experience:
|
||||
// - Scroll position preserved
|
||||
// - Minimum amount of text updated
|
||||
|
||||
var rulesToDoc = function(doc, rules) {
|
||||
if ( doc.getValue() === '' || rules.length === 0 ) {
|
||||
var rulesToDoc = function(clearHistory) {
|
||||
for ( var key in unfilteredRules ) {
|
||||
if ( unfilteredRules.hasOwnProperty(key) === false ) { continue; }
|
||||
var doc = unfilteredRules[key].doc;
|
||||
var rules = filterRules(key);
|
||||
if ( doc.lineCount() === 1 && doc.getValue() === '' || rules.length === 0 ) {
|
||||
doc.setValue(rules.length !== 0 ? rules.join('\n') : '');
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
if ( differ === undefined ) { differ = new diff_match_patch(); }
|
||||
var beforeText = doc.getValue();
|
||||
|
@ -87,6 +130,29 @@ var rulesToDoc = function(doc, rules) {
|
|||
doc.replaceRange('', beg, end);
|
||||
}
|
||||
doc.endOperation();
|
||||
}
|
||||
cleanEditText = mergeView.editor().getValue().trim();
|
||||
cleanEditToken = mergeView.editor().changeGeneration();
|
||||
if ( clearHistory ) {
|
||||
mergeView.editor().clearHistory();
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var filterRules = function(key) {
|
||||
var rules = unfilteredRules[key].rules;
|
||||
var filter = uDom('#ruleFilter input').val();
|
||||
if ( filter !== '' ) {
|
||||
rules = rules.slice();
|
||||
var i = rules.length;
|
||||
while ( i-- ) {
|
||||
if ( rules[i].indexOf(filter) === -1 ) {
|
||||
rules.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rules;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -98,18 +164,16 @@ var renderRules = (function() {
|
|||
details.hnSwitches.sort();
|
||||
details.permanentRules.sort();
|
||||
details.sessionRules.sort();
|
||||
var orig = details.hnSwitches.concat(details.permanentRules),
|
||||
edit = details.hnSwitches.concat(details.sessionRules);
|
||||
rulesToDoc(mergeView.leftOriginal(), orig);
|
||||
rulesToDoc(mergeView.editor(), edit);
|
||||
cleanEditText = mergeView.editor().getValue().trim();
|
||||
unfilteredRules.orig.rules =
|
||||
details.hnSwitches.concat(details.permanentRules);
|
||||
unfilteredRules.edit.rules =
|
||||
details.hnSwitches.concat(details.sessionRules);
|
||||
rulesToDoc(firstVisit);
|
||||
if ( firstVisit ) {
|
||||
mergeView.editor().clearHistory();
|
||||
firstVisit = false;
|
||||
mergeView.editor().execCommand('goNextDiff');
|
||||
}
|
||||
cleanToken = mergeView.editor().changeGeneration();
|
||||
onChange(true);
|
||||
onTextChanged(true);
|
||||
};
|
||||
})();
|
||||
|
||||
|
@ -157,19 +221,14 @@ mergeView.options.revertChunk = function(
|
|||
{ line: toStart.line, ch: 0 },
|
||||
{ line: toEnd.line, ch: 0 }
|
||||
);
|
||||
applyDiff(from === mv.editor(), toAdd, toRemove);
|
||||
to.replaceRange(toAdd, toStart, toEnd);
|
||||
cleanToken = mergeView.editor().changeGeneration();
|
||||
cleanEditText = mergeView.editor().getValue().trim();
|
||||
applyDiff(from === mv.editor(), toAdd, toRemove, renderRules);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
function handleImportFilePicker() {
|
||||
var fileReaderOnLoadHandler = function() {
|
||||
if ( typeof this.result !== 'string' || this.result === '' ) {
|
||||
return;
|
||||
}
|
||||
if ( typeof this.result !== 'string' || this.result === '' ) { return; }
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/757
|
||||
// Support RequestPolicy rule syntax
|
||||
var result = this.result;
|
||||
|
@ -217,41 +276,64 @@ function exportUserRulesToFile() {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
/*
|
||||
var onFilter = (function() {
|
||||
var timer;
|
||||
var onFilterChanged = (function() {
|
||||
var timer,
|
||||
overlay = null,
|
||||
last = '';
|
||||
|
||||
var process = function() {
|
||||
timer = undefined;
|
||||
if ( mergeView.editor().isClean(cleanEditToken) === false ) { return; }
|
||||
if ( overlay !== null ) {
|
||||
mergeView.leftOriginal().removeOverlay(overlay);
|
||||
mergeView.editor().removeOverlay(overlay);
|
||||
overlay = null;
|
||||
}
|
||||
var filter = uDom('#ruleFilter input').val();
|
||||
if ( filter === last ) { return; }
|
||||
last = filter;
|
||||
|
||||
if ( filter !== '' ) {
|
||||
overlay = updateOverlay(filter);
|
||||
mergeView.leftOriginal().addOverlay(overlay);
|
||||
mergeView.editor().addOverlay(overlay);
|
||||
}
|
||||
rulesToDoc(true);
|
||||
};
|
||||
|
||||
return function() {
|
||||
if ( timer !== undefined ) { clearTimeout(timer); }
|
||||
timer = vAPI.setTimeout(process, 577);
|
||||
timer = vAPI.setTimeout(process, 773);
|
||||
};
|
||||
})();
|
||||
*/
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var onChange = (function() {
|
||||
var onTextChanged = (function() {
|
||||
var timer;
|
||||
|
||||
var process = function(now) {
|
||||
timer = undefined;
|
||||
var isClean = mergeView.editor().isClean(cleanToken);
|
||||
var isClean = mergeView.editor().isClean(cleanEditToken);
|
||||
var diff = document.getElementById('diff');
|
||||
if (
|
||||
now &&
|
||||
isClean === false &&
|
||||
mergeView.editor().getValue().trim() === cleanEditText
|
||||
) {
|
||||
cleanToken = mergeView.editor().changeGeneration();
|
||||
cleanEditToken = mergeView.editor().changeGeneration();
|
||||
isClean = true;
|
||||
}
|
||||
diff.classList.toggle('editing', isClean === false);
|
||||
diff.classList.toggle('dirty', mergeView.leftChunks().length !== 0);
|
||||
CodeMirror.commands.save = isClean ? undefined : editSaveHandler;
|
||||
var input = document.querySelector('#ruleFilter input');
|
||||
if ( isClean ) {
|
||||
input.removeAttribute('disabled');
|
||||
CodeMirror.commands.save = undefined;
|
||||
} else {
|
||||
input.setAttribute('disabled', '');
|
||||
CodeMirror.commands.save = editSaveHandler;
|
||||
}
|
||||
};
|
||||
|
||||
return function(now) {
|
||||
|
@ -308,7 +390,7 @@ var editSaveHandler = function() {
|
|||
var editor = mergeView.editor();
|
||||
var editText = editor.getValue().trim();
|
||||
if ( editText === cleanEditText ) {
|
||||
onChange(true);
|
||||
onTextChanged(true);
|
||||
return;
|
||||
}
|
||||
if ( differ === undefined ) { differ = new diff_match_patch(); }
|
||||
|
@ -354,9 +436,10 @@ uDom('#exportButton').on('click', exportUserRulesToFile);
|
|||
uDom('#revertButton').on('click', revertAllHandler);
|
||||
uDom('#commitButton').on('click', commitAllHandler);
|
||||
uDom('#editSaveButton').on('click', editSaveHandler);
|
||||
uDom('#ruleFilter input').on('input', onFilterChanged);
|
||||
|
||||
// https://groups.google.com/forum/#!topic/codemirror/UQkTrt078Vs
|
||||
mergeView.editor().on('updateDiff', function() { onChange(); });
|
||||
mergeView.editor().on('updateDiff', function() { onTextChanged(); });
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
|
|
@ -664,6 +664,7 @@
|
|||
|
||||
function getChunks(diff) {
|
||||
var chunks = [];
|
||||
if (!diff.length) return chunks;
|
||||
var startEdit = 0, startOrig = 0;
|
||||
var edit = Pos(0, 0), orig = Pos(0, 0);
|
||||
for (var i = 0; i < diff.length; ++i) {
|
||||
|
|
Loading…
Reference in New Issue