Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: options.js

Issue 29333819: Issue 2375 - Implement "Blocking lists" section in new options page (Closed)
Patch Set: Small fixes and fix for Object.defineProperty Created Feb. 3, 2016, 2:02 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« background.js ('K') | « options.html ('k') | skin/options.css » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: options.js
===================================================================
--- a/options.js
+++ b/options.js
@@ -24,6 +24,14 @@
var filtersMap = Object.create(null);
var collections = Object.create(null);
var maxLabelId = 0;
+ var getMessage = ext.i18n.getMessage;
+ var filterErrors =
+ {
+ "synchronize_invalid_url": "options_filterList_lastDownload_invalidURL",
+ "synchronize_connection_error": "options_filterList_lastDownload_connectionError",
+ "synchronize_invalid_data": "options_filterList_lastDownload_invalidData",
+ "synchronize_checksum_mismatch": "options_filterList_lastDownload_checksumMismatch"
+ };
function Collection(details)
{
@@ -38,13 +46,22 @@
{
placeholder = document.createElement("li");
placeholder.className = "empty-placeholder";
- placeholder.textContent = ext.i18n.getMessage(text);
+ placeholder.textContent = getMessage(text);
table.appendChild(placeholder);
}
else if (placeholder)
table.removeChild(placeholder);
}
+ Collection.prototype._createElementQuery = function(item)
+ {
+ var access = (item.url || item.text).replace(/'/g, "\\'");
+ return function(container)
+ {
+ return container.querySelector("[data-access='" + access + "']");
+ };
+ };
+
Collection.prototype.addItems = function()
{
var length = Array.prototype.push.apply(this.items, arguments);
@@ -82,7 +99,10 @@
this._setEmpty(table, null);
if (table.hasChildNodes())
- table.insertBefore(listItem, table.childNodes[this.items.indexOf(item)]);
+ {
+ table.insertBefore(listItem,
+ table.childNodes[this.items.indexOf(item)]);
+ }
else
table.appendChild(listItem);
this.updateItem(item);
@@ -98,10 +118,11 @@
return;
this.items.splice(index, 1);
+ var getListElement = this._createElementQuery(item);
for (var i = 0; i < this.details.length; i++)
{
var table = E(this.details[i].id);
- var element = table.childNodes[index];
+ var element = getListElement(table);
// Element gets removed so make sure to handle focus appropriately
var control = element.querySelector(".control");
@@ -146,6 +167,36 @@
var control = element.querySelector(".control[role='checkbox']");
if (control)
control.setAttribute("aria-checked", item.disabled == false);
+
+ var downloadStatus = item.downloadStatus;
+ var dateElement = element.querySelector(".date");
+ var timeElement = element.querySelector(".time");
+ if(dateElement && timeElement)
+ {
+ if (downloadStatus && downloadStatus != "synchronize_ok")
+ {
+ if (downloadStatus in filterErrors)
+ timeElement.textContent = getMessage(filterErrors[downloadStatus]);
+ else
+ timeElement.textContent = item.downloadStatus;
+ }
+ else if (item.lastDownload > 0)
+ {
+ var dateTime = i18n_formatDateTime(item.lastDownload * 1000);
+ dateElement.textContent = dateTime[0];
+ timeElement.textContent = dateTime[1];
+ }
+ else
+ {
+ timeElement.textContent = getMessage("options_filterList_lastDownload_inProgress");
Thomas Greiner 2016/02/03 14:50:14 Whenever adding a subscription I see two issues:
saroyanm 2016/02/03 17:43:12 Done.
+ }
+ }
+ var websiteElement = element.querySelector(".context-menu .website");
+ var sourceElement = element.querySelector(".context-menu .source");
+ if (websiteElement && item.homepage)
+ websiteElement.setAttribute("href", item.homepage);
+ if (sourceElement)
+ sourceElement.setAttribute("href", item.url);
}
};
@@ -155,9 +206,14 @@
for (var i = 0; i < this.details.length; i++)
{
var table = E(this.details[i].id);
- var template = table.querySelector("template");
- table.innerHTML = "";
- table.appendChild(template);
+ var element = table.firstChild;
+ while (element)
+ {
+ if (element.tagName == "LI" && !element.classList.contains("static"))
+ table.removeChild(element);
+ element = element.nextElementSibling;
+ }
+
this._setEmpty(table, this.details[i].emptyText);
}
};
@@ -177,12 +233,11 @@
return true;
}
- function onToggleSubscriptionClick(e)
+ function toggleRemoveSubscription(e)
{
e.preventDefault();
- var checkbox = e.target;
- var subscriptionUrl = checkbox.parentElement.getAttribute("data-access");
- if (checkbox.getAttribute("aria-checked") == "true")
+ var subscriptionUrl = findParentData(e.target, "access", false);
+ if (e.target.getAttribute("aria-checked") == "true")
{
ext.backgroundPage.sendMessage({
type: "subscriptions.remove",
@@ -193,16 +248,28 @@
addEnableSubscription(subscriptionUrl);
}
+ function toggleDisableSubscription(e)
+ {
+ e.preventDefault();
+ var subscriptionUrl = findParentData(e.target, "access", false);
+ ext.backgroundPage.sendMessage(
+ {
+ type: "subscriptions.toggle",
+ keepInstalled: true,
+ url: subscriptionUrl
+ });
+ }
+
function onAddLanguageSubscriptionClick(e)
{
e.preventDefault();
- var url = this.parentNode.getAttribute("data-access");
+ var url = findParentData(this, "access", false);
addEnableSubscription(url);
}
function onRemoveFilterClick()
{
- var filter = this.parentNode.getAttribute("data-access");
+ var filter = findParentData(this, "access", false);
ext.backgroundPage.sendMessage(
{
type: "filters.remove",
@@ -214,7 +281,7 @@
[
{
id: "recommend-list-table",
- onClick: onToggleSubscriptionClick
+ onClick: toggleRemoveSubscription
}
]);
collections.langs = new Collection(
@@ -222,7 +289,7 @@
{
id: "blocking-languages-table",
emptyText: "options_dialog_language_added_empty",
- onClick: onToggleSubscriptionClick
+ onClick: toggleRemoveSubscription
},
{
id: "blocking-languages-dialog-table",
@@ -241,14 +308,14 @@
[
{
id: "acceptableads-table",
- onClick: onToggleSubscriptionClick
+ onClick: toggleRemoveSubscription
}
]);
collections.custom = new Collection(
[
{
id: "custom-list-table",
- onClick: onToggleSubscriptionClick
+ onClick: toggleRemoveSubscription
}
]);
collections.whitelist = new Collection(
@@ -266,23 +333,23 @@
emptyText: "options_customFilters_empty"
}
]);
+ collections.filterLists = new Collection(
+ [
+ {
+ id: "all-filter-lists-table",
+ onClick: toggleDisableSubscription
+ }
+ ]);
- function updateSubscription(subscription)
+ function observeSubscription(subscription)
{
- var subscriptionUrl = subscription.url;
- var knownSubscription = subscriptionsMap[subscriptionUrl];
- if (knownSubscription)
- knownSubscription.disabled = subscription.disabled;
- else
+ function onObjectChanged(change)
{
- getAcceptableAdsURL(function(acceptableAdsUrl)
+ for (var i = 0; i < change.length; i++)
{
- function onObjectChanged()
+ if (change[i].name == "disabled")
{
- for (var i in collections)
- collections[i].updateItem(subscription);
-
- var recommendation = recommendationsMap[subscriptionUrl];
+ var recommendation = recommendationsMap[subscription.url];
if (recommendation && recommendation.type == "ads")
{
if (subscription.disabled == false)
@@ -297,33 +364,57 @@
}
}
}
+ for (var i in collections)
+ collections[i].updateItem(subscription);
+ }
+ }
- if (!Object.observe)
+ if (!Object.observe)
+ {
+ ["disabled", "lastDownload"].forEach(function(property)
+ {
+ subscription["$" + property] = subscription[property];
+ Object.defineProperty(subscription, property,
{
- // Currently only "disabled" property of subscription used for observation
- // but with Advanced tab implementation we should also add more properties.
- ["disabled"].forEach(function(property)
+ get: function()
{
- subscription["$" + property] = subscription[property];
- Object.defineProperty(subscription, property,
+ return this["$" + property];
+ },
+ set: function(newValue)
+ {
+ var oldValue = this["$" + property];
+ this["$" + property] = newValue;
Thomas Greiner 2016/02/03 14:50:14 Detail: Shouldn't this only be set whenever the va
saroyanm 2016/02/03 17:43:12 Done.
+ if (oldValue != newValue)
{
- get: function()
- {
- return this["$" + property];
- },
- set: function(value)
- {
- this["$" + property] = value;
- onObjectChanged();
- }
- });
- });
- }
- else
- {
- Object.observe(subscription, onObjectChanged);
- }
+ var change = Object.create(null);
+ change.name = property;
+ onObjectChanged([change]);
+ }
+ }
+ });
+ });
+ }
+ else
+ {
+ Object.observe(subscription, onObjectChanged);
+ }
+ }
+ function updateSubscription(subscription)
+ {
+ var subscriptionUrl = subscription.url;
+ var knownSubscription = subscriptionsMap[subscriptionUrl];
+ if (knownSubscription)
+ {
+ for (var property in subscription)
+ if (property != "title")
+ knownSubscription[property] = subscription[property];
+ }
+ else
+ {
+ observeSubscription(subscription);
+ getAcceptableAdsURL(function(acceptableAdsUrl)
+ {
var collection = null;
if (subscriptionUrl in recommendationsMap)
{
@@ -381,19 +472,18 @@
subscription.disabled = null;
subscription.downloadStatus = null;
subscription.homepage = null;
- subscription.lastSuccess = null;
var recommendation = Object.create(null);
recommendation.type = element.getAttribute("type");
var prefix = element.getAttribute("prefixes");
if (prefix)
{
prefix = prefix.replace(/\W/g, "_");
- subscription.title = ext.i18n.getMessage("options_language_" + prefix);
+ subscription.title = getMessage("options_language_" + prefix);
}
else
{
var type = recommendation.type.replace(/\W/g, "_");
- subscription.title = ext.i18n.getMessage("common_feature_" + type + "_title");
+ subscription.title = getMessage("common_feature_" + type + "_title");
}
recommendationsMap[subscription.url] = recommendation;
@@ -402,8 +492,24 @@
});
}
+ function findParentData(element, dataName, returnElement)
+ {
+ while (element)
+ {
+ if (element.hasAttribute("data-" + dataName))
+ return returnElement ? element : element.getAttribute("data-" + dataName);
+
+ element = element.parentElement;
+ }
+ return null;
+ }
+
function onClick(e)
{
+ var context = document.querySelector(".show-context-menu");
+ if (context)
+ context.classList.remove("show-context-menu");
+
var element = e.target;
while (true)
{
@@ -469,21 +575,38 @@
document.body.setAttribute("data-tab",
element.getAttribute("data-tab"));
break;
+ case "update-all-subscriptions":
+ ext.backgroundPage.sendMessage(
+ {
+ type: "subscriptions.update"
+ });
+ break;
+ case "open-context-menu":
+ var listItem = findParentData(element, "access", true);
+ if (listItem != context)
+ listItem.classList.add("show-context-menu");
+ break;
+ case "update-subscription":
+ ext.backgroundPage.sendMessage(
+ {
+ type: "subscriptions.update",
+ url: findParentData(element, "access", false)
+ });
+ break;
+ case "remove-subscription":
+ ext.backgroundPage.sendMessage(
+ {
+ type: "subscriptions.remove",
+ url: findParentData(element, "access", false)
+ });
+ break;
}
}
}
function onDOMLoaded()
{
- var recommendationTemplate = document.querySelector("#recommend-list-table template");
- var popularText = ext.i18n.getMessage("options_popular");
- recommendationTemplate.content.querySelector(".popular").textContent = popularText;
- var languagesTemplate = document.querySelector("#all-lang-table template");
- var buttonText = ext.i18n.getMessage("options_button_add");
- languagesTemplate.content.querySelector(".button-add span").textContent = buttonText;
-
populateLists();
-
function onFindLanguageKeyUp()
{
var searchStyle = E("search-style");
@@ -530,7 +653,7 @@
// Initialize interactive UI elements
document.body.addEventListener("click", onClick, false);
- var placeholderValue = ext.i18n.getMessage("options_dialog_language_find");
+ var placeholderValue = getMessage("options_dialog_language_find");
E("find-language").setAttribute("placeholder", placeholderValue);
E("find-language").addEventListener("keyup", onFindLanguageKeyUp, false);
E("whitelisting-textbox").addEventListener("keypress", function(e)
@@ -541,7 +664,7 @@
// Advanced tab
var filterTextbox = document.querySelector("#custom-filters-add input");
- placeholderValue = ext.i18n.getMessage("options_customFilters_textbox_placeholder");
+ placeholderValue = getMessage("options_customFilters_textbox_placeholder");
filterTextbox.setAttribute("placeholder", placeholderValue);
function addCustomFilters()
{
@@ -649,7 +772,7 @@
var subscription = Object.create(null);
subscription.url = acceptableAdsUrl;
subscription.disabled = true;
- subscription.title = ext.i18n.getMessage("options_acceptableAds_description");
+ subscription.title = getMessage("options_acceptableAds_description");
updateSubscription(subscription);
// Load user subscriptions
@@ -755,14 +878,27 @@
switch (action)
{
case "added":
+ updateSubscription(subscription);
+ updateShareLink();
+
+ var knownSubscription = subscriptionsMap[subscription.url];
+ if (knownSubscription)
+ collections.filterLists.addItems(knownSubscription);
+ else
+ collections.filterLists.addItems(subscription);
+ break;
case "disabled":
updateSubscription(subscription);
updateShareLink();
break;
+ case "lastDownload":
+ updateSubscription(subscription);
+ break;
case "homepage":
// TODO: NYI
break;
case "removed":
+ var knownSubscription = subscriptionsMap[subscription.url];
getAcceptableAdsURL(function(acceptableAdsUrl)
{
if (subscription.url == acceptableAdsUrl)
@@ -772,7 +908,6 @@
}
else
{
- var knownSubscription = subscriptionsMap[subscription.url];
if (subscription.url in recommendationsMap)
knownSubscription.disabled = true;
else
@@ -782,6 +917,7 @@
}
}
updateShareLink();
+ collections.filterLists.removeItem(knownSubscription);
});
break;
case "title":
@@ -871,7 +1007,7 @@
ext.backgroundPage.sendMessage(
{
type: "subscriptions.listen",
- filter: ["added", "disabled", "homepage", "removed", "title"]
+ filter: ["added", "disabled", "homepage", "lastDownload", "removed", "title"]
});
window.addEventListener("DOMContentLoaded", onDOMLoaded, false);
« background.js ('K') | « options.html ('k') | skin/options.css » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld