- Set the maximum time allowed on the site per day. After this time, has elapsed the site will be blocked.
+ Set the maximum time allowed on the site per day. After this time, has elapsed the site will be blocked.
+ Restrictions can be configured for specific paths on a site as well.
List of sites with notifications:
Show notifications every time you spend a specified time interval on the
- site
+ site. Notifications can be configured for specific paths on a site as well.
diff --git a/src/scripts/activity.js b/src/scripts/activity.js
index 920513c..f6de03a 100644
--- a/src/scripts/activity.js
+++ b/src/scripts/activity.js
@@ -5,27 +5,27 @@ class Activity {
if (this.isValidPage(tab) === true) {
if (tab.id && (tab.id != 0)) {
tabs = tabs || [];
- var domain = extractHostname(tab.url);
+ var url = new Url(tab.url);
var isDifferentUrl = false;
- if (currentTab !== tab.url) {
+ if (!url.isMatch(currentTab)) {
isDifferentUrl = true;
}
- if (this.isNewUrl(domain) && !this.isInBlackList(domain)) {
+ if (this.isNewUrl(url) && !this.isInBlackList(url)) {
var favicon = tab.favIconUrl;
if (favicon === undefined) {
- favicon = 'chrome://favicon/' + domain;
+ favicon = 'chrome://favicon/' + url.host;
}
- var newTab = new Tab(domain, favicon);
+ var newTab = new Tab(url, favicon);
tabs.push(newTab);
}
- if (isDifferentUrl && !this.isInBlackList(domain)) {
- this.setCurrentActiveTab(domain);
- var tabUrl = this.getTab(domain);
+ if (isDifferentUrl && !this.isInBlackList(url)) {
+ this.setCurrentActiveTab(url);
+ var tabUrl = this.getTab(url);
if (tabUrl !== undefined)
tabUrl.incCounter();
- this.addTimeInterval(domain);
+ this.addTimeInterval(url);
}
}
} else this.closeIntervalForCurrentTab();
@@ -41,13 +41,13 @@ class Activity {
isInBlackList(domain) {
if (setting_black_list !== undefined && setting_black_list.length > 0)
- return setting_black_list.find(o => isDomainEquals(extractHostname(o), extractHostname(domain))) !== undefined;
+ return setting_black_list.find(o => o.isMatch(domain)) !== undefined;
else return false;
}
isLimitExceeded(domain, tab) {
if (setting_restriction_list !== undefined && setting_restriction_list.length > 0) {
- var item = setting_restriction_list.find(o => isDomainEquals(extractHostname(o.domain), extractHostname(domain)));
+ var item = setting_restriction_list.find(o => o.url.isMatch(domain));
if (item !== undefined) {
var data = tab.days.find(x => x.date == todayLocalDate());
if (data !== undefined) {
@@ -63,7 +63,7 @@ class Activity {
wasDeferred(domain){
if (deferredRestrictionsList != undefined){
- let defItem = deferredRestrictionsList.find(x => extractHostname(x.site) == extractHostname(domain));
+ let defItem = deferredRestrictionsList.find(x => new Url(x.site).isMatch(domain));
if (defItem != null){
let time = defItem.dateOfDeferred;
if (time + DEFERRED_TIMEOUT > new Date().getTime()){
@@ -84,19 +84,23 @@ class Activity {
isNewUrl(domain) {
if (tabs.length > 0)
- return tabs.find(o => o.url === domain) === undefined;
+ return tabs.find(o => o.url.isMatch(domain)) === undefined;
else return true;
}
getTab(domain) {
if (tabs !== undefined)
- return tabs.find(o => o.url === domain);
+ return tabs.find(o => o.url.isMatch(domain));
}
updateFavicon(tab) {
- var domain = extractHostname(tab.url);
- var currentTab = this.getTab(domain);
+ if (!this.isValidPage(tab)){
+ return;
+ }
+
+ var url = new Url(tab.url);
+ var currentTab = this.getTab(url);
if (currentTab !== null && currentTab !== undefined) {
if (tab.favIconUrl !== undefined && tab.favIconUrl !== currentTab.favicon) {
currentTab.favicon = tab.favIconUrl;
@@ -110,13 +114,8 @@ class Activity {
this.addTimeInterval(domain);
}
- clearCurrentActiveTab() {
- this.closeIntervalForCurrentTab();
- currentTab = '';
- }
-
addTimeInterval(domain) {
- var item = timeIntervalList.find(o => o.domain === domain && o.day == todayLocalDate());
+ var item = timeIntervalList.find(o => o.url.isMatch(domain) && o.day == todayLocalDate());
if (item != undefined) {
if (item.day == todayLocalDate())
item.addInterval();
@@ -132,18 +131,21 @@ class Activity {
}
}
- closeIntervalForCurrentTab() {
- if (currentTab !== '' && timeIntervalList != undefined) {
- var item = timeIntervalList.find(o => o.domain === currentTab && o.day == todayLocalDate());
+ closeIntervalForCurrentTab(preserveCurrentTab) {
+ if (currentTab && timeIntervalList != undefined) {
+ var item = timeIntervalList.find(o => o.url.isMatch(currentTab) && o.day == todayLocalDate());
if (item != undefined)
item.closeInterval();
}
- currentTab = '';
+
+ if (!preserveCurrentTab) {
+ currentTab = null;
+ }
}
isNeedNotifyView(domain, tab){
if (setting_notification_list !== undefined && setting_notification_list.length > 0) {
- var item = setting_notification_list.find(o => isDomainEquals(extractHostname(o.domain), extractHostname(domain)));
+ var item = setting_notification_list.find(o => o.url.isMatch(domain));
if (item !== undefined) {
var today = todayLocalDate();
var data = tab.days.find(x => x.date == today);
diff --git a/src/scripts/background.js b/src/scripts/background.js
index 5da1728..2aa6a7b 100644
--- a/src/scripts/background.js
+++ b/src/scripts/background.js
@@ -35,7 +35,7 @@ function backgroundCheck() {
if (currentWindow.focused) {
var activeTab = currentWindow.tabs.find(t => t.active === true);
if (activeTab !== undefined && activity.isValidPage(activeTab)) {
- var activeUrl = extractHostname(activeTab.url);
+ var activeUrl = new Url(activeTab.url);
var tab = activity.getTab(activeUrl);
if (tab === undefined) {
activity.addTab(activeTab);
@@ -49,7 +49,7 @@ function backgroundCheck() {
});
} else {
if (tab !== undefined) {
- if (currentTab !== tab.url) {
+ if (!tab.url.isMatch(currentTab)) {
activity.setCurrentActiveTab(tab.url);
}
chrome.idle.queryState(parseInt(setting_interval_inactivity), function(state) {
@@ -60,7 +60,7 @@ function backgroundCheck() {
}
}
}
- } else activity.closeIntervalForCurrentTab();
+ } else activity.closeIntervalForCurrentTab(true);
});
}
@@ -146,9 +146,9 @@ function isVideoPlayedOnPage() {
}
function checkDOM(state, activeUrl, tab, activeTab) {
- if (state === 'idle' && isDomainEquals(activeUrl, "youtube.com")) {
+ if (state === 'idle' && activeUrl.isMatch("youtube.com")) {
trackForYT(mainTRacker, activeUrl, tab, activeTab);
- } else if (state === 'idle' && isDomainEquals(activeUrl, "netflix.com")) {
+ } else if (state === 'idle' && activeUrl.isMatch("netflix.com")) {
trackForNetflix(mainTRacker, activeUrl, tab, activeTab);
} else activity.closeIntervalForCurrentTab();
}
@@ -275,13 +275,13 @@ function addListener() {
function loadTabs() {
storage.loadTabs(STORAGE_TABS, function(items) {
tabs = [];
- if (items != undefined) {
- for (var i = 0; i < items.length; i++) {
- tabs.push(new Tab(items[i].url, items[i].favicon, items[i].days, items[i].summaryTime, items[i].counter));
- }
- if (isNeedDeleteTimeIntervalFromTabs)
- deleteTimeIntervalFromTabs();
+ items = items || [];
+
+ for (var i = 0; i < items.length; i++) {
+ tabs.push(new Tab(items[i].url, items[i].favicon, items[i].days, items[i].summaryTime, items[i].counter));
}
+ if (isNeedDeleteTimeIntervalFromTabs)
+ deleteTimeIntervalFromTabs();
});
}
@@ -300,31 +300,46 @@ function deleteYesterdayTimeInterval() {
function loadBlackList() {
storage.getValue(STORAGE_BLACK_LIST, function(items) {
- setting_black_list = items;
+ setting_black_list = [];
+ items = items || [];
+
+ for (var i = 0; i < items.length; i++) {
+ setting_black_list.push(new Url(url));
+ }
})
}
function loadTimeIntervals() {
storage.getValue(STORAGE_TIMEINTERVAL_LIST, function(items) {
timeIntervalList = [];
- if (items != undefined) {
- for (var i = 0; i < items.length; i++) {
- timeIntervalList.push(new TimeInterval(items[i].day, items[i].domain, items[i].intervals));
- }
- deleteYesterdayTimeInterval();
+ items = items || [];
+
+ for (var i = 0; i < items.length; i++) {
+ timeIntervalList.push(new TimeInterval(items[i].day, items[i].url || items[i].domain, items[i].intervals));
}
+ deleteYesterdayTimeInterval();
});
}
function loadRestrictionList() {
storage.getValue(STORAGE_RESTRICTION_LIST, function(items) {
- setting_restriction_list = items;
- })
+ setting_restriction_list = [];
+ items = items || [];
+
+ for (var i = 0; i < items.length; i++) {
+ setting_restriction_list.push(new Restriction(items[i].url || items[i].domain, items[i].time));
+ }
+ });
}
function loadNotificationList() {
storage.getValue(STORAGE_NOTIFICATION_LIST, function(items) {
- setting_notification_list = items;
+ setting_notification_list = [];
+ items = items || [];
+
+ for (var i = 0; i < items.length; i++) {
+ setting_notification_list.push(new Notification(items[i].url || items[i].domain, items[i].time));
+ }
});
}
diff --git a/src/scripts/block.js b/src/scripts/block.js
index 58bd6bb..cfe417e 100644
--- a/src/scripts/block.js
+++ b/src/scripts/block.js
@@ -6,16 +6,15 @@ var restrictionList = [];
document.addEventListener("DOMContentLoaded", function () {
var url = new URL(document.URL);
- blockSiteUrl = url.searchParams.get("url");
- document.getElementById("site").innerText = extractHostname(blockSiteUrl);
+ blockSiteUrl = new Url(url.searchParams.get("url"));
+ document.getElementById("site").innerText = blockSiteUrl;
storage.getValue(STORAGE_RESTRICTION_LIST, function (items) {
- restrictionList = items;
+ restrictionList = (items || []).map(item => new Restriction(item.url || item.domain, item.time));
if (restrictionList === undefined) restrictionList = [];
- var currentItem = restrictionList.find((x) =>
- isDomainEquals(extractHostname(x.domain), extractHostname(blockSiteUrl))
- );
+ var currentItem = restrictionList.find(x => x.url.isMatch(blockSiteUrl));
if (currentItem !== undefined) {
+ document.getElementById("site").innerText = currentItem.url.toString();
document.getElementById("limit").innerText =
convertShortSummaryTimeToString(currentItem.time);
}
@@ -38,7 +37,7 @@ document.addEventListener("DOMContentLoaded", function () {
chrome.tabs.query(
{ currentWindow: true, active: true },
function (tab) {
- chrome.tabs.update(tab.id, { url: blockSiteUrl });
+ chrome.tabs.update(tab.id, { url: blockSiteUrl.href });
}
);
});
diff --git a/src/scripts/chart/chart-core.js b/src/scripts/chart/chart-core.js
index 3626188..c5d32c8 100644
--- a/src/scripts/chart/chart-core.js
+++ b/src/scripts/chart/chart-core.js
@@ -475,7 +475,7 @@ function drawIntervalChart(data) {
})
.attr("height", function (d) {
var offset = getMinutesTo(d.interval) - getMinutesFrom(d.interval);
- if (offset == 0) {
+ if (offset <= 0) {
var offsetSeconds = getSecondsTo(d.interval) - getSecondsFrom(d.interval);
if (offsetSeconds <= 3)
return 0;
diff --git a/src/scripts/common.js b/src/scripts/common.js
index 5a7b8a3..07eea15 100644
--- a/src/scripts/common.js
+++ b/src/scripts/common.js
@@ -64,10 +64,15 @@ function isEmpty(obj) {
}
function convertTimeToSummaryTime(time) {
+ var resultTimeValue = Number(time);
+ if (!isNaN(resultTimeValue)){
+ return resultTimeValue;
+ }
+
var timeValue = time.split(':');
var hour = timeValue[0];
var min = timeValue[1];
- var resultTimeValue = 0;
+ resultTimeValue = 0;
if (hour > 0)
resultTimeValue = hour * 3600;
resultTimeValue += min * 60;
@@ -189,38 +194,6 @@ function getDateFromRange(range) {
}
}
-function isDomainEquals(first, second) {
- if (first === second)
- return true;
- else {
- var resultUrl = function(url) {
- if (url.indexOf('www.') > -1)
- return url.split('www.')[1];
- return url;
- };
-
- if (resultUrl(first) === resultUrl(second))
- return true;
- else return false;
- }
-}
-
-function extractHostname(url) {
- var hostname;
-
- if (url.indexOf("//") > -1) {
- hostname = url.split('/')[2];
- }
- else {
- hostname = url.split('/')[0];
- }
-
- hostname = hostname.split(':')[0];
- hostname = hostname.split('?')[0];
-
- return hostname;
-}
-
function treatAsUTC(date) {
var result = new Date(date);
result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
diff --git a/src/scripts/restriction.js b/src/scripts/restriction.js
index 3b0c8ef..29a4797 100644
--- a/src/scripts/restriction.js
+++ b/src/scripts/restriction.js
@@ -1,15 +1,15 @@
'use strict';
class Restriction {
- constructor(domain, time) {
- this.domain = domain;
+ constructor(url, time) {
+ this.url = new Url(url);
this.time = convertTimeToSummaryTime(time);
}
};
class Notification{
- constructor(domain, time) {
- this.domain = domain;
+ constructor(url, time) {
+ this.url = new Url(url);
this.time = convertTimeToSummaryTime(time);
}
};
\ No newline at end of file
diff --git a/src/scripts/settings.js b/src/scripts/settings.js
index e92ec24..7a628b9 100644
--- a/src/scripts/settings.js
+++ b/src/scripts/settings.js
@@ -116,22 +116,16 @@ function loadSettings() {
let s = item;
});
storage.getValue(STORAGE_BLACK_LIST, function (items) {
- if (items !== undefined)
- blackList = items;
- else blackList = [];
- viewBlackList(items);
+ blackList = (items || []).map(item => new Url(item))
+ viewBlackList(blackList);
});
storage.getValue(STORAGE_RESTRICTION_LIST, function (items) {
- restrictionList = items;
- if (restrictionList === undefined)
- restrictionList = [];
- viewRestrictionList(items);
+ restrictionList = (items || []).map(item => new Restriction(item.url || item.domain, item.time));
+ viewRestrictionList(restrictionList);
});
storage.getValue(STORAGE_NOTIFICATION_LIST, function (items) {
- notifyList = items;
- if (notifyList === undefined)
- notifyList = [];
- viewNotificationList(items);
+ notifyList = (items || []).map(item => new Notification(item.url || item.domain, item.time));
+ viewNotificationList(notifyList);
});
storage.getValue(STORAGE_NOTIFICATION_MESSAGE, function (mess) {
document.getElementById('notifyMessage').value = mess;
@@ -250,7 +244,7 @@ function viewNotificationList(items) {
function viewRestrictionList(items) {
if (items !== undefined) {
for (var i = 0; i < items.length; i++) {
- addDomainToEditableListBox(items[i], 'restrictionsList', actionEditSite, deleteRestrictionSite, updateItemFromResctrictoinList, updateRestrictionList);
+ addDomainToEditableListBox(items[i], 'restrictionsList', actionEditSite, deleteRestrictionSite, updateItemFromRestrictionList, updateRestrictionList);
}
}
}
@@ -332,7 +326,7 @@ function viewNotify(elementName) {
function actionAddRectrictionToList(newSite, newTime) {
if (!isContainsRestrictionSite(newSite)) {
var restriction = new Restriction(newSite, newTime);
- addDomainToEditableListBox(restriction, 'restrictionsList', actionEditSite, deleteRestrictionSite, updateItemFromResctrictoinList, updateRestrictionList);
+ addDomainToEditableListBox(restriction, 'restrictionsList', actionEditSite, deleteRestrictionSite, updateItemFromRestrictionList, updateRestrictionList);
if (restrictionList === undefined)
restrictionList = [];
restrictionList.push(restriction);
@@ -404,7 +398,7 @@ function addDomainToEditableListBox(entity, elementId, actionEdit, actionDelete,
var domainLbl = document.createElement('input');
domainLbl.type = 'text';
domainLbl.classList.add('readonly-input', 'inline-block', 'element-item');
- domainLbl.value = entity.domain;
+ domainLbl.value = entity.url.toString();
domainLbl.readOnly = true;
domainLbl.setAttribute('name', 'domain');
@@ -456,7 +450,7 @@ function deleteBlackSite(e) {
function deleteRestrictionSite(e) {
var targetElement = e.path[1];
var itemValue = targetElement.querySelector("[name='domain']").value;
- var item = restrictionList.find(x => x.domain == itemValue);
+ var item = restrictionList.find(x => x.url.isMatch(itemValue));
restrictionList.splice(restrictionList.indexOf(item), 1);
document.getElementById('restrictionsList').removeChild(targetElement);
updateRestrictionList();
@@ -465,7 +459,7 @@ function deleteRestrictionSite(e) {
function deleteNotificationSite(e) {
var targetElement = e.path[1];
var itemValue = targetElement.querySelector("[name='domain']").value;
- var item = notifyList.find(x => x.domain == itemValue);
+ var item = notifyList.find(x => x.url.isMatch(itemValue));
notifyList.splice(notifyList.indexOf(item), 1);
document.getElementById('notifyList').removeChild(targetElement);
updateNotificationList();
@@ -501,23 +495,23 @@ function actionEditSite(e, actionUpdateTimeFromList, actionUpdateList) {
}
function isContainsRestrictionSite(domain) {
- return restrictionList.find(x => x.domain == domain) != undefined;
+ return restrictionList.find(x => x.url.isMatch(domain)) != undefined;
}
function isContainsNotificationSite(domain) {
- return notifyList.find(x => x.domain == domain) != undefined;
+ return notifyList.find(x => x.url.isMatch(domain)) != undefined;
}
function isContainsBlackSite(domain) {
- return blackList.find(x => x == domain) != undefined;
+ return blackList.find(x => x.isMatch(domain)) != undefined;
}
-function updateItemFromResctrictoinList(domain, time) {
- restrictionList.find(x => x.domain === domain).time = convertTimeToSummaryTime(time);
+function updateItemFromRestrictionList(domain, time) {
+ restrictionList.find(x => x.url.isMatch(domain)).time = convertTimeToSummaryTime(time);
}
function updateItemFromNotifyList(domain, time) {
- notifyList.find(x => x.domain === domain).time = convertTimeToSummaryTime(time);
+ notifyList.find(x => x.url.isMatch(domain)).time = convertTimeToSummaryTime(time);
}
function updateBlackList() {
diff --git a/src/scripts/tab.js b/src/scripts/tab.js
index 809d405..7e22c2e 100644
--- a/src/scripts/tab.js
+++ b/src/scripts/tab.js
@@ -2,7 +2,7 @@
class Tab {
constructor(url, favicon, days, summary, counter) {
- this.url = url;
+ this.url = new Url(url);
this.favicon = favicon;
if (summary !== undefined)
this.summaryTime = summary;
diff --git a/src/scripts/timeInterval.js b/src/scripts/timeInterval.js
index 3862549..36ebf88 100644
--- a/src/scripts/timeInterval.js
+++ b/src/scripts/timeInterval.js
@@ -1,8 +1,8 @@
'use strict';
class TimeInterval {
- constructor(day, domain, intervals) {
- this.domain = domain;
+ constructor(day, url, intervals) {
+ this.url = new Url(url);
if (intervals != undefined)
this.intervals = intervals;
else this.intervals = [];
diff --git a/src/scripts/ui.js b/src/scripts/ui.js
index 83e9175..635f7c5 100644
--- a/src/scripts/ui.js
+++ b/src/scripts/ui.js
@@ -98,12 +98,13 @@ class UI {
this.getTableOfSite().appendChild(document.createElement('hr'));
}
- setActiveTooltipe(currentTab) {
- if (currentTab !== '') {
- var element = document.getElementById(currentTab);
+ setActiveTooltip(currentTab) {
+ if (!!currentTab) {
+ const host = currentTab.host;
+ var element = document.getElementById(host);
if (element !== null) {
var event = new Event("mouseenter");
- document.getElementById(currentTab).dispatchEvent(event);
+ document.getElementById(host).dispatchEvent(event);
}
}
}
@@ -162,9 +163,10 @@ class UI {
addLineToTableOfSite(tab, currentTab, summaryTime, typeOfList, counter, blockName) {
var div = document.createElement('div');
+ var tabUrlString = tab.url.host;
div.addEventListener('mouseenter', function() {
if (document.getElementById('chart').innerHTML !== '') {
- var item = document.getElementById(tab.url);
+ var item = document.getElementById(tabUrlString);
if (item !== null) {
item.dispatchEvent(new Event('mouseenter'));
item.classList.add('mouse-over');
@@ -176,7 +178,7 @@ class UI {
});
div.addEventListener('mouseout', function() {
if (document.getElementById('chart').innerHTML !== '') {
- var item = document.getElementById(tab.url);
+ var item = document.getElementById(tabUrlString);
if (item !== null) {
item.classList.remove('mouse-over');
} else document.getElementById('Others').classList.remove('mouse-over');
@@ -193,10 +195,10 @@ class UI {
divForImg.classList.add('block-img');
divForImg.appendChild(img);
- var spanUrl = this.createElement('span', ['span-url'], tab.url);
- spanUrl.setAttribute('href', 'https://' + tab.url);
+ var spanUrl = this.createElement('span', ['span-url'], tabUrlString);
+ spanUrl.setAttribute('href', 'https://' + tabUrlString);
- if (tab.url == currentTab) {
+ if (tab.url.isMatch(currentTab)) {
var divForImage = document.createElement('div');
div.classList.add('span-active-url');
var imgCurrentDomain = document.createElement('img');
@@ -212,16 +214,9 @@ class UI {
if (typeOfList !== undefined && typeOfList === TypeListEnum.ToDay) {
if (restrictionList !== undefined && restrictionList.length > 0) {
- var item = restrictionList.find(x => isDomainEquals(x.domain, tab.url));
- if (item !== undefined) {
- var divLimit = this.createElement('div', ['tooltip', 'inline-block']);
- var limitIcon = this.createElement('img', ['margin-left-5', 'tooltip']);
- limitIcon.height = 15;
- limitIcon.src = '/icons/limit.png';
- var tooltip = this.createElement('span', ['tooltiptext'], "Daily limit is " + convertShortSummaryTimeToLongString(item.time));
- divLimit = this.appendChild(divLimit, [limitIcon, tooltip]);
- spanUrl.appendChild(divLimit);
- }
+ this.addRestrictionIcon(tab, restrictionList, spanUrl);
+ } else {
+ getLimitsListFromStorage(() => this.addRestrictionIcon(tab, restrictionList, spanUrl));
}
}
@@ -241,6 +236,19 @@ class UI {
this.getTableOfSite().appendChild(div);
}
+ addRestrictionIcon(tab, restrictions, spanUrl) {
+ var item = restrictions.find(x => x.url.isMatch(tab.url));
+ if (item !== undefined) {
+ var divLimit = this.createElement('div', ['tooltip', 'inline-block']);
+ var limitIcon = this.createElement('img', ['margin-left-5', 'tooltip']);
+ limitIcon.height = 15;
+ limitIcon.src = '/icons/limit.png';
+ var tooltip = this.createElement('span', ['tooltiptext'], "Daily limit is " + convertShortSummaryTimeToLongString(item.time));
+ divLimit = this.appendChild(divLimit, [limitIcon, tooltip]);
+ spanUrl.appendChild(divLimit);
+ }
+ }
+
createElementsForTotalTime(summaryTime, typeOfList, parentElement) {
var arr = getArrayTime(summaryTime);
var isNextPartActiv = false;
@@ -318,8 +326,8 @@ class UI {
getDateRange() {
return {
- 'from': new Date(document.getElementById('dateFrom').value),
- 'to': new Date(document.getElementById('dateTo').value)
+ 'from': new Date(document.getElementById('dateFrom').value + ' '),
+ 'to': new Date(document.getElementById('dateTo').value + ' ')
};
}
diff --git a/src/scripts/url.js b/src/scripts/url.js
new file mode 100644
index 0000000..f41d88a
--- /dev/null
+++ b/src/scripts/url.js
@@ -0,0 +1,66 @@
+"use strict";
+
+class Url {
+ constructor(url) {
+ if (url instanceof URL) {
+ item = url;
+ } else if (typeof url === "string") {
+ if (url.indexOf("//") === -1) {
+ url = "http://" + url;
+ }
+ } else {
+ this.href = url.href;
+ this.host = url.host;
+ this.path = url.path;
+ return;
+ }
+
+ var item = new URL(url);
+
+ this.href = item.href;
+ this.host = item.hostname;
+ this.path = item.pathname === "/" ? "" : item.pathname;
+ }
+
+ isMatch(url) {
+ if (!url) {
+ return false;
+ }
+
+ try {
+ url = url instanceof Url ? url : new Url(url);
+ } catch {
+ return false;
+ }
+
+ return this.isHostMatch(url.host) && this.isPathMatch(url.path);
+ }
+
+ isHostMatch(host) {
+ if (host === this.host) {
+ return true;
+ }
+
+ var thisHostParts = this.host.split(".").reverse();
+
+ var hostParts = host.split(".").reverse();
+
+ var result = thisHostParts.every((part, i) => hostParts[i] === part);
+
+ return result;
+ }
+
+ isPathMatch(path) {
+ var result = this.path === '' || path === this.path || path.indexOf(this.path) === 0;
+
+ return result;
+ }
+
+ getId() {
+ return this.host + this.path.replace(/\//g, "-");
+ }
+
+ toString() {
+ return this.host + this.path;
+ }
+}
diff --git a/src/scripts/webact.js b/src/scripts/webact.js
index c9d69e4..0df7104 100644
--- a/src/scripts/webact.js
+++ b/src/scripts/webact.js
@@ -147,8 +147,16 @@ window.addEventListener('click', function (e) {
}
});
-function getLimitsListFromStorage() {
- storage.loadTabs(STORAGE_RESTRICTION_LIST, getLimitsListFromStorageCallback);
+function getLimitsListFromStorage(callback) {
+ callback = callback || (() => {});
+ if (!restrictionList) {
+ storage.loadTabs(STORAGE_RESTRICTION_LIST, items => {
+ getLimitsListFromStorageCallback(items);
+ callback();
+ });
+ } else {
+ callback();
+ }
}
function getDataFromStorage() {
@@ -163,9 +171,7 @@ function getDataFromStorageByDays() {
}
function getLimitsListFromStorageCallback(items) {
- if (items !== undefined)
- restrictionList = items;
- else restrictionList = [];
+ restrictionList = (items || []).map(item => new Restriction(item.url, item.time));
}
function fillEmptyBlock() {
@@ -176,88 +182,99 @@ function fillEmptyBlock() {
function getTabsFromStorage(tabs) {
tabsFromStorage = tabs;
targetTabs = [];
-
+
ui.clearUI();
if (tabs === null) {
- ui.fillEmptyBlock('chart');
- return;
+ ui.fillEmptyBlock("chart");
+ return;
}
-
+
var counterOfSite;
if (currentTypeOfList === TypeListEnum.All) {
- targetTabs = tabs.sort(function (a, b) {
- return b.summaryTime - a.summaryTime;
- });
-
- if (targetTabs.length > 0) {
- totalTime = getTotalTime(targetTabs);
- stat.allDaysTime = totalTime;
-
- } else {
- ui.fillEmptyBlock('chart');
- return;
- }
-
- counterOfSite = tabs.length;
+ targetTabs = tabs;
+ if (targetTabs.length > 0) {
+ totalTime = getTotalTime(targetTabs, currentTypeOfList);
+ stat.allDaysTime = totalTime;
+ } else {
+ ui.fillEmptyBlock("chart");
+ return;
+ }
+
+ counterOfSite = tabs.length;
}
if (currentTypeOfList === TypeListEnum.ToDay) {
- targetTabs = tabs.filter(x => x.days.find(s => s.date === todayLocalDate()));
- counterOfSite = targetTabs.length;
- if (targetTabs.length > 0) {
- targetTabs = targetTabs.sort(function (a, b) {
- return b.days.find(s => s.date === todayLocalDate()).summary - a.days.find(s => s.date === todayLocalDate()).summary;
- });
-
- totalTime = getTotalTime(targetTabs);
- stat.todayTime = totalTime;
- } else {
- ui.fillEmptyBlock('chart');
- return;
- }
+ targetTabs = tabs.filter((x) =>
+ x.days.find((s) => s.date === todayLocalDate())
+ );
+ counterOfSite = targetTabs.length;
+ if (targetTabs.length > 0) {
+ targetTabs = targetTabs.sort(function (a, b) {
+ return (
+ b.days.find((s) => s.date === todayLocalDate()).summary -
+ a.days.find((s) => s.date === todayLocalDate()).summary
+ );
+ });
+
+ totalTime = getTotalTime(targetTabs, currentTypeOfList);
+ stat.todayTime = totalTime;
+ } else {
+ ui.fillEmptyBlock("chart");
+ return;
+ }
}
-
+
if (currentTypeOfList === TypeListEnum.All)
- ui.addTableHeader(currentTypeOfList, counterOfSite, totalTime, getFirstDay());
+ ui.addTableHeader(
+ currentTypeOfList,
+ counterOfSite,
+ totalTime,
+ getFirstDay()
+ );
if (currentTypeOfList === TypeListEnum.ToDay)
- ui.addTableHeader(currentTypeOfList, counterOfSite, totalTime);
-
+ ui.addTableHeader(currentTypeOfList, counterOfSite, totalTime);
+
var currentTab = getCurrentTab();
-
+
var tabsForChart = [];
var summaryCounter = 0;
- for (var i = 0; i < targetTabs.length; i++) {
- var summaryTime;
- var counter;
- if (currentTypeOfList === TypeListEnum.ToDay) {
- summaryTime = targetTabs[i].days.find(x => x.date == todayLocalDate()).summary;
- let item = targetTabs[i].days.find(x => x.date == todayLocalDate());
- if (item != null)
- counter = item.counter;
- }
- if (currentTypeOfList === TypeListEnum.All) {
- summaryTime = targetTabs[i].summaryTime;
- counter = targetTabs[i].counter;
- }
-
- summaryCounter += counter;
-
- if (currentTypeOfList === TypeListEnum.ToDay || (currentTypeOfList === TypeListEnum.All && i <= 30))
- ui.addLineToTableOfSite(targetTabs[i], currentTab, summaryTime, currentTypeOfList, counter);
- else
- ui.addExpander();
-
- if (i <= 8)
- addTabForChart(tabsForChart, targetTabs[i].url, summaryTime, counter);
- else addTabOthersForChart(tabsForChart, summaryTime);
+ var tabGroups = getTabGroups(targetTabs, currentTypeOfList);
+
+ for (var i = 0; i < tabGroups.length; i++) {
+ var summaryTime = 0;
+ var counter = 0;
+ var tabGroup = tabGroups[i];
+
+ summaryTime = tabGroup.summaryTime;
+ counter = tabGroup.counter;
+
+ summaryCounter += counter;
+
+ const targetTab = tabGroup.tabs.find(t => t.url.isMatch(currentTab)) || tabGroup.tabs[0];
+
+ if (
+ currentTypeOfList === TypeListEnum.ToDay ||
+ (currentTypeOfList === TypeListEnum.All && i <= 30)
+ )
+ ui.addLineToTableOfSite(
+ targetTab,
+ currentTab,
+ summaryTime,
+ currentTypeOfList,
+ counter
+ );
+ else ui.addExpander();
+
+ var tabForChartUrl = i <= 8 ? tabGroup.host : 'Others';
+ addTabForChart(tabsForChart, tabForChartUrl, summaryTime, counter);
}
-
+
ui.addHrAfterTableOfSite();
ui.createTotalBlock(totalTime, currentTypeOfList, summaryCounter);
ui.drawChart(tabsForChart);
- ui.setActiveTooltipe(currentTab);
-
+ ui.setActiveTooltip(currentTab);
+
ui.removePreloader();
-}
+ }
function getTabsForTimeChart(timeIntervals) {
var resultArr = [];
@@ -265,14 +282,48 @@ function getTabsForTimeChart(timeIntervals) {
timeIntervals.forEach(function (data) {
if (data.day == todayLocalDate()) {
data.intervals.forEach(function (interval) {
- resultArr.push({ 'domain': data.domain, 'interval': interval });
+ resultArr.push({ 'domain': data.url.host, 'interval': interval });
});
}
});
}
+
return resultArr;
}
+function getTabGroups(tabs, typeOfList, date) {
+ var result = [];
+
+ var tabGroups = groupTabsByHost(tabs);
+
+ for(const host in tabGroups){
+ var groupedTabs = tabGroups[host];
+
+ result.push({
+ host: host,
+ counter: getTotalCount(groupedTabs, typeOfList, date),
+ summaryTime: getTotalTime(groupedTabs, typeOfList, date),
+ tabs: groupedTabs
+ });
+ }
+
+ result.sort(function (a, b) {
+ return b.summaryTime - a.summaryTime;
+ });
+
+ return result;
+}
+
+function groupTabsByHost(tabs) {
+ var tabGroups = tabs.reduce((groups, tab) => {
+ var key = tab.url.host;
+ (groups[key] = groups[key] || []).push(tab);
+ return groups;
+ }, {});
+
+ return tabGroups;
+}
+
function getTabsForExpander() {
if (tabsFromBackground != undefined && tabsFromBackground != null && tabsFromBackground.length > 0)
getTabsFromStorageForExpander(tabsFromBackground);
@@ -283,34 +334,27 @@ function getTimeIntervalList() {
}
function drawTimeChart(items) {
- ui.drawTimeChart(getTabsForTimeChart(items));
+ var timeIntervalList = [];
+ items = items || [];
+
+ for (var i = 0; i < items.length; i++) {
+ timeIntervalList.push(new TimeInterval(items[i].day, items[i].url || items[i].domain, items[i].intervals));
+ }
+
+ ui.drawTimeChart(getTabsForTimeChart(timeIntervalList));
}
function getTabsFromStorageForExpander(tabs) {
tabsFromStorage = tabs;
targetTabs = [];
- targetTabs = tabs.sort(function (a, b) {
- return b.summaryTime - a.summaryTime;
- });
-
var currentTab = getCurrentTab();
+
+ var tabGroups = getTabGroups(tabs, currentTypeOfList);
- for (var i = 31; i < targetTabs.length; i++) {
- var summaryTime;
- var counter;
- if (currentTypeOfList === TypeListEnum.ToDay) {
- summaryTime = targetTabs[i].days.find(x => x.date == todayLocalDate()).summary;
- let item = targetTabs[i].days.find(x => x.date == todayLocalDate());
- if (item != undefined)
- counter = item.counter;
- }
- if (currentTypeOfList === TypeListEnum.All) {
- summaryTime = targetTabs[i].summaryTime;
- counter = targetTabs[i].counter;
- }
-
- ui.addLineToTableOfSite(targetTabs[i], currentTab, summaryTime, currentTypeOfList, counter);
+ for (var i = 31; i < tabGroups.length; i++) {
+ var tabGroup = tabGroups[i];
+ ui.addLineToTableOfSite(tabGroup, currentTab, tabGroup.summaryTime, currentTypeOfList, tabGroup.counter);
}
var table = ui.getTableOfSite();
@@ -318,16 +362,38 @@ function getTabsFromStorageForExpander(tabs) {
ui.addHrAfterTableOfSite();
}
-function getTotalTime(tabs) {
+function getTotalCount(tabs, typeofList, date) {
var total;
- if (currentTypeOfList === TypeListEnum.ToDay) {
- var summaryTimeList = tabs.map(function (a) { return a.days.find(s => s.date === todayLocalDate()).summary; });
- total = summaryTimeList.reduce(function (a, b) { return a + b; })
+ if (typeofList === TypeListEnum.ToDay) {
+ date = date || todayLocalDate();
+ total = tabs.reduce((tot, tab) => {
+ let item = tab.days.find((x) => x.date == date);
+ return tot + (item.counter || 0);
+ }, 0);
+ } else if (typeofList === TypeListEnum.All) {
+ total = tabs.reduce((tot, tab) => tot + tab.counter, 0);
}
- if (currentTypeOfList === TypeListEnum.All) {
- var summaryTimeList = tabs.map(function (a) { return a.summaryTime; });
- total = summaryTimeList.reduce(function (a, b) { return a + b; })
+
+ return total;
+}
+
+
+function getTotalTime(tabs, typeOfList, date) {
+ var total;
+ switch(typeOfList){
+ case TypeListEnum.ByDays:
+ case TypeListEnum.ToDay:
+ date = date || todayLocalDate();
+ var summaryTimeList = tabs.map(function (a) { return a.days.find(s => s.date === date).summary; });
+ total = summaryTimeList.reduce(function (a, b) { return a + b; })
+ break;
+ case TypeListEnum.All:
+ var summaryTimeList = tabs.map(function (a) { return a.summaryTime; });
+ total = summaryTimeList.reduce(function (a, b) { return a + b; })
+ break;
+ default:
}
+
return total;
}
@@ -350,26 +416,19 @@ function getCurrentTab() {
return chrome.extension.getBackgroundPage().currentTab;
}
-function addTabForChart(tabsForChart, url, time, counter) {
- tabsForChart.push({
- 'url': url,
- 'percentage': getPercentageForChart(time),
- 'summary': time,
- 'visits': counter
- });
-}
-
-function addTabOthersForChart(tabsForChart, summaryTime) {
- var tab = tabsForChart.find(x => x.url == 'Others');
+function addTabForChart(tabsForChart, url, summaryTime, counter) {
+ var tab = tabsForChart.find(x => x.url == url);
if (tab === undefined) {
tabsForChart.push({
- 'url': 'Others',
+ 'url': url,
'percentage': getPercentageForChart(summaryTime),
- 'summary': summaryTime
+ 'summary': summaryTime,
+ 'visits': counter
});
} else {
tab['summary'] += summaryTime;
tab['percentage'] = getPercentageForChart(tab['summary']);
+ tab['visits'] += counter;
}
}
@@ -511,12 +570,15 @@ function getTabsFromStorageByDay(day, blockName) {
content.classList.add('content-inner');
content.id = blockName + '_content';
document.getElementById(blockName).appendChild(content);
- for (var i = 0; i < targetTabs.length; i++) {
- var summaryTime, counter;
- summaryTime = targetTabs[i].days.find(x => x.date == day).summary;
- counter = targetTabs[i].days.find(x => x.date == day).counter;
- ui.addLineToTableOfSite(targetTabs[i], currentTab, summaryTime, TypeListEnum.ByDays, counter, blockName + '_content');
+ var tabGroups = getTabGroups(targetTabs, TypeListEnum.ByDays, day);
+
+ for (const tabGroup of tabGroups){
+ var summaryTime = tabGroup.summaryTime;
+ var counter = tabGroup.counter;
+ const targetTab = tabGroup.tabs.find(t => t.url.isMatch(currentTab)) || tabGroup.tabs[0];
+
+ ui.addLineToTableOfSite(targetTab, currentTab, summaryTime, TypeListEnum.ByDays, counter, blockName + '_content');
}
}
diff --git a/src/style/settings.css b/src/style/settings.css
index f71759d..5c7fb35 100644
--- a/src/style/settings.css
+++ b/src/style/settings.css
@@ -225,13 +225,13 @@ input[type="button"]:hover {
background-color: #555;
color: #fff;
text-align: center;
- padding: 5px 0;
+ padding: 5px;
border-radius: 6px;
/* Position the tooltip text */
position: absolute;
z-index: 1;
- transform: translateX(-50%) translateY(-150%);
+ transform: translateX(-50%) translateY(-120%);
/* Fade in tooltip */
opacity: 0;