@@ -31,6 +30,23 @@
+
+
diff --git a/src/css/3p-filters.css b/src/css/3p-filters.css
index 509931a61..4c6e469cc 100644
--- a/src/css/3p-filters.css
+++ b/src/css/3p-filters.css
@@ -20,26 +20,28 @@ body[dir=rtl] #lists {
#lists > li {
margin: 0.5em 0 0 0;
padding: 0;
- font-size: 15px;
list-style-type: none;
}
+#lists > li > span {
+ font-size: 15px;
+ }
#lists > li > ul {
margin: 0.25em 0 0 0;
}
-li.listDetails {
+li.listEntry {
font-size: 14px;
margin: 0 auto 0 auto;
margin-left: 1em;
margin-right: 0em;
}
-body[dir=rtl] li.listDetails {
+body[dir=rtl] li.listEntry {
margin-left: 0em;
margin-right: 1em;
}
-li.listDetails > * {
+li.listEntry > * {
unicode-bidi: embed;
}
-li.listDetails > a:nth-of-type(2) {
+li.listEntry > a:nth-of-type(2) {
font-size: 13px;
opacity: 0.5;
}
@@ -89,11 +91,12 @@ body[dir=rtl] #buttonApply {
display: none;
}
span.status {
- margin: 0;
+ margin: 0 0 0 1em;
border: 1px solid transparent;
padding: 1px 2px;
display: inline-block;
- font-size: 11px;
+ font-size: smaller;
+ line-height: 1;
opacity: 0.7;
}
span.purge {
diff --git a/src/js/3p-filters.js b/src/js/3p-filters.js
index 02c858886..6249dad02 100644
--- a/src/js/3p-filters.js
+++ b/src/js/3p-filters.js
@@ -67,6 +67,10 @@ var renderNumber = function(value) {
var renderBlacklists = function() {
uDom('body').toggleClass('busy', true);
+ var listGroupTemplate = uDom('#templates .groupEntry');
+ var listEntryTemplate = uDom('#templates .listEntry');
+ var listStatsTemplate = vAPI.i18n('3pListsOfBlockedHostsPerListStats');
+
// Assemble a pretty blacklist name if possible
var listNameFromListKey = function(listKey) {
if ( listKey === listDetails.userFiltersPath ) {
@@ -80,98 +84,71 @@ var renderBlacklists = function() {
return listTitle;
};
- // Assemble a pretty blacklist name if possible
- var htmlFromHomeURL = function(entry) {
- if ( !entry.homeDomain ) {
- return '';
+ var liFromListEntry = function(listKey) {
+ var elem, text;
+ var entry = listDetails.available[listKey];
+ var li = listEntryTemplate.clone();
+
+ if ( entry.off !== true ) {
+ li.descendants('input').attr('checked', '');
}
- return [
- '
(',
- entry.homeDomain,
- ')'
- ].join('');
- };
- var purgeButtontext = vAPI.i18n('3pExternalListPurge');
- var updateButtontext = vAPI.i18n('3pExternalListNew');
- var obsoleteButtontext = vAPI.i18n('3pExternalListObsolete');
- var liTemplate = [
- '
',
- '',
- ' ',
- '',
- '{{name}}',
- '\u200E',
- '{{homeURL}}',
- ': ',
- '',
- vAPI.i18n('3pListsOfBlockedHostsPerListStats'),
- ''
- ].join('');
+ elem = li.descendants('a:nth-of-type(1)');
+ elem.attr('href', encodeURI(listKey));
+ elem.text(listNameFromListKey(listKey) + '\u200E');
+
+ elem = li.descendants('a:nth-of-type(2)');
+ if ( entry.homeDomain ) {
+ elem.attr('href', 'http://' + encodeURI(entry.homeHostname));
+ elem.text('(' + entry.homeDomain + ')');
+ elem.css('display', '');
+ }
+
+ elem = li.descendants('span:nth-of-type(1)');
+ text = listStatsTemplate
+ .replace('{{used}}', renderNumber(!entry.off && !isNaN(+entry.entryUsedCount) ? entry.entryUsedCount : 0))
+ .replace('{{total}}', !isNaN(+entry.entryCount) ? renderNumber(entry.entryCount) : '?');
+ elem.text(text);
- var htmlFromLeaf = function(listKey) {
- var html = [];
- var list = listDetails.available[listKey];
- var li = liTemplate
- .replace('{{checked}}', list.off ? '' : 'checked')
- .replace('{{URL}}', encodeURI(listKey))
- .replace('{{name}}', listNameFromListKey(listKey))
- .replace('{{homeURL}}', htmlFromHomeURL(list))
- .replace('{{used}}', !list.off && !isNaN(+list.entryUsedCount) ? renderNumber(list.entryUsedCount) : '0')
- .replace('{{total}}', !isNaN(+list.entryCount) ? renderNumber(list.entryCount) : '?');
- html.push(li);
// https://github.com/gorhill/uBlock/issues/104
- var asset = listDetails.cache[listKey];
- if ( asset === undefined ) {
- return html.join('\n');
- }
+ var asset = listDetails.cache[listKey] || {};
+
// Update status
- if ( list.off !== true ) {
- var obsolete = asset.repoObsolete ||
- asset.cacheObsolete ||
- asset.cached !== true && re3rdPartyExternalAsset.test(listKey);
- if ( obsolete ) {
- html.push(
- ' ',
- '',
- asset.repoObsolete ? updateButtontext : obsoleteButtontext,
- ''
- );
+ if ( entry.off !== true ) {
+ if ( asset.repoObsolete ) {
+ li.descendants('span.status.new').css('display', '');
+ needUpdate = true;
+ } else if ( asset.cacheObsolete ) {
+ li.descendants('span.status.obsolete').css('display', '');
+ needUpdate = true;
+ } else if ( entry.external && !asset.cached ) {
+ li.descendants('span.status.obsolete').css('display', '');
needUpdate = true;
}
}
+
// In cache
if ( asset.cached ) {
- html.push(
- ' ',
- '',
- purgeButtontext,
- ''
- );
+ li.descendants('span.status.purge').css('display', '');
hasCachedContent = true;
}
- return html.join('\n');
+ return li;
};
- var htmlFromBranch = function(groupKey, listKeys) {
- var html = [
- '',
- vAPI.i18n('3pGroup' + groupKey.charAt(0).toUpperCase() + groupKey.slice(1)),
- ''
- ];
+ var liFromListGroup = function(groupKey, listKeys) {
+ var liGroup = listGroupTemplate.clone();
+ liGroup.descendants('span').text(vAPI.i18n('3pGroup' + groupKey.charAt(0).toUpperCase() + groupKey.slice(1)));
+ var ulGroup = liGroup.descendants('ul');
if ( !listKeys ) {
- return html.join('');
+ return liGroup;
}
listKeys.sort(function(a, b) {
return (listDetails.available[a].title || "").localeCompare(listDetails.available[b].title || "");
});
for ( var i = 0; i < listKeys.length; i++ ) {
- html.push(htmlFromLeaf(listKeys[i]));
+ ulGroup.append(liFromListEntry(listKeys[i]));
}
- html.push('
');
- return html.join('');
+ return liGroup;
};
// https://www.youtube.com/watch?v=unCVi4hYRlY#t=30m18s
@@ -201,7 +178,7 @@ var renderBlacklists = function() {
hasCachedContent = false;
// Visually split the filter lists in purpose-based groups
- var html = [];
+ var ulLists = uDom('#lists').empty();
var groups = groupsFromLists(details.available);
var groupKey, i;
var groupKeys = [
@@ -216,15 +193,14 @@ var renderBlacklists = function() {
];
for ( i = 0; i < groupKeys.length; i++ ) {
groupKey = groupKeys[i];
- html.push(htmlFromBranch(groupKey, groups[groupKey]));
+ ulLists.append(liFromListGroup(groupKey, groups[groupKey]));
delete groups[groupKey];
}
// For all groups not covered above (if any left)
groupKeys = Object.keys(groups);
for ( i = 0; i < groupKeys.length; i++ ) {
groupKey = groupKeys[i];
- html.push(htmlFromBranch(groupKey, groups[groupKey]));
- delete groups[groupKey];
+ ulLists.append(liFromListGroup(groupKey, groups[groupKey]));
}
uDom('#listsOfBlockedHostsPrompt').text(
@@ -234,17 +210,6 @@ var renderBlacklists = function() {
);
uDom('#autoUpdate').prop('checked', listDetails.autoUpdate === true);
uDom('#parseCosmeticFilters').prop('checked', listDetails.cosmetic === true);
- uDom('#lists').html(html.join(''));
- uDom('a').attr('target', '_blank');
-
- // Firefox: sanitizer drops those `href` attributes that point to local URLs
- var lis = uDom('a[data-href]');
- var a;
- i = lis.length;
- while ( i-- ) {
- a = lis.subset(i, 1);
- a.attr('href', a.attr('data-href'));
- }
updateWidgets();
};
@@ -370,7 +335,7 @@ var reloadAll = function(update) {
});
// Reload blacklists
var switches = [];
- var lis = uDom('#lists .listDetails');
+ var lis = uDom('#lists .listEntry');
var i = lis.length;
var path;
while ( i-- ) {
@@ -472,8 +437,8 @@ uDom.onLoad(function() {
uDom('#buttonApply').on('click', buttonApplyHandler);
uDom('#buttonUpdate').on('click', buttonUpdateHandler);
uDom('#buttonPurgeAll').on('click', buttonPurgeAllHandler);
- uDom('#lists').on('change', '.listDetails > input', onListCheckboxChanged);
- uDom('#lists').on('click', '.listDetails > a:nth-of-type(1)', onListLinkClicked);
+ uDom('#lists').on('change', '.listEntry > input', onListCheckboxChanged);
+ uDom('#lists').on('click', '.listEntry > a:nth-of-type(1)', onListLinkClicked);
uDom('#lists').on('click', 'span.purge', onPurgeClicked);
uDom('#externalLists').on('input', externalListsChangeHandler);
uDom('#externalListsApply').on('click', externalListsApplyHandler);