1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-09-18 08:52:26 +02:00

code review of 3rd-party filters pane code

This commit is contained in:
gorhill 2017-01-20 08:40:19 -05:00
parent 29c7ba6a1a
commit 71a1e8c694

View File

@ -30,9 +30,7 @@
/******************************************************************************/ /******************************************************************************/
var listDetails = {}; var listDetails = {};
var parseCosmeticFilters = true; var filteringSettingsHash = '';
var ignoreGenericCosmeticFilters = false;
var selectedListsHashBefore = '';
var externalLists = ''; var externalLists = '';
/******************************************************************************/ /******************************************************************************/
@ -61,7 +59,7 @@ var renderNumber = function(value) {
/******************************************************************************/ /******************************************************************************/
var renderFilterLists = function() { var renderFilterLists = function(first) {
var listGroupTemplate = uDom('#templates .groupEntry'), var listGroupTemplate = uDom('#templates .groupEntry'),
listEntryTemplate = uDom('#templates .listEntry'), listEntryTemplate = uDom('#templates .listEntry'),
listStatsTemplate = vAPI.i18n('3pListsOfBlockedHostsPerListStats'), listStatsTemplate = vAPI.i18n('3pListsOfBlockedHostsPerListStats'),
@ -72,40 +70,39 @@ var renderFilterLists = function() {
var listNameFromListKey = function(listKey) { var listNameFromListKey = function(listKey) {
var list = listDetails.current[listKey] || listDetails.available[listKey]; var list = listDetails.current[listKey] || listDetails.available[listKey];
var listTitle = list ? list.title : ''; var listTitle = list ? list.title : '';
if ( listTitle === '' ) { if ( listTitle === '' ) { return listKey; }
return listKey;
}
return listTitle; return listTitle;
}; };
var liFromListEntry = function(listKey, li) { var liFromListEntry = function(listKey, li) {
var entry = listDetails.available[listKey]; var entry = listDetails.available[listKey],
li = li ? li : listEntryTemplate.clone().nodeAt(0); elem;
li.setAttribute('data-listkey', listKey); if ( !li ) {
var elem = li.querySelector('input[type="checkbox"]'); li = listEntryTemplate.clone().nodeAt(0);
if ( entry.off !== true ) {
elem.setAttribute('checked', '');
} else {
elem.removeAttribute('checked');
} }
elem = li.querySelector('a:nth-of-type(1)'); if ( li.getAttribute('data-listkey') !== listKey ) {
elem.setAttribute('href', 'asset-viewer.html?url=' + encodeURI(listKey)); li.setAttribute('data-listkey', listKey);
elem.setAttribute('type', 'text/html'); elem = li.querySelector('input[type="checkbox"]');
elem.textContent = listNameFromListKey(listKey) + '\u200E'; elem.checked = entry.off !== true;
elem = li.querySelector('a:nth-of-type(2)'); elem = li.querySelector('a:nth-of-type(1)');
if ( entry.instructionURL ) { elem.setAttribute('href', 'asset-viewer.html?url=' + encodeURI(listKey));
elem.setAttribute('href', entry.instructionURL); elem.setAttribute('type', 'text/html');
elem.style.setProperty('display', ''); elem.textContent = listNameFromListKey(listKey) + '\u200E';
} else { elem = li.querySelector('a:nth-of-type(2)');
elem.style.setProperty('display', 'none'); if ( entry.instructionURL ) {
} elem.setAttribute('href', entry.instructionURL);
elem = li.querySelector('a:nth-of-type(3)'); elem.style.setProperty('display', '');
if ( entry.supportName ) { } else {
elem.setAttribute('href', entry.supportURL); elem.style.setProperty('display', 'none');
elem.textContent = '(' + entry.supportName + ')'; }
elem.style.setProperty('display', ''); elem = li.querySelector('a:nth-of-type(3)');
} else { if ( entry.supportName ) {
elem.style.setProperty('display', 'none'); elem.setAttribute('href', entry.supportURL);
elem.textContent = '(' + entry.supportName + ')';
elem.style.setProperty('display', '');
} else {
elem.style.setProperty('display', 'none');
}
} }
elem = li.querySelector('span.counts'); elem = li.querySelector('span.counts');
var text = listStatsTemplate var text = listStatsTemplate
@ -124,15 +121,9 @@ var renderFilterLists = function() {
typeof remoteURL === 'string' && remoteURL.lastIndexOf('http:', 0) === 0 typeof remoteURL === 'string' && remoteURL.lastIndexOf('http:', 0) === 0
); );
// Badge for update status // Badge for update status
li.classList.toggle( li.classList.toggle('obsolete', entry.off !== true && asset.obsolete === true);
'obsolete',
entry.off !== true && asset.obsolete === true
);
// Badge for cache status // Badge for cache status
li.classList.toggle( li.classList.toggle('cached', asset.cached === true && asset.writeTime > 0);
'cached',
asset.cached === true && asset.writeTime > 0
);
if ( asset.cached ) { if ( asset.cached ) {
li.querySelector('.status.purge').setAttribute( li.querySelector('.status.purge').setAttribute(
'title', 'title',
@ -145,9 +136,7 @@ var renderFilterLists = function() {
}; };
var listEntryCountFromGroup = function(listKeys) { var listEntryCountFromGroup = function(listKeys) {
if ( Array.isArray(listKeys) === false ) { if ( Array.isArray(listKeys) === false ) { return ''; }
return '';
}
var count = 0; var count = 0;
var i = listKeys.length; var i = listKeys.length;
while ( i-- ) { while ( i-- ) {
@ -204,8 +193,6 @@ var renderFilterLists = function() {
var onListsReceived = function(details) { var onListsReceived = function(details) {
// Before all, set context vars // Before all, set context vars
listDetails = details; listDetails = details;
parseCosmeticFilters = details.parseCosmeticFilters;
ignoreGenericCosmeticFilters = details.ignoreGenericCosmeticFilters;
// 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.
@ -248,23 +235,19 @@ var renderFilterLists = function() {
uDom('#lists .listEntries .listEntry.discard').remove(); uDom('#lists .listEntries .listEntry.discard').remove();
uDom('#buttonUpdate').toggleClass('disabled', document.querySelector('#lists .listEntry.obsolete') === null); uDom('#buttonUpdate').toggleClass('disabled', document.querySelector('#lists .listEntry.obsolete') === null);
uDom('#autoUpdate').prop('checked', listDetails.autoUpdate === true); uDom('#autoUpdate').prop('checked', listDetails.autoUpdate === true);
uDom('#parseCosmeticFilters').prop('checked', listDetails.parseCosmeticFilters === true);
uDom('#ignoreGenericCosmeticFilters').prop('checked', listDetails.ignoreGenericCosmeticFilters === true);
uDom('#listsOfBlockedHostsPrompt').text( uDom('#listsOfBlockedHostsPrompt').text(
vAPI.i18n('3pListsOfBlockedHostsPrompt') vAPI.i18n('3pListsOfBlockedHostsPrompt')
.replace('{{netFilterCount}}', renderNumber(details.netFilterCount)) .replace('{{netFilterCount}}', renderNumber(details.netFilterCount))
.replace('{{cosmeticFilterCount}}', renderNumber(details.cosmeticFilterCount)) .replace('{{cosmeticFilterCount}}', renderNumber(details.cosmeticFilterCount))
); );
// Compute a hash of the lists currently enabled in memory. // Compute a hash of the settings so that we can keep track of changes
var selectedListsBefore = []; // affecting the loading of filter lists.
for ( var key in listDetails.current ) { if ( first ) {
if ( listDetails.current[key].off !== true ) { uDom('#parseCosmeticFilters').prop('checked', listDetails.parseCosmeticFilters === true);
selectedListsBefore.push(key); uDom('#ignoreGenericCosmeticFilters').prop('checked', listDetails.ignoreGenericCosmeticFilters === true);
} filteringSettingsHash = hashFromCurrentFromSettings();
} }
selectedListsHashBefore = selectedListsBefore.sort().join();
renderWidgets(); renderWidgets();
}; };
@ -276,9 +259,9 @@ var renderFilterLists = function() {
// This is to give a visual hint that the selection of blacklists has changed. // This is to give a visual hint that the selection of blacklists has changed.
var renderWidgets = function() { var renderWidgets = function() {
uDom('#buttonApply').toggleClass('disabled', !listsSelectionChanged()); uDom('#buttonApply').toggleClass('disabled', filteringSettingsHash === hashFromCurrentFromSettings());
uDom('#buttonPurgeAll').toggleClass('disabled', document.querySelector('#lists .listEntry.cached') === null); uDom('#buttonPurgeAll').toggleClass('disabled', document.querySelector('#lists .listEntry.cached') === null);
uDom('#buttonUpdate').toggleClass('disabled', document.querySelector('#lists .listEntry.obsolete') === null); uDom('#buttonUpdate').toggleClass('disabled', document.querySelector('#lists .listEntry.obsolete > input[type="checkbox"]:checked') === null);
}; };
/******************************************************************************/ /******************************************************************************/
@ -291,30 +274,34 @@ var updateAssetStatus = function(details) {
renderWidgets(); renderWidgets();
}; };
/******************************************************************************/ /*******************************************************************************
// Return whether selection of lists changed. Compute a hash from all the settings affecting how filter lists are loaded
in memory.
var listsSelectionChanged = function() { **/
if (
listDetails.parseCosmeticFilters !== parseCosmeticFilters || var hashFromCurrentFromSettings = function() {
listDetails.parseCosmeticFilters && var hash = [
listDetails.ignoreGenericCosmeticFilters !== ignoreGenericCosmeticFilters document.getElementById('parseCosmeticFilters').checked,
) { document.getElementById('ignoreGenericCosmeticFilters').checked
return true; ];
var listHash = [],
listEntries = document.querySelectorAll('#lists .listEntry[data-listkey]'),
liEntry,
i = listEntries.length;
while ( i-- ) {
liEntry = listEntries[i];
if ( liEntry.querySelector('input[type="checkbox"]:checked') !== null ) {
listHash.push(liEntry.getAttribute('data-listkey'));
}
} }
var selectedListsAfter = [], return hash.concat(listHash.sort()).join();
listEntries = uDom('#lists .listEntry[data-listkey] > input[type="checkbox"]:checked');
for ( var i = 0, n = listEntries.length; i < n; i++ ) {
selectedListsAfter.push(listEntries.at(i).ancestors('.listEntry[data-listkey]').attr('data-listkey'));
}
return selectedListsHashBefore !== selectedListsAfter.sort().join();
}; };
/******************************************************************************/ /******************************************************************************/
var onListCheckboxChanged = function() { var onFilteringSettingsChanged = function() {
renderWidgets(); renderWidgets();
}; };
@ -352,33 +339,33 @@ var selectFilterLists = function(callback) {
messaging.send('dashboard', { messaging.send('dashboard', {
what: 'userSettings', what: 'userSettings',
name: 'parseAllABPHideFilters', name: 'parseAllABPHideFilters',
value: listDetails.parseCosmeticFilters value: document.getElementById('parseCosmeticFilters').checked
}); });
messaging.send('dashboard', { messaging.send('dashboard', {
what: 'userSettings', what: 'userSettings',
name: 'ignoreGenericCosmeticFilters', name: 'ignoreGenericCosmeticFilters',
value: listDetails.ignoreGenericCosmeticFilters value: document.getElementById('ignoreGenericCosmeticFilters').checked
}); });
// Filter lists // Filter lists
var listKeys = [], var listKeys = [],
liEntries = uDom('#lists .listEntry'), liEntry, liEntries = document.querySelectorAll('#lists .listEntry[data-listkey]'),
i = liEntries.length; i = liEntries.length,
liEntry;
while ( i-- ) { while ( i-- ) {
liEntry = liEntries.at(i); liEntry = liEntries[i];
if ( liEntry.descendants('input').first().prop('checked') ) { if ( liEntry.querySelector('input[type="checkbox"]:checked') !== null ) {
listKeys.push(liEntry.attr('data-listkey')); listKeys.push(liEntry.getAttribute('data-listkey'));
} }
} }
messaging.send( messaging.send(
'dashboard', 'dashboard',
{ { what: 'selectFilterLists', keys: listKeys },
what: 'selectFilterLists',
keys: listKeys
},
callback callback
); );
filteringSettingsHash = hashFromCurrentFromSettings();
}; };
/******************************************************************************/ /******************************************************************************/
@ -389,6 +376,7 @@ var buttonApplyHandler = function() {
messaging.send('dashboard', { what: 'reloadAllFilters' }); messaging.send('dashboard', { what: 'reloadAllFilters' });
}; };
selectFilterLists(onSelectionDone); selectFilterLists(onSelectionDone);
renderWidgets();
}; };
/******************************************************************************/ /******************************************************************************/
@ -399,6 +387,7 @@ var buttonUpdateHandler = function() {
messaging.send('dashboard', { what: 'forceUpdateAssets' }); messaging.send('dashboard', { what: 'forceUpdateAssets' });
}; };
selectFilterLists(onSelectionDone); selectFilterLists(onSelectionDone);
renderWidgets();
}; };
/******************************************************************************/ /******************************************************************************/
@ -430,14 +419,6 @@ var autoUpdateCheckboxChanged = function() {
/******************************************************************************/ /******************************************************************************/
var cosmeticSwitchChanged = function() {
listDetails.parseCosmeticFilters = uDom.nodeFromId('parseCosmeticFilters').checked;
listDetails.ignoreGenericCosmeticFilters = uDom.nodeFromId('ignoreGenericCosmeticFilters').checked;
renderWidgets();
};
/******************************************************************************/
var renderExternalLists = function() { var renderExternalLists = function() {
var onReceived = function(details) { var onReceived = function(details) {
uDom('#externalLists').val(details); uDom('#externalLists').val(details);
@ -553,18 +534,18 @@ self.cloud.onPull = fromCloudData;
/******************************************************************************/ /******************************************************************************/
uDom('#autoUpdate').on('change', autoUpdateCheckboxChanged); uDom('#autoUpdate').on('change', autoUpdateCheckboxChanged);
uDom('#parseCosmeticFilters').on('change', cosmeticSwitchChanged); uDom('#parseCosmeticFilters').on('change', onFilteringSettingsChanged);
uDom('#ignoreGenericCosmeticFilters').on('change', cosmeticSwitchChanged); 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('#lists').on('change', '.listEntry > input', onListCheckboxChanged); uDom('#lists').on('change', '.listEntry > input', onFilteringSettingsChanged);
uDom('#lists').on('click', 'span.purge', onPurgeClicked); uDom('#lists').on('click', 'span.purge', onPurgeClicked);
uDom('#externalLists').on('input', externalListsChangeHandler); uDom('#externalLists').on('input', externalListsChangeHandler);
uDom('#externalListsApply').on('click', externalListsApplyHandler); uDom('#externalListsApply').on('click', externalListsApplyHandler);
uDom('#lists').on('click', '.groupEntry > span', groupEntryClickHandler); uDom('#lists').on('click', '.groupEntry > span', groupEntryClickHandler);
renderFilterLists(); renderFilterLists(true);
renderExternalLists(); renderExternalLists();
/******************************************************************************/ /******************************************************************************/