diff --git a/images/checkbox.png b/images/checkbox.png
deleted file mode 100644
index 0ea9e84..0000000
Binary files a/images/checkbox.png and /dev/null differ
diff --git a/images/checkedbox.png b/images/checkedbox.png
deleted file mode 100644
index a354faf..0000000
Binary files a/images/checkedbox.png and /dev/null differ
diff --git a/images/checkwhite.png b/images/checkwhite.png
deleted file mode 100644
index 6eb37e7..0000000
Binary files a/images/checkwhite.png and /dev/null differ
diff --git a/images/close.png b/images/close.png
deleted file mode 100644
index a16beae..0000000
Binary files a/images/close.png and /dev/null differ
diff --git a/images/close.svg b/images/close.svg
new file mode 100644
index 0000000..e2144b7
--- /dev/null
+++ b/images/close.svg
@@ -0,0 +1,13 @@
+
+
+
diff --git a/images/closeorange.png b/images/closeorange.png
deleted file mode 100644
index 9ce56bd..0000000
Binary files a/images/closeorange.png and /dev/null differ
diff --git a/images/file.png b/images/file.png
deleted file mode 100644
index 6c1293a..0000000
Binary files a/images/file.png and /dev/null differ
diff --git a/images/file.svg b/images/file.svg
new file mode 100644
index 0000000..0bab034
--- /dev/null
+++ b/images/file.svg
@@ -0,0 +1,14 @@
+
+
+
diff --git a/images/menuclose.png b/images/menuclose.png
deleted file mode 100644
index 0ead943..0000000
Binary files a/images/menuclose.png and /dev/null differ
diff --git a/images/menufile.png b/images/menufile.png
deleted file mode 100644
index 2037fd9..0000000
Binary files a/images/menufile.png and /dev/null differ
diff --git a/images/menustar.png b/images/menustar.png
deleted file mode 100644
index 920757e..0000000
Binary files a/images/menustar.png and /dev/null differ
diff --git a/images/star-full.png b/images/star-full.png
deleted file mode 100644
index 0ec84aa..0000000
Binary files a/images/star-full.png and /dev/null differ
diff --git a/images/star.png b/images/star.png
deleted file mode 100644
index 6d48f97..0000000
Binary files a/images/star.png and /dev/null differ
diff --git a/images/star.svg b/images/star.svg
new file mode 100644
index 0000000..e06d678
--- /dev/null
+++ b/images/star.svg
@@ -0,0 +1,17 @@
+
+
+
diff --git a/manifest.json b/manifest.json
index fc14941..84ade30 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "Tabzie",
- "version": "1.2.2",
+ "version": "1.2.3",
"description": "A minimal tab organizer",
"homepage_url": "https://github.com/fgkolf/tabzie",
"icons": {
diff --git a/popup/index.html b/popup/index.html
index 0765c22..4de2d8e 100644
--- a/popup/index.html
+++ b/popup/index.html
@@ -4,12 +4,17 @@
-
+
+
+
+
{
const menu = document.getElementById('menu');
- const checkboxes = document.getElementsByClassName('checkbox');
+ const checkboxes = document.querySelectorAll("input[type='checkbox']");
if (on) {
- menu.style.display = 'grid';
+ menu.classList.add('open');
Array.prototype.forEach.call(checkboxes, (el) => {
- el.style.display = 'block';
+ el.style.display = 'grid';
});
} else {
- menu.style.display = 'none';
+ menu.classList.remove('open');
Array.prototype.forEach.call(checkboxes, (el) => {
- el.classList.remove('checked');
+ el.checked = false;
if (el.id === 'menuCheckbox') {
return;
}
@@ -57,14 +55,12 @@ const onMenuXClicked = () => {
const onCheckBoxClicked = (e) => {
const { id, url } = e.target.dataset;
- if (checkedIds.includes(id)) {
- checkedIds.splice(checkedIds.indexOf(id), 1);
- checkedUrls.splice(checkedUrls.indexOf(url), 1);
- e.target.classList.remove('checked');
- } else {
+ if (e.target.checked) {
checkedIds.push(id);
checkedUrls.push(url);
- e.target.classList.add('checked');
+ } else {
+ checkedIds.splice(checkedIds.indexOf(id), 1);
+ checkedUrls.splice(checkedUrls.indexOf(url), 1);
}
if (checkedIds.length === 0) {
@@ -76,24 +72,20 @@ const onCheckBoxClicked = (e) => {
};
const onMenuCheckboxClicked = (e) => {
- const isChecked = e.target.classList.contains('checked');
- if (isChecked) {
- e.target.classList.remove('checked');
- } else {
- e.target.classList.add('checked');
- }
checkedIds = [];
checkedUrls = [];
+
+ if (!e.target.checked) {
+ setMenuVisibility(false);
+ return;
+ }
+
// eslint-disable-next-line no-undef
- const checkboxes = container.getElementsByClassName('checkbox');
+ const checkboxes = container.querySelectorAll("input[type='checkbox']");
Array.prototype.forEach.call(checkboxes, (el) => {
- if (isChecked) {
- setMenuVisibility(false);
- } else {
- el.setAttribute('class', 'checkbox checked');
- checkedIds.push(el.dataset.id);
- checkedUrls.push(el.dataset.url);
- }
+ el.checked = true;
+ checkedIds.push(el.dataset.id);
+ checkedUrls.push(el.dataset.url);
});
};
@@ -169,10 +161,10 @@ const onStarClicked = async ({ target }) => {
const { url } = target.dataset;
const bkmNode = await browser.bookmarks.search({ url });
if (bkmNode && bkmNode.length > 0) {
- target.style.backgroundImage = starBtnUri;
+ target.classList.remove('full');
browser.bookmarks.remove(bkmNode[0].id);
} else {
- target.style.backgroundImage = starBtnFullUri;
+ target.classList.add('full');
browser.bookmarks.create({
url,
title: url,
@@ -211,16 +203,16 @@ const onImageEnter = async (e) => {
const starButton = document.getElementById(`star_${id}`);
const bkmNode = await browser.bookmarks.search({ url });
if (bkmNode && bkmNode.length > 0) {
- starButton.style.backgroundImage = starBtnFullUri;
+ starButton.classList.add('full');
} else {
- starButton.style.backgroundImage = starBtnUri;
+ starButton.classList.remove('full');
}
}
// if only one tab don't show checkbox
// eslint-disable-next-line no-undef
if (container.childElementCount > 1) {
const checkbox = document.getElementById(`checkbox_${id}`);
- checkbox.style.display = 'block';
+ checkbox.style.display = 'grid';
}
};
diff --git a/scripts/main.js b/scripts/main.js
index 1c208af..f20c217 100644
--- a/scripts/main.js
+++ b/scripts/main.js
@@ -1,5 +1,6 @@
/* eslint-disable no-undef */
const container = document.getElementById('container');
+const loading = document.getElementById('loading');
const addSearchInputChangeListener = () => {
document.getElementById('search').addEventListener('input', onInputChange);
@@ -39,7 +40,7 @@ const addGridContainerListeners = () => {
if (e.target.classList.contains('x')) {
onXClicked(e);
}
- if (e.target.classList.contains('checkbox')) {
+ if (e.target.type === 'checkbox') {
onCheckBoxClicked(e);
}
e.stopPropagation();
@@ -76,17 +77,21 @@ const createOverlay = ({ url, id, title, windowId }) => {
xButton.setAttribute('class', 'btn x');
xButton.setAttribute('data-id', id);
- const checkbox = document.createElement('span');
- checkbox.setAttribute('class', 'checkbox');
+ const checkboxWrap = document.createElement('label');
+ checkboxWrap.setAttribute('class', 'checkbox-wrap');
+ checkboxWrap.setAttribute('for', `checkbox_${id}`);
+ const checkbox = document.createElement('input');
+ checkbox.setAttribute('type', 'checkbox');
checkbox.setAttribute('id', `checkbox_${id}`);
checkbox.setAttribute('data-id', id);
checkbox.setAttribute('data-url', url);
+ checkboxWrap.appendChild(checkbox);
const header = document.createElement('h2');
header.innerText = title;
overlay.appendChild(header);
- overlay.appendChild(checkbox);
+ overlay.appendChild(checkboxWrap);
overlay.appendChild(starButton);
overlay.appendChild(fileButton);
overlay.appendChild(xButton);
@@ -96,6 +101,7 @@ const createOverlay = ({ url, id, title, windowId }) => {
// Image related
const createImage = (imageUri) => {
const image = document.createElement('img');
+ image.setAttribute('loading', 'lazy');
image.setAttribute('src', imageUri);
return image;
};
@@ -107,30 +113,29 @@ const onCaptured = (imageUri, tab) => {
return fragment;
};
+const handleLoading = () => {
+ setTimeout(() => {
+ container.classList.remove('hidden');
+ loading.remove();
+ }, 1500);
+};
+
const urlRegEx =
/[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&/=]*)/;
const isValidURLFormat = (url) => urlRegEx.test(url);
-function* yieldMyTabs(tabs) {
- // eslint-disable-next-line no-restricted-syntax
- for (const tab of tabs) {
- yield tab;
- }
-}
-
-const createLazyTabItems = async (tabs) => {
- const tabsIterator = yieldMyTabs(tabs);
- let nextIteration = tabsIterator.next();
- while (!nextIteration.done) {
- const tab = nextIteration.value;
- const gridItem = document.createElement('div');
- gridItem.setAttribute('class', 'grid-item');
- gridItem.setAttribute('id', tab.id);
- // eslint-disable-next-line no-await-in-loop
- const uri = await browser.tabs.captureTab(tab.id);
- gridItem.appendChild(onCaptured(uri, tab));
- container.appendChild(gridItem);
- nextIteration = tabsIterator.next();
+const createTabItems = (tabs) => {
+ while (tabs.length) {
+ const fragment = document.createDocumentFragment();
+ tabs.splice(0, 4).forEach(async (tab) => {
+ const gridItem = document.createElement('div');
+ fragment.appendChild(gridItem);
+ gridItem.setAttribute('class', 'grid-item');
+ gridItem.setAttribute('id', tab.id);
+ const uri = await browser.tabs.captureTab(tab.id);
+ gridItem.appendChild(onCaptured(uri, tab));
+ });
+ container.appendChild(fragment);
}
};
@@ -138,19 +143,19 @@ const getTabs = async () => {
const tabs = await browser.tabs.query({ pinned: false });
const validTabs = tabs.filter((tab) => isValidURLFormat(tab.url));
if (validTabs.length > 0) {
- createLazyTabItems(validTabs);
+ handleLoading();
+ createTabItems(validTabs);
addGridContainerListeners();
} else {
- const emptyContainer = document.createElement('div');
- emptyContainer.setAttribute('class', 'grid-item empty');
- emptyContainer.innerText = 'Start browsing and come back!';
- container.appendChild(emptyContainer);
+ loading.innerText = 'Start browsing and come back!';
}
};
const setPopupProperties = (windowInfo) => {
if (windowInfo.width < 800) {
- document.getElementById('container').setAttribute('class', 'grid-list');
+ document
+ .getElementById('container')
+ .setAttribute('class', 'grid-list hidden');
document.getElementById('curtain').style.gridTemplateColumns = 'auto';
document.getElementById('search').style.gridArea = '2 / 1';
document.getElementById('search').style.left = '35px';
@@ -165,8 +170,8 @@ const adjustPopup = async () => {
};
const loadContent = () => {
- adjustPopup();
getTabs();
+ adjustPopup();
addCloseBtnListener();
addMenuButtonsListeners();
addSearchInputChangeListener();