[Pkg-mozext-commits] [adblock-plus] 47/74: Issue 2376 - Implement custom filters functionality in options page
David Prévot
taffit at moszumanska.debian.org
Tue Aug 11 12:07:09 UTC 2015
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch master
in repository adblock-plus.
commit 7eede4ea130aca0ee2c7b4f19998fb1ceba3f694
Author: Manvel Saroyan <manvel at adblockplus.org>
Date: Wed Jul 15 18:48:51 2015 +0200
Issue 2376 - Implement custom filters functionality in options page
---
README.md | 2 +
background.js | 57 ++++++++++++++++----
locale/en-US/options.json | 24 ++++++---
messageResponder.js | 82 ++++++++++++++++++++++------
options.html | 52 +++++++++---------
options.js | 123 +++++++++++++++++++++++++++++++-----------
skin/options.css | 134 +++++++++++++++++++++++++++++++++++-----------
7 files changed, 356 insertions(+), 118 deletions(-)
diff --git a/README.md b/README.md
index 995d679..2678aa5 100644
--- a/README.md
+++ b/README.md
@@ -72,3 +72,5 @@ The behavior of this page is affected by a number of URL parameters:
creating the link to the version-specific release notes
* `addSubscription=true`: this parameter should trigger a dialog for adding
subscriptions as initiated by clicking on an "abp:subscribe" link
+* `filterError=true`: causes filter validation to fail, showing validation
+ errors when adding new filters on the options page
diff --git a/background.js b/background.js
index fecc5fc..5155e9a 100644
--- a/background.js
+++ b/background.js
@@ -31,6 +31,15 @@
}
}
+ var params = {
+ blockedURLs: "",
+ seenDataCorruption: false,
+ filterlistsReinitialized: false,
+ addSubscription: false,
+ filterError: false
+ };
+ updateFromURL(params);
+
var modules = {};
global.require = function(module)
{
@@ -153,6 +162,24 @@
return new modules.filterClasses.Filter(text);
};
+ modules.filterValidation =
+ {
+ parseFilter: function(text)
+ {
+
+ if (params.filterError)
+ return {error: "Invalid filter"};
+ return {filter: modules.filterClasses.Filter.fromText(text)};
+ },
+ parseFilters: function(text)
+ {
+ if (params.filterError)
+ return {errors: ["Invalid filter"]};
+ return {filters:
+ text.split("\n").map(modules.filterClasses.Filter.fromText)};
+ }
+ };
+
modules.synchronizer = {
Synchronizer: {}
};
@@ -161,8 +188,6 @@
defaultMatcher: {
matchesAny: function(url, requestType, docDomain, thirdParty)
{
- var params = {blockedURLs: ""};
- updateFromURL(params);
var blocked = params.blockedURLs.split(",");
if (blocked.indexOf(url) >= 0)
return new modules.filterClasses.BlockingFilter();
@@ -221,7 +246,23 @@
"@@||alternate.de^$document",
"@@||der.postillion.com^$document",
"@@||taz.de^$document",
- "@@||amazon.de^$document"
+ "@@||amazon.de^$document",
+ "||biglemon.am/bg_poster/banner.jpg",
+ "winfuture.de###header_logo_link",
+ "###WerbungObenRechts10_GesamtDIV",
+ "###WerbungObenRechts8_GesamtDIV",
+ "###WerbungObenRechts9_GesamtDIV",
+ "###WerbungUntenLinks4_GesamtDIV",
+ "###WerbungUntenLinks7_GesamtDIV",
+ "###WerbungUntenLinks8_GesamtDIV",
+ "###WerbungUntenLinks9_GesamtDIV",
+ "###Werbung_Sky",
+ "###Werbung_Wide",
+ "###__ligatus_placeholder__",
+ "###ad-bereich1-08",
+ "###ad-bereich1-superbanner",
+ "###ad-bereich2-08",
+ "###ad-bereich2-skyscrapper"
];
var knownFilters = filters.map(modules.filterClasses.Filter.fromText);
@@ -236,14 +277,10 @@
knownSubscriptions[subscriptionUrl] = modules.subscriptionClasses.Subscription.fromURL(subscriptionUrl);
var customSubscription = knownSubscriptions["~user~786254"];
- var issues = {seenDataCorruption: false, filterlistsReinitialized: false};
- updateFromURL(issues);
- global.seenDataCorruption = issues.seenDataCorruption;
- global.filterlistsReinitialized = issues.filterlistsReinitialized;
+ global.seenDataCorruption = params.seenDataCorruption;
+ global.filterlistsReinitialized = params.filterlistsReinitialized;
- var events = {addSubscription: false};
- updateFromURL(events);
- if (events.addSubscription)
+ if (params.addSubscription)
{
// We don't know how long it will take for the page to fully load
// so we'll post the message after one second
diff --git a/locale/en-US/options.json b/locale/en-US/options.json
index 4c6455e..8fe5b8a 100644
--- a/locale/en-US/options.json
+++ b/locale/en-US/options.json
@@ -44,7 +44,7 @@
"message": "Blocking"
},
"options_language_title": {
- "description": "Option name in General tab",
+ "description": "Ad blocking list option name in General tab",
"message": "<strong>Adblocking</strong> for websites in..."
},
"options_language_add": {
@@ -52,7 +52,7 @@
"message": "add other website languages"
},
"options_furtherBlocking_title": {
- "description": "Option name in General tab",
+ "description": "Blocking list option name in General tab",
"message": "Further blocking options"
},
"options_popular": {
@@ -127,14 +127,26 @@
"description": "Update button in Advanced tab",
"message": "Update all blocking lists"
},
- "options_blockingRules": {
- "description": "Own blicking list header in Advanced tab",
+ "options_customFilters_title": {
+ "description": "Custom filters option name in Advanced tab",
"message": "Blocking rules"
},
- "options_blockingRules_edit": {
- "description": "Edit rules button in Advanced tab",
+ "options_customFilters_textbox_placeholder": {
+ "description": "Adding custom filter textbox placeholder text in Advanced tab",
+ "message": "add your blocking rule here"
+ },
+ "options_customFilter_edit": {
+ "description": "Label for editing custom filter in Advanced tab",
"message": "edit rules"
},
+ "options_customFilter_list": {
+ "description": "Label for editing custom filter in Advanced tab",
+ "message": "list view"
+ },
+ "options_customFilter_save": {
+ "description": "Label for editing custom filter in Advanced tab",
+ "message": "save"
+ },
"options_faq_title": {
"description": "FAQ section name in Help tab and link label in same section",
"message": "Frequently asked questions"
diff --git a/messageResponder.js b/messageResponder.js
index 5322f17..bd27638 100644
--- a/messageResponder.js
+++ b/messageResponder.js
@@ -30,6 +30,7 @@
var Filter = filterClasses.Filter;
var BlockingFilter = filterClasses.BlockingFilter;
var Synchronizer = require("synchronizer").Synchronizer;
+ var filterValidation = require("filterValidation");
var subscriptionClasses = require("subscriptionClasses");
var Subscription = subscriptionClasses.Subscription;
@@ -55,6 +56,23 @@
"subscription": "subscriptions.listen"
};
+ function sendMessage(type, action, args, page)
+ {
+ var pages = page ? [page] : changeListeners.keys();
+ for (var i = 0; i < pages.length; i++)
+ {
+ var filters = changeListeners.get(pages[i]);
+ if (filters[type] && filters[type].indexOf(action) >= 0)
+ {
+ pages[i].sendMessage({
+ type: messageTypes[type],
+ action: action,
+ args: args
+ });
+ }
+ }
+ }
+
function onFilterChange(action)
{
if (action == "load")
@@ -85,21 +103,8 @@
else
return arg;
});
-
- var pages = changeListeners.keys();
- for (var i = 0; i < pages.length; i++)
- {
- var filters = changeListeners.get(pages[i]);
- if (filters[type] && filters[type].indexOf(action) >= 0)
- {
- pages[i].sendMessage({
- type: messageTypes[type],
- action: action,
- args: args
- });
- }
- }
- };
+ sendMessage(type, action, args);
+ }
global.ext.onMessage.addListener(function(message, sender, callback)
{
@@ -178,7 +183,11 @@
break;
case "filters.add":
var filter = Filter.fromText(message.text);
- FilterStorage.addFilter(filter);
+ var result = filterValidation.parseFilter(message.text);
+ if (result.error)
+ sendMessage("app", "error", [result.error.toString()], sender.page);
+ else if (result.filter)
+ FilterStorage.addFilter(result.filter);
break;
case "filters.blocked":
var filter = defaultMatcher.matchesAny(message.url, message.requestType,
@@ -195,6 +204,47 @@
callback(subscription.filters.map(convertFilter));
break;
+ case "filters.importRaw":
+ var result = filterValidation.parseFilters(message.text);
+ var errors = [];
+ for (var i = 0; i < result.errors.length; i++)
+ {
+ var error = result.errors[i];
+ if (error.type != "unexpected-filter-list-header")
+ errors.push(error.toString());
+ }
+
+ if (errors.length > 0)
+ {
+ sendMessage("app", "error", errors, sender.page);
+ return;
+ }
+
+ var seenFilter = Object.create(null);
+ for (var i = 0; i < result.filters.length; i++)
+ {
+ var filter = result.filters[i];
+ FilterStorage.addFilter(filter);
+ seenFilter[filter.text] = null;
+ }
+
+ for (var i = 0; i < FilterStorage.subscriptions.length; i++)
+ {
+ var subscription = FilterStorage.subscriptions[i];
+ if (!(subscription instanceof SpecialSubscription))
+ continue;
+
+ for (var j = subscription.filters.length - 1; j >= 0; j--)
+ {
+ var filter = subscription.filters[j];
+ if (/^@@\|\|([^\/:]+)\^\$document$/.test(filter.text))
+ continue;
+
+ if (!(filter.text in seenFilter))
+ FilterStorage.removeFilter(filter);
+ }
+ }
+ break;
case "filters.listen":
if (message.filter)
listenerFilters.filter = message.filter;
diff --git a/options.html b/options.html
index 61a3445..4601331 100644
--- a/options.html
+++ b/options.html
@@ -178,7 +178,7 @@
<div>
<h1><span class="i18n_options_blockingList_title"></span><a class="i18n_options_readMore tooltip" href="#" target="_blank"></a></h1>
<ul id="blocking-list-tabs" class="tabs horizontal">
- <li class="i18n_options_tab_overview active" data-show="blocking-list-overview"></li><li class="i18n_options_tab_ownList" data-show="blocking-list-own"></li>
+ <li class="i18n_options_tab_overview active" data-show="blocking-list-overview"></li><li class="i18n_options_tab_ownList" data-show="custom-filters"></li>
</ul>
<div id="blocking-list">
<div id="blocking-list-overview">
@@ -199,33 +199,37 @@
</button>
</div>
</div>
- <div id="blocking-list-own">
- <p class="i18n_options_blockingRules"></p>
- <ul class="table list">
- <li><span>zap2it.com##.zc-station-position</span></li>
- <li><span>downturk.net##.zippo</span></li>
- <li><span>yahoo.com##.y708-promo-middle</span></li>
- <li><span>reflector.com##.yahooboss</span></li>
- <li><span>yardbarker.com##.yard_leader</span></li>
- <li><span>espn.co.uk##.will_hill</span></li>
- <li><span>listverse.com##.wiki</span></li>
- <li><span>planet5d.com##.wp-image-1573</span></li>
- <li><span>buzzinn.net##.wpn_finner</span></li>
- <li><span>talkers.com##.wpss_slideshow</span></li>
- </ul>
- <div class="controls" style="margin: 0px;">
- <input type="text" placeholder="add your blocking rule here"/>
- <div class="input-control">
- <span class="input-separator"></span>
- <span class="i18n_options_button_add input-button-text"></span>
- <span class="icon icon-enter-blue"></span>
+ <div id="custom-filters">
+ <h2 id="custom-filters-header" class="i18n_options_customFilters_title"></h2>
+ <div id="custom-filters-wrapper">
+ <div id="custom-filters-list-wrapper">
+ <ul id="custom-filters-table" class="table list">
+ <template>
+ <span class="display"></span>
+ </template>
+ </ul>
+ <form id="custom-filters-add" class="controls">
+ <input type="text"/>
+ <button class="i18n_options_button_add" type="submit"></button>
+ </form>
</div>
+ <textarea id="custom-filters-raw"></textarea>
</div>
- <div class="controls">
- <button>
+ <div id="custom-filters-edit-wrapper" class="controls">
+ <button id="custom-filters-show-edit">
<span class="icon icon-edit"></span>
- <span class="i18n_options_blockingRules_edit"></span>
+ <span class="i18n_options_customFilter_edit"></span>
</button>
+ <div id="custom-filters-raw-controls">
+ <button>
+ <span class="icon icon-edit"></span>
+ <span class="i18n_options_customFilter_list"></span>
+ </button>
+ <button id="custom-filters-raw-save">
+ <span class="icon icon-edit"></span>
+ <span class="i18n_options_customFilter_save"></span>
+ </button>
+ </div>
</div>
</div>
</div>
diff --git a/options.js b/options.js
index 9194892..ded94e8 100644
--- a/options.js
+++ b/options.js
@@ -38,8 +38,8 @@
this.items.sort(function(a, b)
{
- var aValue = (a.title || a.url || a.text).toLowerCase();
- var bValue = (b.title || b.url || a.text).toLowerCase();
+ var aValue = (a.title || a.text || a.url).toLowerCase();
+ var bValue = (b.title || b.text || b.url).toLowerCase();
return aValue.localeCompare(bValue);
});
@@ -107,7 +107,13 @@
e.preventDefault();
var subscriptionUrl = e.target.parentNode.dataset.access;
if (!e.target.checked)
- removeSubscription(subscriptionUrl);
+ {
+ ext.backgroundPage.sendMessage(
+ {
+ type: "subscriptions.remove",
+ url: subscriptionUrl
+ });
+ }
else
addEnableSubscription(subscriptionUrl);
}
@@ -122,7 +128,11 @@
function onRemoveFilterClick()
{
var filter = this.parentNode.dataset.access;
- removeFilter(filter);
+ ext.backgroundPage.sendMessage(
+ {
+ type: "filters.remove",
+ text: filter
+ });
}
collections.popular = new Collection(
@@ -170,6 +180,12 @@
onClick: onRemoveFilterClick
}
]);
+ collections.customFilters = new Collection(
+ [
+ {
+ id: "custom-filters-table"
+ }
+ ]);
function updateSubscription(subscription)
{
@@ -266,12 +282,11 @@
{
filter.title = match[1];
collections.whitelist.addItems(filter);
- filtersMap[filter.text] = filter
}
else
- {
- // TODO: add `filters[i].text` to list of custom filters
- }
+ collections.customFilters.addItems(filter);
+
+ filtersMap[filter.text] = filter;
}
function loadRecommendations()
@@ -345,6 +360,14 @@
searchStyle.innerHTML = "#all-lang-table li:not([data-search*=\"" + this.value.toLowerCase() + "\"]) { display: none; }";
}
+ function isEnterPressed(e)
+ {
+ // e.keyCode has been deprecated so we attempt to use e.key
+ if ("key" in e)
+ return e.key == "Enter";
+ return e.keyCode == 13; // keyCode "13" corresponds to "Enter"
+ }
+
// Initialize navigation sidebar
ext.backgroundPage.sendMessage(
{
@@ -395,9 +418,7 @@
E("whitelisting-add-button").addEventListener("click", addWhitelistedDomain, false);
E("whitelisting-textbox").addEventListener("keypress", function(e)
{
- // e.keyCode has been deprecated so we attempt to use e.key
- // keyCode "13" corresponds to "Enter"
- if ((e.key && e.key == "Enter") || (!e.key && e.keyCode == 13))
+ if (isEnterPressed(e))
addWhitelistedDomain();
}, false);
E("import-blockingList-button").addEventListener("click", function()
@@ -406,6 +427,50 @@
addEnableSubscription(url);
delete document.body.dataset.dialog;
}, false);
+
+ // Advanced tab
+ var filterTextbox = document.querySelector("#custom-filters-add input");
+ placeholderValue = ext.i18n.getMessage("options_customFilters_textbox_placeholder");
+ filterTextbox.setAttribute("placeholder", placeholderValue);
+ function addCustomFilters()
+ {
+ var filterText = filterTextbox.value;
+ ext.backgroundPage.sendMessage(
+ {
+ type: "filters.add",
+ text: filterText
+ });
+ filterTextbox.value = "";
+ }
+ E("custom-filters-add").addEventListener("submit", function(e)
+ {
+ e.preventDefault();
+ addCustomFilters();
+ }, false);
+ var customFilterEditButtons = document.querySelectorAll("#custom-filters-edit-wrapper button");
+ E("custom-filters-edit-wrapper").addEventListener("click", function(e)
+ {
+ var target = null;
+ if (e.target.localName == "button")
+ target = e.target;
+ else if (e.target.parentElement.localName == "button")
+ target = e.target.parentElement;
+ else
+ return;
+
+ var id = target.id;
+ E("custom-filters").classList.toggle("mode-edit");
+ if (id == "custom-filters-show-edit")
+ editCustomFilters();
+ else if (id == "custom-filters-raw-save")
+ {
+ ext.backgroundPage.sendMessage(
+ {
+ type: "filters.importRaw",
+ text: E("custom-filters-raw").value
+ });
+ }
+ }, false);
}
function openDialog(name)
@@ -485,7 +550,11 @@
function editCustomFilters()
{
- //TODO: NYI
+ var customFilterItems = collections.customFilters.items;
+ var filterTexts = [];
+ for (var i = 0; i < customFilterItems.length; i++)
+ filterTexts.push(customFilterItems[i].text);
+ E("custom-filters-raw").value = filterTexts.join("\n");
}
function getAcceptableAdsURL(callback)
@@ -526,24 +595,6 @@
ext.backgroundPage.sendMessage(message);
}
- function removeSubscription(url)
- {
- ext.backgroundPage.sendMessage(
- {
- type: "subscriptions.remove",
- url: url
- });
- }
-
- function removeFilter(filter)
- {
- ext.backgroundPage.sendMessage(
- {
- type: "filters.remove",
- text: filter
- });
- }
-
function onFilterMessage(action, filter)
{
switch (action)
@@ -558,6 +609,7 @@
case "removed":
var knownFilter = filtersMap[filter.text];
collections.whitelist.removeItem(knownFilter);
+ collections.customFilters.removeItem(knownFilter);
delete filtersMap[filter.text];
updateShareLink();
break;
@@ -647,7 +699,14 @@
{
case "app.listen":
if (message.action == "addSubscription")
- showAddSubscriptionDialog(message.args[0]);
+ {
+ E("blockingList-textbox").value = message.args[0].url;
+ openDialog("customlist");
+ }
+ else if (message.action == "error")
+ {
+ alert(message.args.join("\n"));
+ }
break;
case "filters.listen":
onFilterMessage(message.action, message.args[0]);
@@ -661,7 +720,7 @@
ext.backgroundPage.sendMessage(
{
type: "app.listen",
- filter: ["addSubscription"]
+ filter: ["addSubscription", "error"]
});
ext.backgroundPage.sendMessage(
{
diff --git a/skin/options.css b/skin/options.css
index e53a0e3..2f5d070 100644
--- a/skin/options.css
+++ b/skin/options.css
@@ -85,6 +85,13 @@ input[type="search"]::-webkit-search-cancel-button
display: none;
}
+input[type="text"], input[type="search"]
+{
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
.option-name
{
display: flex;
@@ -450,7 +457,8 @@ div.button
}
.icon, .table input[type="checkbox"]::before, .table button.delete,
-#content-help a::before, #dialog-close::before
+#content-help a::before, #dialog-close::before,
+#custom-filters-add button::after
{
background-image: url(options-sprite.png);
display: inline-block;
@@ -461,7 +469,7 @@ div.button
background-position: -0px -0px;
cursor: pointer;
height: 18px;
- width: 18px;
+ min-width: 18px;
}
.icon-update
@@ -565,7 +573,7 @@ div.button
outline: 0px;
padding-bottom: 5px;
vertical-align: text-bottom;
- width: 330px;
+ width: 100%;
}
#whitelisting .controls .button-add span
@@ -609,65 +617,134 @@ div.button
Advanced tab content
*/
-#blocking-list-own .table
+#custom-filters-header
+{
+ padding: 0px 20px;
+ margin-bottom: 10px;
+}
+
+#custom-filters-raw-controls
+{
+ display: flex;
+}
+
+#custom-filters:not(.mode-edit) #custom-filters-raw,
+#custom-filters:not(.mode-edit) #custom-filters-raw-controls,
+#custom-filters.mode-edit #custom-filters-show-edit,
+#custom-filters.mode-edit #custom-filters-list-wrapper
+{
+ display: none;
+}
+
+#custom-filters-raw-save
+{
+ padding: 0px 16px;
+}
+
+#custom-filters .table
{
height: 290px;
overflow: auto;
width: auto;
}
-#blocking-list-own .controls
+#custom-filters-add
{
display: flex;
padding: 0px;
border: none;
}
-#blocking-list-own input[type="text"],
-#blocking-list-own input[type="text"]:focus
+#custom-filters .controls
{
- border: 0px;
- border-bottom: 1px solid;
- border-top: 1px solid;
+ border-top: none;
+}
+
+#custom-filters-raw
+{
+ width: 100%;
+ height: 100%;
+}
+
+#custom-filters-wrapper
+{
+ height: 330px;
+}
+
+#custom-filters input[type="text"]
+{
+ border-width: 1px 0px 1px 0px;
+ border-bottom-style: solid;
+ border-top-style: solid;
border-color: #1E8728;
- box-sizing: border-box;
height: 25px;
- outline: 0px;
-moz-padding-start: 10px;
-webkit-padding-start: 10px;
+ -moz-padding-end: 60px;
+ -webkit-padding-end: 60px;
+ padding-top: 18px;
+ padding-bottom: 18px;
width: 100%;
}
-.icon-enter-blue
+#custom-filters input[type="text"]:focus
{
- background-position: -28px -85px;
- cursor: pointer;
- height: 10px;
- margin: 0px 0px -2px 2px;
- width: 10px;
+ outline: 0px;
}
-#blocking-list-own .input-control
+#custom-filters-add input
{
- position: absolute;
- -webkit-margin-start: -50px;
- -moz-margin-start: -50px;
- bottom: 5px;
+ font-size: 13px;
+ background-color: #F5F5F5;
+}
+
+#custom-filters-add input::-webkit-input-placeholder
+{
+ font-weight: 600;
+}
+#custom-filters-add input::-moz-placeholder
+{
+ font-weight: 600;
}
-#blocking-list-own .input-separator
+#custom-filters-table
{
+ border-top: 1px solid #CDCDCD;
+}
+
+#custom-filters-add button
+{
+ font-size: 14px;
+ -webkit-margin-start: -60px;
+ -moz-margin-start: -60px;
+ -webkit-padding-end: 6px;
+ -moz-padding-end: 6px;
+ cursor: pointer;
+ color: #3A7BA6;
+}
+
+#custom-filters-add button::before
+{
+ content: "";
display: inline-block;
-moz-border-end: 1px solid #CDCDCD;
-webkit-border-end: 1px solid #CDCDCD;
height: 15px;
- margin: 0px 4px -4px 0px;
+ -webkit-margin-end: 10px;
+ -moz-margin-end: 10px;
+ margin-bottom: -2px;
width: 1px;
}
-#blocking-list-own .input-button-text
+#custom-filters-add button::after
{
- font-size: 12px;
+ content: "";
+ background-position: -28px -85px;
+ cursor: pointer;
+ height: 10px;
+ -webkit-margin-start: 6px;
+ -moz-margin-start: 6px;
+ width: 10px;
}
.tooltip, #block-element-explanation a
@@ -807,9 +884,6 @@ body[data-dialog] #dialog-background
#dialog input[type="text"],
#dialog input[type="search"]
{
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
font-size: 16px;
margin-top: 10px;
padding: 5px;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/adblock-plus.git
More information about the Pkg-mozext-commits
mailing list