mirror of https://github.com/gorhill/uBlock.git
various improvements to the "Filter lists" pane
This commit is contained in:
parent
fb2b402940
commit
b60c06f3c4
|
@ -13,32 +13,30 @@
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<div id="cloudWidget" class="hide" data-cloud-entry="tpFiltersPane"></div>
|
|
||||||
<div>
|
<div id="cloudWidget" class="hide" data-cloud-entry="tpFiltersPane"></div>
|
||||||
<ul id="options">
|
<div>
|
||||||
<li><button id="buttonUpdate" class="custom important disabled" data-i18n="3pUpdateNow"></button>
|
<ul id="options" class="root">
|
||||||
<button id="buttonPurgeAll" class="custom disabled" data-i18n="3pPurgeAll"></button>
|
<li><button id="buttonUpdate" class="custom important disabled" data-i18n="3pUpdateNow"></button>
|
||||||
<button id="buttonApply" class="custom important disabled" data-i18n="3pApplyChanges"></button>
|
<button id="buttonPurgeAll" class="custom disabled" data-i18n="3pPurgeAll"></button>
|
||||||
<li><input type="checkbox" id="autoUpdate"><label data-i18n="3pAutoUpdatePrompt1" for="autoUpdate"></label> 
|
<button id="buttonApply" class="custom important disabled" data-i18n="3pApplyChanges"></button>
|
||||||
<li><input type="checkbox" id="parseCosmeticFilters"><label data-i18n="3pParseAllABPHideFiltersPrompt1" for="parseCosmeticFilters"></label><button class="whatisthis"></button>
|
<li><input type="checkbox" id="autoUpdate"><label data-i18n="3pAutoUpdatePrompt1" for="autoUpdate"></label> 
|
||||||
<div class="whatisthis-expandable para" data-i18n="3pParseAllABPHideFiltersInfo"></div>
|
<li><input type="checkbox" id="parseCosmeticFilters"><label data-i18n="3pParseAllABPHideFiltersPrompt1" for="parseCosmeticFilters"></label><button class="whatisthis"></button>
|
||||||
<li><input type="checkbox" id="ignoreGenericCosmeticFilters"><label data-i18n="3pIgnoreGenericCosmeticFilters" for="ignoreGenericCosmeticFilters"></label><button class="whatisthis"></button>
|
<div class="whatisthis-expandable para" data-i18n="3pParseAllABPHideFiltersInfo"></div>
|
||||||
<div class="whatisthis-expandable para" data-i18n="3pIgnoreGenericCosmeticFiltersInfo"></div>
|
<li><input type="checkbox" id="ignoreGenericCosmeticFilters"><label data-i18n="3pIgnoreGenericCosmeticFilters" for="ignoreGenericCosmeticFilters"></label><button class="whatisthis"></button>
|
||||||
</ul>
|
<div class="whatisthis-expandable para" data-i18n="3pIgnoreGenericCosmeticFiltersInfo"></div>
|
||||||
<p><span id="listsOfBlockedHostsPrompt"></span></p>
|
</ul>
|
||||||
|
<ul class="root">
|
||||||
|
<li><span id="listsOfBlockedHostsPrompt"></span>
|
||||||
<ul id="lists"></ul>
|
<ul id="lists"></ul>
|
||||||
</div>
|
</ul>
|
||||||
<div id="externalListsDiv">
|
</div>
|
||||||
<p>
|
|
||||||
<span data-i18n="3pExternalListsHint" style="margin: 0 0 0.25em 0; font-size: 13px;"></span>
|
|
||||||
<a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Filter-lists-from-around-the-web" target="_blank"></a>
|
|
||||||
<textarea id="externalLists" dir="ltr" spellcheck="false"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="templates" style="display: none;">
|
<div id="templates" style="display: none;">
|
||||||
<ul>
|
<ul>
|
||||||
<li class="groupEntry"><span class="geName"></span> <span class="geCount dim"></span>
|
<li class="groupEntry"><span class="geDetails"><span class="geName"></span> <span class="geCount dim"></span></span>
|
||||||
<ul class="listEntries"></ul>
|
<ul class="listEntries"></ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="listEntry">
|
<li class="listEntry">
|
||||||
|
@ -54,6 +52,9 @@
|
||||||
--><span class="fa status updating" title="3pUpdating"></span>​<!--
|
--><span class="fa status updating" title="3pUpdating"></span>​<!--
|
||||||
--><span class="fa status failed" title="3pNetworkError"></span>
|
--><span class="fa status failed" title="3pNetworkError"></span>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="listEntry toImport"><input type="checkbox" id="importLists"><label for="importLists" data-i18n="3pImport"></label><!--
|
||||||
|
--><a class="fa info towiki" href="https://github.com/gorhill/uBlock/wiki/Filter-lists-from-around-the-web" target="_blank"></a><!--
|
||||||
|
--><textarea id="externalLists" dir="ltr" spellcheck="false" placeholder="3pExternalListsHint"></textarea>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
"description":"appears as tab name in dashboard"
|
"description":"appears as tab name in dashboard"
|
||||||
},
|
},
|
||||||
"3pPageName":{
|
"3pPageName":{
|
||||||
"message":"3rd-party filters",
|
"message":"Filter lists",
|
||||||
"description":"appears as tab name in dashboard"
|
"description":"appears as tab name in dashboard"
|
||||||
},
|
},
|
||||||
"1pPageName":{
|
"1pPageName":{
|
||||||
|
@ -351,6 +351,10 @@
|
||||||
"message":"Apply changes",
|
"message":"Apply changes",
|
||||||
"description":"English: Apply changes"
|
"description":"English: Apply changes"
|
||||||
},
|
},
|
||||||
|
"3pGroupDefault":{
|
||||||
|
"message":"Local",
|
||||||
|
"description":"Header for the uBlock filters section in 'Filter lists pane'"
|
||||||
|
},
|
||||||
"3pGroupAds":{
|
"3pGroupAds":{
|
||||||
"message":"Ads",
|
"message":"Ads",
|
||||||
"description":"English: Ads"
|
"description":"English: Ads"
|
||||||
|
@ -379,8 +383,12 @@
|
||||||
"message":"Custom",
|
"message":"Custom",
|
||||||
"description":"English: Custom"
|
"description":"English: Custom"
|
||||||
},
|
},
|
||||||
|
"3pImport":{
|
||||||
|
"message":"Import...",
|
||||||
|
"description":"The label for the checkbox used to import external filter lists"
|
||||||
|
},
|
||||||
"3pExternalListsHint":{
|
"3pExternalListsHint":{
|
||||||
"message":"One URL per line. Lines prefixed with <code>!</code> will be ignored. Invalid URLs will be silently ignored.",
|
"message":"One URL per line. Invalid URLs will be silently ignored.",
|
||||||
"description":"Short information about how to use the textarea to import external filter lists by URL"
|
"description":"Short information about how to use the textarea to import external filter lists by URL"
|
||||||
},
|
},
|
||||||
"3pExternalListObsolete":{
|
"3pExternalListObsolete":{
|
||||||
|
|
|
@ -3,8 +3,16 @@
|
||||||
100% { transform: rotate(360deg); -webkit-transform: rotate(360deg); }
|
100% { transform: rotate(360deg); -webkit-transform: rotate(360deg); }
|
||||||
}
|
}
|
||||||
ul {
|
ul {
|
||||||
padding: 0;
|
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
|
padding-left: 1em;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
body[dir="rtl"] ul {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
ul.root {
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
#options li {
|
#options li {
|
||||||
margin-bottom: 0.5em;
|
margin-bottom: 0.5em;
|
||||||
|
@ -13,7 +21,7 @@ ul {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
#listsOfBlockedHostsPrompt:before {
|
#listsOfBlockedHostsPrompt:before {
|
||||||
color: #aaa;
|
color: #888;
|
||||||
content: '\2212 ';
|
content: '\2212 ';
|
||||||
}
|
}
|
||||||
body.hideUnused #listsOfBlockedHostsPrompt:before {
|
body.hideUnused #listsOfBlockedHostsPrompt:before {
|
||||||
|
@ -21,53 +29,46 @@ body.hideUnused #listsOfBlockedHostsPrompt:before {
|
||||||
}
|
}
|
||||||
#lists {
|
#lists {
|
||||||
margin: 0.5em 0 0 0;
|
margin: 0.5em 0 0 0;
|
||||||
padding-left: 0.5em;
|
padding: 0;
|
||||||
padding-right: 0em;
|
|
||||||
}
|
|
||||||
body[dir="rtl"] #lists {
|
|
||||||
padding-left: 0em;
|
|
||||||
padding-right: 0.5em;
|
|
||||||
}
|
}
|
||||||
#lists > li {
|
#lists > li {
|
||||||
margin: 0.5em 0 0 0;
|
margin: 0.5em 0 0 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
#lists > .groupEntry > .geName {
|
#lists > .groupEntry .geDetails {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 110%;
|
|
||||||
}
|
}
|
||||||
#lists > .groupEntry > .geCount {
|
#lists > .groupEntry .geDetails:before {
|
||||||
font-size: 90%;
|
color: #888;
|
||||||
}
|
|
||||||
#lists > .groupEntry:not(:first-child) > .geName:before {
|
|
||||||
color: #aaa;
|
|
||||||
content: '\2212 ';
|
content: '\2212 ';
|
||||||
}
|
}
|
||||||
#lists > .groupEntry.collapsed > .geName:before {
|
#lists > .groupEntry.hideUnused .geDetails:before {
|
||||||
color: #aaa;
|
|
||||||
content: '+ ';
|
content: '+ ';
|
||||||
}
|
}
|
||||||
|
#lists > .groupEntry .geName {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
#lists > .groupEntry .geCount {
|
||||||
|
font-size: 90%;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
#lists > .groupEntry > ul {
|
#lists > .groupEntry > ul {
|
||||||
margin: 0.25em 0 0 0;
|
margin: 0.25em 0 0 0;
|
||||||
}
|
padding-left: 1em;
|
||||||
#lists > .groupEntry.collapsed > ul {
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
li.listEntry {
|
li.listEntry {
|
||||||
line-height: 150%;
|
|
||||||
margin: 0 auto 0 auto;
|
margin: 0 auto 0 auto;
|
||||||
margin-left: 2.5em;
|
padding: 0.2em 0;
|
||||||
margin-right: 0;
|
white-space: nowrap;
|
||||||
text-indent: -2em;
|
|
||||||
}
|
}
|
||||||
body[dir="rtl"] li.listEntry {
|
body[dir="rtl"] li.listEntry {
|
||||||
margin-left: 0em;
|
}
|
||||||
margin-right: 2.5em;
|
li.listEntry.unused {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
li.listEntry > * {
|
li.listEntry > * {
|
||||||
margin-right: 0.5em;
|
margin-right: 0.5em;
|
||||||
text-indent: 0;
|
|
||||||
unicode-bidi: embed;
|
unicode-bidi: embed;
|
||||||
}
|
}
|
||||||
li.listEntry.toRemove > input[type="checkbox"] {
|
li.listEntry.toRemove > input[type="checkbox"] {
|
||||||
|
@ -83,6 +84,9 @@ li.listEntry > .fa {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
vertical-align: baseline;
|
vertical-align: baseline;
|
||||||
}
|
}
|
||||||
|
li.listEntry > a.towiki {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
li.listEntry > a.fa:hover {
|
li.listEntry > a.fa:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
@ -164,17 +168,18 @@ body.updating li.listEntry.obsolete > input[type="checkbox"]:checked ~ span.upda
|
||||||
animation: spin 2s linear infinite;
|
animation: spin 2s linear infinite;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
#externalListsDiv {
|
li.listEntry.toImport > input[type="checkbox"] ~ textarea {
|
||||||
margin: 1.5em auto 0 1.5em;
|
border: 1px solid #ccc;
|
||||||
}
|
|
||||||
body[dir=rtl] #externalListsDiv {
|
|
||||||
margin: 1.5em 1.5em 0 auto;
|
|
||||||
}
|
|
||||||
#externalLists {
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
height: 8em;
|
display: block;
|
||||||
margin-top: 0.25em;
|
font-size: smaller;
|
||||||
|
height: 6em;
|
||||||
|
margin-left: 2em;
|
||||||
|
resize: vertical;
|
||||||
|
visibility: hidden;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
width: 100%;
|
width: calc(100% - 4em);
|
||||||
word-wrap: normal;
|
}
|
||||||
|
li.listEntry.toImport > input[type="checkbox"]:checked ~ textarea {
|
||||||
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
uBlock Origin - a browser extension to block requests.
|
uBlock Origin - a browser extension to block requests.
|
||||||
Copyright (C) 2014-2017 Raymond Hill
|
Copyright (C) 2014-2018 Raymond Hill
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -32,7 +32,8 @@
|
||||||
var listDetails = {},
|
var listDetails = {},
|
||||||
filteringSettingsHash = '',
|
filteringSettingsHash = '',
|
||||||
lastUpdateTemplateString = vAPI.i18n('3pLastUpdate'),
|
lastUpdateTemplateString = vAPI.i18n('3pLastUpdate'),
|
||||||
reValidExternalList = /[a-z-]+:\/\/\S*\/\S+/;
|
reValidExternalList = /[a-z-]+:\/\/\S*\/\S+/,
|
||||||
|
hideUnusedSet = new Set();
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
@ -69,7 +70,6 @@ var renderFilterLists = function(soft) {
|
||||||
listEntryTemplate = uDom('#templates .listEntry'),
|
listEntryTemplate = uDom('#templates .listEntry'),
|
||||||
listStatsTemplate = vAPI.i18n('3pListsOfBlockedHostsPerListStats'),
|
listStatsTemplate = vAPI.i18n('3pListsOfBlockedHostsPerListStats'),
|
||||||
renderElapsedTimeToString = vAPI.i18n.renderElapsedTimeToString,
|
renderElapsedTimeToString = vAPI.i18n.renderElapsedTimeToString,
|
||||||
hideUnusedLists = document.body.classList.contains('hideUnused'),
|
|
||||||
groupNames = new Map();
|
groupNames = new Map();
|
||||||
|
|
||||||
// Assemble a pretty list name if possible
|
// Assemble a pretty list name if possible
|
||||||
|
@ -80,16 +80,17 @@ var renderFilterLists = function(soft) {
|
||||||
return listTitle;
|
return listTitle;
|
||||||
};
|
};
|
||||||
|
|
||||||
var liFromListEntry = function(listKey, li) {
|
var liFromListEntry = function(listKey, li, hideUnused) {
|
||||||
var entry = listDetails.available[listKey],
|
var entry = listDetails.available[listKey],
|
||||||
elem;
|
elem;
|
||||||
if ( !li ) {
|
if ( !li ) {
|
||||||
li = listEntryTemplate.clone().nodeAt(0);
|
li = listEntryTemplate.clone().nodeAt(0);
|
||||||
}
|
}
|
||||||
|
var on = entry.off !== true;
|
||||||
if ( li.getAttribute('data-listkey') !== listKey ) {
|
if ( li.getAttribute('data-listkey') !== listKey ) {
|
||||||
li.setAttribute('data-listkey', listKey);
|
li.setAttribute('data-listkey', listKey);
|
||||||
elem = li.querySelector('input[type="checkbox"]');
|
elem = li.querySelector('input[type="checkbox"]');
|
||||||
elem.checked = entry.off !== true;
|
elem.checked = on;
|
||||||
elem = li.querySelector('a:nth-of-type(1)');
|
elem = li.querySelector('a:nth-of-type(1)');
|
||||||
elem.setAttribute('href', 'asset-viewer.html?url=' + encodeURI(listKey));
|
elem.setAttribute('href', 'asset-viewer.html?url=' + encodeURI(listKey));
|
||||||
elem.setAttribute('type', 'text/html');
|
elem.setAttribute('type', 'text/html');
|
||||||
|
@ -115,18 +116,17 @@ var renderFilterLists = function(soft) {
|
||||||
} else {
|
} else {
|
||||||
li.classList.remove('mustread');
|
li.classList.remove('mustread');
|
||||||
}
|
}
|
||||||
|
li.classList.toggle('unused', hideUnused && !on);
|
||||||
}
|
}
|
||||||
// https://github.com/gorhill/uBlock/issues/1429
|
// https://github.com/gorhill/uBlock/issues/1429
|
||||||
if ( !soft ) {
|
if ( !soft ) {
|
||||||
elem = li.querySelector('input[type="checkbox"]');
|
li.querySelector('input[type="checkbox"]').checked = on;
|
||||||
elem.checked = entry.off !== true;
|
|
||||||
}
|
}
|
||||||
li.style.setProperty('display', hideUnusedLists && entry.off === true ? 'none' : '');
|
|
||||||
elem = li.querySelector('span.counts');
|
elem = li.querySelector('span.counts');
|
||||||
var text = '';
|
var text = '';
|
||||||
if ( !isNaN(+entry.entryUsedCount) && !isNaN(+entry.entryCount) ) {
|
if ( !isNaN(+entry.entryUsedCount) && !isNaN(+entry.entryCount) ) {
|
||||||
text = listStatsTemplate
|
text = listStatsTemplate
|
||||||
.replace('{{used}}', renderNumber(entry.off ? 0 : entry.entryUsedCount))
|
.replace('{{used}}', renderNumber(on ? entry.entryUsedCount : 0))
|
||||||
.replace('{{total}}', renderNumber(entry.entryCount));
|
.replace('{{total}}', renderNumber(entry.entryCount));
|
||||||
}
|
}
|
||||||
elem.textContent = text;
|
elem.textContent = text;
|
||||||
|
@ -157,14 +157,18 @@ var renderFilterLists = function(soft) {
|
||||||
|
|
||||||
var listEntryCountFromGroup = function(listKeys) {
|
var listEntryCountFromGroup = function(listKeys) {
|
||||||
if ( Array.isArray(listKeys) === false ) { return ''; }
|
if ( Array.isArray(listKeys) === false ) { return ''; }
|
||||||
var count = 0;
|
var count = 0,
|
||||||
|
total = 0;
|
||||||
var i = listKeys.length;
|
var i = listKeys.length;
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
if ( listDetails.available[listKeys[i]].off !== true ) {
|
if ( listDetails.available[listKeys[i]].off !== true ) {
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
|
total += 1;
|
||||||
}
|
}
|
||||||
return count === 0 ? '' : '(' + count.toLocaleString() + ')';
|
return total !== 0 ?
|
||||||
|
'(' + count.toLocaleString() + '/' + total.toLocaleString() + ')' :
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
var liFromListGroup = function(groupKey, listKeys) {
|
var liFromListGroup = function(groupKey, listKeys) {
|
||||||
|
@ -189,13 +193,19 @@ var renderFilterLists = function(soft) {
|
||||||
if ( liGroup.querySelector('.geName:empty') === null ) {
|
if ( liGroup.querySelector('.geName:empty') === null ) {
|
||||||
liGroup.querySelector('.geCount').textContent = listEntryCountFromGroup(listKeys);
|
liGroup.querySelector('.geCount').textContent = listEntryCountFromGroup(listKeys);
|
||||||
}
|
}
|
||||||
|
var hideUnused = mustHideUnusedLists(groupKey);
|
||||||
|
liGroup.classList.toggle('hideUnused', hideUnused);
|
||||||
var ulGroup = liGroup.querySelector('.listEntries');
|
var ulGroup = liGroup.querySelector('.listEntries');
|
||||||
if ( !listKeys ) { return liGroup; }
|
if ( !listKeys ) { return liGroup; }
|
||||||
listKeys.sort(function(a, b) {
|
listKeys.sort(function(a, b) {
|
||||||
return (listDetails.available[a].title || '').localeCompare(listDetails.available[b].title || '');
|
return (listDetails.available[a].title || '').localeCompare(listDetails.available[b].title || '');
|
||||||
});
|
});
|
||||||
for ( var i = 0; i < listKeys.length; i++ ) {
|
for ( var i = 0; i < listKeys.length; i++ ) {
|
||||||
var liEntry = liFromListEntry(listKeys[i], ulGroup.children[i]);
|
var liEntry = liFromListEntry(
|
||||||
|
listKeys[i],
|
||||||
|
ulGroup.children[i],
|
||||||
|
hideUnused
|
||||||
|
);
|
||||||
if ( liEntry.parentElement === null ) {
|
if ( liEntry.parentElement === null ) {
|
||||||
ulGroup.appendChild(liEntry);
|
ulGroup.appendChild(liEntry);
|
||||||
}
|
}
|
||||||
|
@ -226,7 +236,10 @@ var renderFilterLists = function(soft) {
|
||||||
|
|
||||||
// Incremental rendering: this will allow us to easily discard unused
|
// Incremental rendering: this will allow us to easily discard unused
|
||||||
// DOM list entries.
|
// DOM list entries.
|
||||||
uDom('#lists .listEntries .listEntry').addClass('discard');
|
uDom('#lists .listEntries .listEntry[data-listkey]').addClass('discard');
|
||||||
|
|
||||||
|
// Remove import widget while we recreate list of lists.
|
||||||
|
var importWidget = uDom('.listEntry.toImport').detach();
|
||||||
|
|
||||||
// Visually split the filter lists in purpose-based groups
|
// Visually split the filter lists in purpose-based groups
|
||||||
var ulLists = document.querySelector('#lists'),
|
var ulLists = document.querySelector('#lists'),
|
||||||
|
@ -242,6 +255,7 @@ var renderFilterLists = function(soft) {
|
||||||
'regions',
|
'regions',
|
||||||
'custom'
|
'custom'
|
||||||
];
|
];
|
||||||
|
document.body.classList.toggle('hideUnused', mustHideUnusedLists('*'));
|
||||||
for ( i = 0; i < groupKeys.length; i++ ) {
|
for ( i = 0; i < groupKeys.length; i++ ) {
|
||||||
groupKey = groupKeys[i];
|
groupKey = groupKeys[i];
|
||||||
liGroup = liFromListGroup(groupKey, groups[groupKey]);
|
liGroup = liFromListGroup(groupKey, groups[groupKey]);
|
||||||
|
@ -263,17 +277,28 @@ var renderFilterLists = function(soft) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uDom('#lists .listEntries .listEntry.discard').remove();
|
uDom('#lists .listEntries .listEntry.discard').remove();
|
||||||
uDom('#autoUpdate').prop('checked', listDetails.autoUpdate === true);
|
|
||||||
uDom('#listsOfBlockedHostsPrompt').text(
|
// Re-insert import widget.
|
||||||
|
uDom('[data-groupkey="custom"] .listEntries').append(importWidget);
|
||||||
|
|
||||||
|
uDom.nodeFromId('autoUpdate').checked = listDetails.autoUpdate === true;
|
||||||
|
uDom.nodeFromId('listsOfBlockedHostsPrompt').textContent =
|
||||||
vAPI.i18n('3pListsOfBlockedHostsPrompt')
|
vAPI.i18n('3pListsOfBlockedHostsPrompt')
|
||||||
.replace('{{netFilterCount}}', renderNumber(details.netFilterCount))
|
.replace(
|
||||||
.replace('{{cosmeticFilterCount}}', renderNumber(details.cosmeticFilterCount))
|
'{{netFilterCount}}',
|
||||||
);
|
renderNumber(details.netFilterCount)
|
||||||
|
)
|
||||||
|
.replace(
|
||||||
|
'{{cosmeticFilterCount}}',
|
||||||
|
renderNumber(details.cosmeticFilterCount)
|
||||||
|
);
|
||||||
|
uDom.nodeFromId('parseCosmeticFilters').checked =
|
||||||
|
listDetails.parseCosmeticFilters === true;
|
||||||
|
uDom.nodeFromId('ignoreGenericCosmeticFilters').checked =
|
||||||
|
listDetails.ignoreGenericCosmeticFilters === true;
|
||||||
|
|
||||||
// Compute a hash of the settings so that we can keep track of changes
|
// Compute a hash of the settings so that we can keep track of changes
|
||||||
// affecting the loading of filter lists.
|
// affecting the loading of filter lists.
|
||||||
uDom('#parseCosmeticFilters').prop('checked', listDetails.parseCosmeticFilters === true);
|
|
||||||
uDom('#ignoreGenericCosmeticFilters').prop('checked', listDetails.ignoreGenericCosmeticFilters === true);
|
|
||||||
if ( !soft ) {
|
if ( !soft ) {
|
||||||
filteringSettingsHash = hashFromCurrentFromSettings();
|
filteringSettingsHash = hashFromCurrentFromSettings();
|
||||||
}
|
}
|
||||||
|
@ -286,12 +311,18 @@ var renderFilterLists = function(soft) {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var renderWidgets = function() {
|
var renderWidgets = function() {
|
||||||
uDom('#buttonApply').toggleClass('disabled', filteringSettingsHash === hashFromCurrentFromSettings());
|
uDom('#buttonApply').toggleClass(
|
||||||
|
'disabled',
|
||||||
|
filteringSettingsHash === hashFromCurrentFromSettings()
|
||||||
|
);
|
||||||
uDom('#buttonPurgeAll').toggleClass(
|
uDom('#buttonPurgeAll').toggleClass(
|
||||||
'disabled',
|
'disabled',
|
||||||
document.querySelector('#lists .listEntry.cached:not(.obsolete)') === null
|
document.querySelector('#lists .listEntry.cached:not(.obsolete)') === null
|
||||||
);
|
);
|
||||||
uDom('#buttonUpdate').toggleClass('disabled', document.querySelector('body:not(.updating) #lists .listEntry.obsolete > input[type="checkbox"]:checked') === null);
|
uDom('#buttonUpdate').toggleClass(
|
||||||
|
'disabled',
|
||||||
|
document.querySelector('body:not(.updating) #lists .listEntry.obsolete > input[type="checkbox"]:checked') === null
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -323,8 +354,8 @@ var updateAssetStatus = function(details) {
|
||||||
|
|
||||||
var hashFromCurrentFromSettings = function() {
|
var hashFromCurrentFromSettings = function() {
|
||||||
var hash = [
|
var hash = [
|
||||||
document.getElementById('parseCosmeticFilters').checked,
|
uDom.nodeFromId('parseCosmeticFilters').checked,
|
||||||
document.getElementById('ignoreGenericCosmeticFilters').checked
|
uDom.nodeFromId('ignoreGenericCosmeticFilters').checked
|
||||||
];
|
];
|
||||||
var listHash = [],
|
var listHash = [],
|
||||||
listEntries = document.querySelectorAll('#lists .listEntry[data-listkey]:not(.toRemove)'),
|
listEntries = document.querySelectorAll('#lists .listEntry[data-listkey]:not(.toRemove)'),
|
||||||
|
@ -338,7 +369,8 @@ var hashFromCurrentFromSettings = function() {
|
||||||
}
|
}
|
||||||
hash.push(
|
hash.push(
|
||||||
listHash.sort().join(),
|
listHash.sort().join(),
|
||||||
reValidExternalList.test(document.getElementById('externalLists').value),
|
uDom.nodeFromId('importLists').checked &&
|
||||||
|
reValidExternalList.test(uDom.nodeFromId('externalLists').value),
|
||||||
document.querySelector('#lists .listEntry.toRemove') !== null
|
document.querySelector('#lists .listEntry.toRemove') !== null
|
||||||
);
|
);
|
||||||
return hash.join();
|
return hash.join();
|
||||||
|
@ -424,6 +456,7 @@ var selectFilterLists = function(callback) {
|
||||||
var externalListsElem = document.getElementById('externalLists'),
|
var externalListsElem = document.getElementById('externalLists'),
|
||||||
toImport = externalListsElem.value.trim();
|
toImport = externalListsElem.value.trim();
|
||||||
externalListsElem.value = '';
|
externalListsElem.value = '';
|
||||||
|
uDom.nodeFromId('importLists').checked = false;
|
||||||
|
|
||||||
messaging.send(
|
messaging.send(
|
||||||
'dashboard',
|
'dashboard',
|
||||||
|
@ -490,36 +523,89 @@ var autoUpdateCheckboxChanged = function() {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var toggleUnusedLists = function() {
|
// Collapsing of unused lists.
|
||||||
document.body.classList.toggle('hideUnused');
|
|
||||||
var hide = document.body.classList.contains('hideUnused');
|
var mustHideUnusedLists = function(which) {
|
||||||
uDom('#lists li.listEntry > input[type="checkbox"]:not(:checked)')
|
var hideAll = hideUnusedSet.has('*');
|
||||||
.ancestors('li.listEntry[data-listkey]')
|
if ( which === '*' ) { return hideAll; }
|
||||||
.css('display', hide ? 'none' : '');
|
return hideUnusedSet.has(which) !== hideAll;
|
||||||
vAPI.localStorage.setItem('hideUnusedFilterLists', hide ? '1' : '0');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
var toggleHideUnusedLists = function(which) {
|
||||||
|
var groupSelector,
|
||||||
var groupEntryClickHandler = function() {
|
doesHideAll = hideUnusedSet.has('*'),
|
||||||
var li = uDom(this).ancestors('.groupEntry');
|
mustHide;
|
||||||
li.toggleClass('collapsed');
|
if ( which === '*' ) {
|
||||||
var key = 'collapseGroup' + li.nthOfType();
|
mustHide = doesHideAll === false;
|
||||||
if ( li.hasClass('collapsed') ) {
|
groupSelector = '';
|
||||||
vAPI.localStorage.setItem(key, 'y');
|
hideUnusedSet.clear();
|
||||||
|
if ( mustHide ) {
|
||||||
|
hideUnusedSet.add(which);
|
||||||
|
}
|
||||||
|
document.body.classList.toggle('hideUnused', mustHide);
|
||||||
|
uDom('.groupEntry[data-groupkey]').toggleClass('hideUnused', mustHide);
|
||||||
} else {
|
} else {
|
||||||
vAPI.localStorage.removeItem(key);
|
var doesHide = hideUnusedSet.has(which);
|
||||||
|
if ( doesHide ) {
|
||||||
|
hideUnusedSet.delete(which);
|
||||||
|
} else {
|
||||||
|
hideUnusedSet.add(which);
|
||||||
|
}
|
||||||
|
mustHide = doesHide === doesHideAll;
|
||||||
|
groupSelector = '.groupEntry[data-groupkey="' + which + '"] ';
|
||||||
|
uDom(groupSelector).toggleClass('hideUnused', mustHide);
|
||||||
}
|
}
|
||||||
|
uDom(groupSelector + '.listEntry > input[type="checkbox"]:not(:checked)')
|
||||||
|
.ancestors('.listEntry[data-listkey]')
|
||||||
|
.toggleClass('unused', mustHide);
|
||||||
|
vAPI.localStorage.setItem(
|
||||||
|
'hideUnusedFilterLists',
|
||||||
|
JSON.stringify(Array.from(hideUnusedSet))
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var revealHiddenUsedLists = function() {
|
||||||
|
uDom('#lists .listEntry.unused > input[type="checkbox"]:checked')
|
||||||
|
.ancestors('.listEntry[data-listkey]')
|
||||||
|
.removeClass('unused');
|
||||||
|
};
|
||||||
|
|
||||||
|
uDom('#listsOfBlockedHostsPrompt').on('click', function() {
|
||||||
|
toggleHideUnusedLists('*');
|
||||||
|
});
|
||||||
|
|
||||||
|
uDom('#lists').on('click', '.groupEntry[data-groupkey] > .geDetails', function(ev) {
|
||||||
|
toggleHideUnusedLists(
|
||||||
|
uDom(ev.target)
|
||||||
|
.ancestors('.groupEntry[data-groupkey]')
|
||||||
|
.attr('data-groupkey')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var aa;
|
||||||
|
try {
|
||||||
|
var json = vAPI.localStorage.getItem('hideUnusedFilterLists');
|
||||||
|
if ( json !== null ) {
|
||||||
|
aa = JSON.parse(json);
|
||||||
|
}
|
||||||
|
} catch (ex) {
|
||||||
|
}
|
||||||
|
if ( Array.isArray(aa) === false ) {
|
||||||
|
aa = [ '*' ];
|
||||||
|
}
|
||||||
|
hideUnusedSet = new Set(aa);
|
||||||
|
})();
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// Cloud-related.
|
||||||
|
|
||||||
var toCloudData = function() {
|
var toCloudData = function() {
|
||||||
var bin = {
|
var bin = {
|
||||||
parseCosmeticFilters: uDom.nodeFromId('parseCosmeticFilters').checked,
|
parseCosmeticFilters: uDom.nodeFromId('parseCosmeticFilters').checked,
|
||||||
ignoreGenericCosmeticFilters: uDom.nodeFromId('ignoreGenericCosmeticFilters').checked,
|
ignoreGenericCosmeticFilters: uDom.nodeFromId('ignoreGenericCosmeticFilters').checked,
|
||||||
selectedLists: [],
|
selectedLists: []
|
||||||
externalLists: listDetails.externalLists
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var liEntries = uDom('#lists .listEntry'), liEntry;
|
var liEntries = uDom('#lists .listEntry'), liEntry;
|
||||||
|
@ -537,7 +623,7 @@ var toCloudData = function() {
|
||||||
var fromCloudData = function(data, append) {
|
var fromCloudData = function(data, append) {
|
||||||
if ( typeof data !== 'object' || data === null ) { return; }
|
if ( typeof data !== 'object' || data === null ) { return; }
|
||||||
|
|
||||||
var elem, checked, i, n;
|
var elem, checked;
|
||||||
|
|
||||||
elem = uDom.nodeFromId('parseCosmeticFilters');
|
elem = uDom.nodeFromId('parseCosmeticFilters');
|
||||||
checked = data.parseCosmeticFilters === true || append && elem.checked;
|
checked = data.parseCosmeticFilters === true || append && elem.checked;
|
||||||
|
@ -549,19 +635,35 @@ var fromCloudData = function(data, append) {
|
||||||
|
|
||||||
var selectedSet = new Set(data.selectedLists),
|
var selectedSet = new Set(data.selectedLists),
|
||||||
listEntries = uDom('#lists .listEntry'),
|
listEntries = uDom('#lists .listEntry'),
|
||||||
listEntry, listKey, input;
|
listEntry, listKey;
|
||||||
for ( i = 0, n = listEntries.length; i < n; i++ ) {
|
for ( var i = 0, n = listEntries.length; i < n; i++ ) {
|
||||||
listEntry = listEntries.at(i);
|
listEntry = listEntries.at(i);
|
||||||
listKey = listEntry.attr('data-listkey');
|
listKey = listEntry.attr('data-listkey');
|
||||||
input = listEntry.descendants('input').first();
|
var hasListKey = selectedSet.has(listKey);
|
||||||
|
selectedSet.delete(listKey);
|
||||||
|
var input = listEntry.descendants('input').first();
|
||||||
if ( append && input.prop('checked') ) { continue; }
|
if ( append && input.prop('checked') ) { continue; }
|
||||||
input.prop('checked', selectedSet.has(listKey) );
|
input.prop('checked', hasListKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
elem = uDom.nodeFromId('externalLists');
|
// If there are URL-like list keys left in the selected set, import them.
|
||||||
if ( !append ) { elem.value = ''; }
|
for ( listKey of selectedSet ) {
|
||||||
elem.value += data.externalLists || '';
|
if ( reValidExternalList.test(listKey) === false ) {
|
||||||
|
selectedSet.delete(listKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( selectedSet.size !== 0 ) {
|
||||||
|
elem = uDom.nodeFromId('externalLists');
|
||||||
|
if ( append ) {
|
||||||
|
if ( elem.value.trim() !== '' ) { elem.value += '\n'; }
|
||||||
|
} else {
|
||||||
|
elem.value = '';
|
||||||
|
}
|
||||||
|
elem.value += Array.from(selectedSet).join('\n');
|
||||||
|
uDom.nodeFromId('importLists').checked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
revealHiddenUsedLists();
|
||||||
renderWidgets();
|
renderWidgets();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -570,24 +672,19 @@ self.cloud.onPull = fromCloudData;
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
document.body.classList.toggle(
|
|
||||||
'hideUnused',
|
|
||||||
vAPI.localStorage.getItem('hideUnusedFilterLists') === '1'
|
|
||||||
);
|
|
||||||
|
|
||||||
uDom('#autoUpdate').on('change', autoUpdateCheckboxChanged);
|
uDom('#autoUpdate').on('change', autoUpdateCheckboxChanged);
|
||||||
uDom('#parseCosmeticFilters').on('change', onFilteringSettingsChanged);
|
uDom('#parseCosmeticFilters').on('change', onFilteringSettingsChanged);
|
||||||
uDom('#ignoreGenericCosmeticFilters').on('change', onFilteringSettingsChanged);
|
uDom('#ignoreGenericCosmeticFilters').on('change', onFilteringSettingsChanged);
|
||||||
uDom('#buttonApply').on('click', buttonApplyHandler);
|
uDom('#buttonApply').on('click', buttonApplyHandler);
|
||||||
uDom('#buttonUpdate').on('click', buttonUpdateHandler);
|
uDom('#buttonUpdate').on('click', buttonUpdateHandler);
|
||||||
uDom('#buttonPurgeAll').on('click', buttonPurgeAllHandler);
|
uDom('#buttonPurgeAll').on('click', buttonPurgeAllHandler);
|
||||||
uDom('#listsOfBlockedHostsPrompt').on('click', toggleUnusedLists);
|
|
||||||
uDom('#lists').on('click', '.groupEntry > span', groupEntryClickHandler);
|
|
||||||
uDom('#lists').on('change', '.listEntry > input', onFilteringSettingsChanged);
|
uDom('#lists').on('change', '.listEntry > input', onFilteringSettingsChanged);
|
||||||
uDom('#lists').on('click', '.listEntry > a.remove', onRemoveExternalList);
|
uDom('#lists').on('click', '.listEntry > a.remove', onRemoveExternalList);
|
||||||
uDom('#lists').on('click', 'span.cache', onPurgeClicked);
|
uDom('#lists').on('click', 'span.cache', onPurgeClicked);
|
||||||
uDom('#externalLists').on('input', onFilteringSettingsChanged);
|
uDom('#externalLists').on('input', onFilteringSettingsChanged);
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
renderFilterLists();
|
renderFilterLists();
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
Loading…
Reference in New Issue