Index: options.js |
=================================================================== |
--- a/options.js |
+++ b/options.js |
@@ -72,6 +72,7 @@ |
if (text) |
listItem.setAttribute("data-search", text.toLowerCase()); |
+ updateTimeDate(listItem, item); |
var control = listItem.querySelector(".control"); |
if (control) |
{ |
@@ -81,7 +82,13 @@ |
this._setEmpty(table, null); |
if (table.hasChildNodes()) |
- table.insertBefore(listItem, table.childNodes[this.items.indexOf(item)]); |
+ { |
+ var index = this.items.indexOf(item); |
+ if (table.firstChild.classList.contains("head")) |
+ index++; |
+ |
+ table.insertBefore(listItem, table.childNodes[index]); |
+ } |
else |
table.appendChild(listItem); |
} |
@@ -96,10 +103,11 @@ |
return; |
this.items.splice(index, 1); |
+ var access = (item.url || item.text).replace(/'/g, "\\'"); |
Thomas Greiner
2016/01/19 11:27:28
I notice the issues with accessing elements by the
saroyanm
2016/01/22 09:55:08
Done, but wouldn't it be simpler to just have a pr
Thomas Greiner
2016/01/25 15:40:28
By returning a function we only create the "access
|
for (var i = 0; i < this.details.length; i++) |
{ |
var table = E(this.details[i].id); |
- var element = table.childNodes[index]; |
+ var element = table.querySelector("[data-access='" + access + "']"); |
element.parentElement.removeChild(element); |
if (this.items.length == 0) |
this._setEmpty(table, this.details[i].emptyText); |
@@ -113,12 +121,79 @@ |
{ |
var table = E(this.details[i].id); |
var template = table.querySelector("template"); |
+ var staticElements = []; |
Thomas Greiner
2016/01/19 11:27:29
This logic is quite complicated. Assuming that you
saroyanm
2016/01/22 09:55:10
Currently we are not using createDocumentFragment
Thomas Greiner
2016/01/25 15:40:27
You could use `Element.nextElementSibling` to avoi
saroyanm
2016/01/26 18:36:15
I assume while you didn't commented under updated
Thomas Greiner
2016/01/27 17:16:56
Thanks for reminding me. I wrote down some parts t
|
+ var element = table.firstChild; |
+ while (element) |
+ { |
+ if (element.tagName == "TEMPLATE" || |
+ (element.classList && element.classList.contains("static"))) |
+ staticElements.push(element); |
+ element = element.nextSibling |
+ } |
+ |
table.innerHTML = ""; |
- table.appendChild(template); |
+ for (var j = 0; j < staticElements.length; j++) |
+ table.appendChild(staticElements[j]); |
+ |
this._setEmpty(table, this.details[i].emptyText); |
} |
}; |
+ Collection.prototype.getTableIds = function() |
Thomas Greiner
2016/01/19 11:27:29
This information is an implementation detail and s
saroyanm
2016/01/22 09:55:09
updated the method to check if the collection has
|
+ { |
+ var ids = []; |
+ for (var i = 0; i < this.details.length; i++) |
+ ids.push(this.details[i].id) |
+ |
+ return ids; |
+ }; |
+ |
+ function updateTimeDate(listItem, subscription) |
+ { |
+ var dateElement = listItem.querySelector(".date"); |
+ var timeElement = listItem.querySelector(".time"); |
+ |
+ if(dateElement && timeElement) |
+ { |
+ if (subscription.downloadStatus && |
+ subscription.downloadStatus != "synchronize_ok") |
+ { |
+ var map = |
+ { |
+ "synchronize_invalid_url": "options_subscription_lastDownload_invalidURL", |
+ "synchronize_connection_error": "options_subscription_lastDownload_connectionError", |
+ "synchronize_invalid_data": "options_subscription_lastDownload_invalidData", |
+ "synchronize_checksum_mismatch": "options_subscription_lastDownload_checksumMismatch" |
+ }; |
+ if (subscription.downloadStatus in map) |
+ timeElement.textContent = ext.i18n.getMessage(map[subscription.downloadStatus]); |
+ else |
+ timeElement.textContent = subscription.downloadStatus; |
+ } |
+ else if (subscription.lastDownload > 0) |
+ { |
+ var timedate = i18n_timeDateStrings(subscription.lastDownload * 1000); |
Thomas Greiner
2016/01/19 11:27:29
This function returns the localized date-time stri
saroyanm
2016/01/22 09:55:10
I see, I was trying to make it consistent with old
Thomas Greiner
2016/01/25 15:40:28
The mere formatting of the string should be generi
saroyanm
2016/01/26 18:36:15
Done.
|
+ if (timedate[1]) |
+ dateElement.textContent = timedate[1].split("/").reverse().join("-"); |
+ else |
+ { |
+ var today = new Date(); |
+ dateElement.textContent = today.getFullYear() + "-" + |
+ today.getMonth()+1 + "-" + today.getDate(); |
+ } |
+ var time = timedate[0].split(":"); |
+ time[2] = time[2].split(" ")[1]; |
+ if (time[2] == "AM" && time[0] == "12") |
+ time[0] = 0; |
+ else if (time[2] == "PM") |
+ time[0] = parseInt(time[0]) + 12; |
+ |
+ time.pop(); |
+ timeElement.textContent = time.join(":"); |
+ } |
+ } |
+ } |
+ |
function onToggleSubscriptionClick(e) |
Thomas Greiner
2016/01/19 11:27:29
I'd suggest renaming this function to "toggleRemov
saroyanm
2016/01/22 09:55:08
Done.
|
{ |
e.preventDefault(); |
@@ -134,6 +209,17 @@ |
addEnableSubscription(subscriptionUrl); |
} |
+ function onToggleSubscriptionStateClick(e) |
+ { |
+ e.preventDefault(); |
+ var subscriptionUrl = e.target.parentNode.getAttribute("data-access"); |
Thomas Greiner
2016/01/19 11:27:29
What about reusing `getParentAccessElement()` sinc
saroyanm
2016/01/22 09:55:10
Done.
Thomas Greiner
2016/01/25 15:40:28
I don't see that you changed anything here.
saroyanm
2016/01/26 18:36:15
Now for sure, thanks.
|
+ ext.backgroundPage.sendMessage( |
+ { |
+ type: "subscriptions.toggleState", |
+ url: subscriptionUrl |
+ }); |
+ } |
+ |
function onAddLanguageSubscriptionClick(e) |
{ |
e.preventDefault(); |
@@ -207,31 +293,40 @@ |
emptyText: "options_customFilters_empty" |
} |
]); |
+ collections.blockingLists = new Collection( |
+ [ |
+ { |
+ id: "blocking-lists-table", |
+ onClick: onToggleSubscriptionStateClick |
+ } |
+ ]); |
- 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() |
+ var property = change[i].name; |
+ if (property == "disabled") |
{ |
- var access = (subscriptionUrl || subscription.text).replace(/'/g, "\\'"); |
+ var access = (subscription.url || |
+ subscription.text).replace(/'/g, "\\'"); |
var elements = document.querySelectorAll("[data-access='" + access + "']"); |
for (var i = 0; i < elements.length; i++) |
{ |
var element = elements[i]; |
+ var tableId = element.parentElement ? element.parentElement.id : ""; |
var control = element.querySelector(".control"); |
- if (control.localName == "input") |
+ if (control && control.localName == "input") |
control.checked = subscription.disabled == false; |
- if (subscriptionUrl in recommendationsMap) |
+ if (subscription.url in recommendationsMap) |
{ |
- var recommendation = recommendationsMap[subscriptionUrl]; |
- if (recommendation.type == "ads") |
+ var recommendation = recommendationsMap[subscription.url]; |
+ var langids = collections.langs.getTableIds(); |
+ var allLangIds = collections.allLangs.getTableIds(); |
+ if (recommendation.type == "ads" && |
+ langids.concat(allLangIds).indexOf(tableId) != -1) |
{ |
if (subscription.disabled == false) |
{ |
@@ -247,33 +342,58 @@ |
} |
} |
} |
+ else |
+ { |
+ var blockingListId = collections.blockingLists.details[0].id; |
+ var blockingList = document.getElementById(blockingListId); |
+ var listItem = blockingList.querySelector("[data-access='" + |
+ subscription.url + "']"); |
+ updateTimeDate(listItem, 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, |
- { |
- get: function() |
- { |
- return this["$" + property]; |
- }, |
- set: function(value) |
- { |
- this["$" + property] = value; |
- onObjectChanged(); |
- } |
- }); |
- }); |
- } |
- else |
- { |
- Object.observe(subscription, onObjectChanged); |
- } |
+ return this["$" + property]; |
+ }, |
+ set: function(value) |
+ { |
+ this["$" + property] = value; |
+ 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) |
+ { |
+ knownSubscription.disabled = subscription.disabled; |
+ knownSubscription.lastDownload = subscription.lastDownload; |
+ } |
+ else |
+ { |
+ observeSubscription(subscription); |
+ getAcceptableAdsURL(function(acceptableAdsUrl) |
+ { |
var collection = null; |
if (subscriptionUrl in recommendationsMap) |
{ |
@@ -366,6 +486,15 @@ |
element = element.parentElement; |
} |
+ function getParentAccessElement() |
Thomas Greiner
2016/01/19 11:27:30
Please avoid declaring functions inside other func
saroyanm
2016/01/22 09:55:09
Good point.
|
+ { |
+ var elementCopy = element; |
+ while (!elementCopy.dataset.access) |
Thomas Greiner
2016/01/19 11:27:29
We can't use `Element.dataset` due to older Safari
saroyanm
2016/01/22 09:55:09
Right, done.
|
+ elementCopy = elementCopy.parentNode; |
+ |
+ return elementCopy; |
+ } |
+ |
var actions = element.getAttribute("data-action").split(","); |
for (var i = 0; i < actions.length; i++) |
{ |
@@ -419,18 +548,83 @@ |
document.body.setAttribute("data-tab", |
element.getAttribute("data-tab")); |
break; |
+ case "update-all-subscriptions": |
+ ext.backgroundPage.sendMessage( |
+ { |
+ type: "subscriptions.updateAll" |
+ }); |
+ break; |
+ case "open-context-menu": |
Thomas Greiner
2016/01/19 11:27:29
We should improve this mechanism because it requir
saroyanm
2016/01/22 09:55:09
Done, but bit hacky, not sure if it's what you mea
Thomas Greiner
2016/01/27 17:16:56
Better but what about replacing it with "toggle-co
saroyanm
2016/01/28 17:00:10
Done.
|
+ var listItem = getParentAccessElement(); |
+ var contextMenu = listItem.querySelector(".content"); |
+ listItem.classList.add("context"); |
+ |
+ function mouseover() |
+ { |
+ contextMenu.addEventListener("mouseout", mouseout, false); |
+ contextMenu.removeEventListener("mouseover", mouseover); |
+ } |
+ function mouseout(event) |
+ { |
+ if (event.target.parentElement != contextMenu) |
+ { |
+ var relatedTarget = event.relatedTarget; |
+ if (relatedTarget.parentNode == this || relatedTarget == this) |
+ return; |
+ listItem.classList.remove("context"); |
+ contextMenu.removeEventListener("mouseout", mouseout); |
+ } |
+ } |
+ |
+ contextMenu.addEventListener("mouseover", mouseover, false); |
+ break; |
+ case "update-now": |
+ ext.backgroundPage.sendMessage( |
+ { |
+ type: "subscriptions.update", |
+ url: getParentAccessElement().dataset.access |
+ }); |
+ break; |
+ case "website": |
+ ext.backgroundPage.sendMessage( |
+ { |
+ type: "subscriptions.website", |
+ url: getParentAccessElement().dataset.access |
+ }); |
+ break; |
+ case "source": |
+ window.open(getParentAccessElement().dataset.access); |
+ break; |
+ case "delete": |
+ ext.backgroundPage.sendMessage( |
+ { |
+ type: "subscriptions.remove", |
+ url: getParentAccessElement().dataset.access |
+ }); |
+ 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; |
+ function updateTemplate(template, selector, messageId) |
Thomas Greiner
2016/01/19 11:27:29
This functionality belongs into "i18n.js". If elem
saroyanm
2016/01/22 09:55:08
Done.
|
+ { |
+ template.content.querySelector(selector). |
+ textContent = ext.i18n.getMessage(messageId); |
+ } |
+ |
+ var template = document.querySelector("#recommend-list-table template"); |
+ updateTemplate(template, ".popular", "options_popular"); |
+ |
+ template = document.querySelector("#all-lang-table template"); |
+ updateTemplate(template, ".button-add span", "options_button_add"); |
+ |
+ template = document.querySelector("#blocking-lists-table template"); |
+ updateTemplate(template, ".update-now", "options_blockingList_update_now"); |
+ updateTemplate(template, ".website", "options_blockingList_website"); |
+ updateTemplate(template, ".source", "options_blockingList_source"); |
+ updateTemplate(template, ".delete", "options_blockingList_delete"); |
populateLists(); |
@@ -705,14 +899,27 @@ |
switch (action) |
{ |
case "added": |
+ updateSubscription(subscription); |
+ updateShareLink(); |
+ |
+ var knownSubscription = subscriptionsMap[subscription.url]; |
+ if (knownSubscription) |
+ collections.blockingLists.addItems(knownSubscription); |
+ else |
+ collections.blockingLists.addItems(subscription); |
+ break; |
case "disabled": |
updateSubscription(subscription); |
updateShareLink(); |
break; |
+ case "updated": |
+ updateSubscription(subscription); |
Thomas Greiner
2016/01/19 11:27:29
That's not what "updated" is meant to notify you o
saroyanm
2016/01/22 09:55:10
Ahh right, thanks for pointing that out. Done.
|
+ break; |
case "homepage": |
// TODO: NYI |
break; |
case "removed": |
+ var knownSubscription = subscriptionsMap[subscription.url]; |
getAcceptableAdsURL(function(acceptableAdsUrl) |
{ |
if (subscription.url == acceptableAdsUrl) |
@@ -722,7 +929,6 @@ |
} |
else |
{ |
- var knownSubscription = subscriptionsMap[subscription.url]; |
if (subscription.url in recommendationsMap) |
knownSubscription.disabled = true; |
else |
@@ -733,6 +939,7 @@ |
} |
updateShareLink(); |
}); |
+ collections.blockingLists.removeItem(knownSubscription); |
break; |
case "title": |
// TODO: NYI |
@@ -821,7 +1028,7 @@ |
ext.backgroundPage.sendMessage( |
{ |
type: "subscriptions.listen", |
- filter: ["added", "disabled", "homepage", "removed", "title"] |
+ filter: ["added", "disabled", "updated", "homepage", "removed", "title"] |
}); |
window.addEventListener("DOMContentLoaded", onDOMLoaded, false); |