From 51b68cdc929a28705df63d4d03dcbe19076cd5ea Mon Sep 17 00:00:00 2001 From: u-Sir <93647031+u-Sir@users.noreply.github.com> Date: Sun, 29 Dec 2024 21:09:01 +0800 Subject: [PATCH] 1.7 --- chromium/custom_page.js | 318 ++++++++++++++++++++++++++-------------- chromium/icon.png | Bin 16358 -> 2745 bytes chromium/manifest.json | 2 +- firefox/custom_page.js | 318 ++++++++++++++++++++++++++-------------- firefox/manifest.json | 2 +- 5 files changed, 422 insertions(+), 218 deletions(-) diff --git a/chromium/custom_page.js b/chromium/custom_page.js index 70cd00e..00433c3 100644 --- a/chromium/custom_page.js +++ b/chromium/custom_page.js @@ -25,7 +25,7 @@ let iframeGap = 20; // Default gap document.addEventListener("DOMContentLoaded", () => { chrome.storage.local.get(["iframeUrls", "iframeSettings", "group", "lastUrls"], (data) => { const urls = data.lastUrls || []; - const group = data.group || { one: '', two: '', three: '', four: '' }; + const group = data.group || { Star: '', Sailing: '', Flower: '', Coffee: '' }; const settings = data.iframeSettings || { width: 375, height: 667, gap: 20 }; iframeWidth = settings.width; @@ -36,27 +36,25 @@ document.addEventListener("DOMContentLoaded", () => { iframeHeightInput.value = iframeHeight; iframeGapInput.value = iframeGap; - oneUrlsInput.value = group.one; - twoUrlsInput.value = group.two; - threeUrlsInput.value = group.three; - fourUrlsInput.value = group.four; + oneUrlsInput.value = group.Star; + twoUrlsInput.value = group.Sailing; + threeUrlsInput.value = group.Flower; + fourUrlsInput.value = group.Coffee; const iframeContainer = document.querySelector('#iframeContainer'); iframeContainer.style.gap = `${iframeGap}px`; // Set the new gap - // urls.forEach((url) => createIframe(url)); - buttonID = ['oneButton', 'twoButton', 'threeButton', 'fourButton']; // Explicit mapping of button IDs to group keys const buttonToGroupMap = { - oneButton: 'one', - twoButton: 'two', - threeButton: 'three', - fourButton: 'four', + oneButton: 'Star', + twoButton: 'Sailing', + threeButton: 'Flower', + fourButton: 'Coffee', }; // Iterate through buttonToGroupMap - Object.entries(buttonToGroupMap).forEach(([buttonId, groupKey]) => { - const button = document.getElementById(buttonId); // Get button by ID + Object.entries(buttonToGroupMap).forEach(([buttonID, groupKey]) => { + const button = document.getElementById(buttonID); // Get button by ID const urls = group[groupKey]; // Get URLs for the group key const split = document.getElementById('split-end'); // Get button by ID @@ -64,11 +62,18 @@ document.addEventListener("DOMContentLoaded", () => { split.style.display = ''; // Bind click event if group has URLs function open() { + + const iframeWrappers = document.querySelectorAll('.iframe-wrapper'); + iframeWrappers.forEach(wrapper => { + wrapper.remove(); + }); addIframe(urls); // Add your specific click event logic here + document.title = buttonToGroupMap[buttonID]; } button.removeEventListener('click', open); button.addEventListener('click', open); + } else { // Hide button if no URLs in the group button.style.display = 'none'; @@ -146,73 +151,158 @@ function createIframe(url) { getTitleFromUrl(url); title.addEventListener("click", () => { - // Get iframeUrls from chrome.storage.local - chrome.storage.local.get('iframeUrls', (data) => { - const urls = data.iframeUrls || []; - const index = urls.indexOf(url); // Find the current URL's index - - if (index === -1) { - return; // URL not found in storage, exit early - } - - - // Create the index selector dropdown - const selector = document.createElement("select"); - selector.style.position = 'absolute'; // Position it dynamically on the page - selector.style.zIndex = '1000'; // Ensure it's on top of other elements - - // Add options to the dropdown for each URL in iframeUrls - urls.forEach((url, idx) => { - const option = document.createElement("option"); - option.value = idx; - option.textContent = `${idx + 1}. ${url}`; - selector.appendChild(option); - }); - - // Set the current URL as the selected option - selector.value = index; - - // Get the bounding rect of the title element - const titleRect = title.getBoundingClientRect(); - - // Set the dropdown position to appear next to the title (adjust these values if necessary) - selector.style.top = `${titleRect.top + window.scrollY}px`; // 5px offset from the bottom of title - selector.style.left = `${titleRect.left + window.scrollX}px`; // Align with left of title - - // Append the selector to the body (or any specific container) - document.body.appendChild(selector); - - // Add event listener to remove the selector when clicking outside or on a different element - const removeSelector = () => { - document.body.removeChild(selector); - }; - - // Remove the selector when clicking outside the selector or the iframe container - document.addEventListener('click', (event) => { - if (!selector.contains(event.target) && !titleBar.contains(event.target)) { - removeSelector(); + // Get iframeUrls and group from chrome.storage.local + chrome.storage.local.get(['iframeUrls', 'group'], (data) => { + const iframeUrls = data.iframeUrls || []; + const group = data.group || {}; + + const currentTitle = document.title; // Get the current title and remove leading/trailing spaces + + // Check if the current title exists in the group object + if (group[currentTitle]) { + + // The title exists in the group, so we will update the group + const urls = group[currentTitle].split(";"); // Assume URLs are stored as a semicolon-separated string + + const index = urls.indexOf(url) !== -1 ? urls.indexOf(url) : urls.indexOf(url.replace(/^https?:\/\//, '')); // Find the current URL's index + + if (index === -1) { + return; // URL not found in the group, exit early } - }, { once: true }); - - // Add an event listener for when the user selects an index - selector.addEventListener("change", () => { - const selectedIndex = parseInt(selector.value); // Get selected index - - // Swap the URL at the current index with the selected index - const temp = urls[index]; - urls[index] = urls[selectedIndex]; - urls[selectedIndex] = temp; - - // Save the updated iframeUrls to chrome.storage.local - chrome.storage.local.set({ iframeUrls: urls }, () => { - // Optionally, update the title or any other UI elements here - title.textContent = urls[selectedIndex]; // Update the title to the selected URL - document.body.removeChild(selector); // Remove the selector from the DOM after selection - window.location.reload(); // Reload the page to reflect the changes + + // Create the index selector dropdown + const selector = document.createElement("select"); + selector.style.position = 'absolute'; // Position it dynamically on the page + selector.style.zIndex = '1000'; // Ensure it's on top of other elements + + // Add options to the dropdown for each URL in the group + urls.forEach((url, idx) => { + const option = document.createElement("option"); + option.value = idx; + option.textContent = `${idx + 1}. ${url}`; + selector.appendChild(option); }); - }); + + // Set the current URL as the selected option + selector.value = index; + + // Get the bounding rect of the title element + const titleRect = title.getBoundingClientRect(); + + // Set the dropdown position to appear next to the title + selector.style.top = `${titleRect.top + window.scrollY + titleRect.height + 5}px`; // Position below the title + selector.style.left = `${titleRect.left + window.scrollX}px`; // Align with left of title + + // Append the selector to the body + document.body.appendChild(selector); + + // Add event listener to remove the selector when clicking outside + const removeSelector = () => { + document.body.removeChild(selector); + }; + + // Remove the selector when clicking outside or on a different element + document.addEventListener('click', (event) => { + if (!selector.contains(event.target) && !title.contains(event.target)) { + removeSelector(); + } + }, { once: true }); + + // Add an event listener for when the user selects an index + selector.addEventListener("change", () => { + const selectedIndex = parseInt(selector.value); // Get selected index + + // Swap the URL at the current index with the selected index + const temp = urls[index]; + urls[index] = urls[selectedIndex]; + urls[selectedIndex] = temp; + + // Update the group object in chrome.storage.local + group[currentTitle] = urls.join(";"); // Store URLs as a semicolon-separated string + + chrome.storage.local.set({ group: group }, () => { + // Optionally, update the title or any other UI elements + title.textContent = urls[selectedIndex]; // Update the title to the selected URL + document.body.removeChild(selector); // Remove the selector from the DOM + const iframeWrappers = document.querySelectorAll('.iframe-wrapper'); + iframeWrappers.forEach(wrapper => { + wrapper.remove(); + }); + addIframe(urls.join(";")); + }); + }); + } else { + + // Current title is not in the group, proceed with iframeUrls logic + const index = iframeUrls.indexOf(url); // Find the current URL's index in iframeUrls + + if (index === -1) { + return; // URL not found in iframeUrls, exit early + } + + // Create the index selector dropdown + const selector = document.createElement("select"); + selector.style.position = 'absolute'; // Position it dynamically on the page + selector.style.zIndex = '1000'; // Ensure it's on top of other elements + + // Add options to the dropdown for each URL in iframeUrls + iframeUrls.forEach((url, idx) => { + const option = document.createElement("option"); + option.value = idx; + option.textContent = `${idx + 1}. ${url}`; + selector.appendChild(option); + }); + + // Set the current URL as the selected option + selector.value = index; + + // Get the bounding rect of the title element + const titleRect = title.getBoundingClientRect(); + + // Set the dropdown position to appear next to the title + selector.style.top = `${titleRect.top + window.scrollY + titleRect.height + 5}px`; // Position below the title + selector.style.left = `${titleRect.left + window.scrollX}px`; // Align with left of title + + // Append the selector to the body + document.body.appendChild(selector); + + // Add event listener to remove the selector when clicking outside + const removeSelector = () => { + document.body.removeChild(selector); + }; + + // Remove the selector when clicking outside or on a different element + document.addEventListener('click', (event) => { + if (!selector.contains(event.target) && !title.contains(event.target)) { + removeSelector(); + } + }, { once: true }); + + // Add an event listener for when the user selects an index + selector.addEventListener("change", () => { + const selectedIndex = parseInt(selector.value); // Get selected index + + // Swap the URL at the current index with the selected index + const temp = iframeUrls[index]; + iframeUrls[index] = iframeUrls[selectedIndex]; + iframeUrls[selectedIndex] = temp; + + // Save the updated iframeUrls to chrome.storage.local + chrome.storage.local.set({ iframeUrls: iframeUrls }, () => { + // Optionally, update the title or any other UI elements + title.textContent = iframeUrls[selectedIndex]; // Update the title to the selected URL + document.body.removeChild(selector); // Remove the selector from the DOM + const iframeWrappers = document.querySelectorAll('.iframe-wrapper'); + iframeWrappers.forEach(wrapper => { + wrapper.remove(); + }); + addIframe(iframeUrls.join(";")); + }); + }); + } }); }); + const removeButton = document.createElement("button"); removeButton.innerHTML = ` @@ -232,7 +322,10 @@ function createIframe(url) { delete data.size[url]; // Remove the size settings for the current URL } iframeWrapper.remove(); - saveUrls(); + const iframeWrappers = document.querySelectorAll('.iframe-wrapper'); + if (iframeWrappers.length === 0) { + document.title = ''; + } }); const refreshButton = document.createElement("button"); @@ -299,9 +392,7 @@ function createIframe(url) { data.size = data.size || {}; data.size[url] = { width, height }; // Update the iframeSettings.url directly - chrome.storage.local.set({ size: data.size }, () => { - // console.log("New iframe size saved:", { width, height }); - }); + chrome.storage.local.set({ size: data.size }); } else { alert("Invalid input. Please enter the size in the format 'widthxheight' (e.g., '600x800')."); } @@ -430,6 +521,11 @@ saveSettingsButton.addEventListener("click", () => { gap: iframeGap, }, }, () => { + if (hasGapChanged) { + + const iframeContainer = document.getElementById('iframeContainer'); + iframeContainer.style.gap = `${iframeGap}px`; // Set the new gap + } // Fetch stored iframe-specific sizes chrome.storage.local.get(["size"], (data) => { const sizeData = data.size || {}; @@ -483,20 +579,19 @@ saveEditButton.addEventListener("click", () => { // Save to local storage chrome.storage.local.set({ group: { - one: oneUrls, - two: twoUrls, - three: threeUrls, - four: fourUrls + Star: oneUrls, + Sailing: twoUrls, + Flower: threeUrls, + Coffee: fourUrls }, }, () => { chrome.storage.local.get(["group"], (data) => { - const group = data.group || { one: '', two: '', three: '', four: '' }; - const buttonID = ['oneButton', 'twoButton', 'threeButton', 'fourButton']; + const group = data.group || { Star: '', Sailing: '', Flower: '', Coffee: '' }; const buttonToGroupMap = { - oneButton: 'one', - twoButton: 'two', - threeButton: 'three', - fourButton: 'four', + oneButton: 'Star', + twoButton: 'Sailing', + threeButton: 'Flower', + fourButton: 'Coffee', }; const split = document.getElementById('split-end'); @@ -504,19 +599,24 @@ saveEditButton.addEventListener("click", () => { let hasUrls = false; // Iterate through buttonToGroupMap - Object.entries(buttonToGroupMap).forEach(([buttonId, groupKey]) => { - const button = document.getElementById(buttonId); + Object.entries(buttonToGroupMap).forEach(([buttonID, groupKey]) => { + const button = document.getElementById(buttonID); const urls = group[groupKey]; if (urls && urls.length > 0) { hasUrls = true; button.style.display = ''; // Show the button - + // Remove existing event listener if any - button.replaceWith(button.cloneNode(true)); - const newButton = document.getElementById(buttonId); + button.replaceWith(button.cloneNode(true)); + const newButton = document.getElementById(buttonID); newButton.addEventListener("click", () => { + const iframeWrappers = document.querySelectorAll('.iframe-wrapper'); + iframeWrappers.forEach(wrapper => { + wrapper.remove(); + }); addIframe(urls); // Add iframe logic + document.title = buttonToGroupMap[buttonID]; // Set the document title }); } else { button.style.display = 'none'; // Hide the button if no URLs @@ -537,12 +637,12 @@ saveEditButton.addEventListener("click", () => { editAllButton.addEventListener("click", async () => { chrome.storage.local.get("group", (data) => { - const group = data.group || { one: '', two: '', three: '', four: '' }; + const group = data.group || { Star: '', Sailing: '', Flower: '', Coffee: '' }; - oneUrlsInput.value = group.one; - twoUrlsInput.value = group.two; - threeUrlsInput.value = group.three; - fourUrlsInput.value = group.four; + oneUrlsInput.value = group.Star; + twoUrlsInput.value = group.Sailing; + threeUrlsInput.value = group.Flower; + fourUrlsInput.value = group.Coffee; editContainer.style.display = editContainer.style.display === "none" ? "flex" : "none"; }) @@ -550,7 +650,7 @@ editAllButton.addEventListener("click", async () => { deleteAllButton.addEventListener("click", async () => { - + document.title = ""; const iframeWrappers = document.querySelectorAll('.iframe-wrapper'); iframeWrappers.forEach(wrapper => { wrapper.remove(); @@ -589,7 +689,6 @@ pcUAButton.addEventListener("click", () => { // If the input hasn't changed, do nothing if (newUrls.length === existingFilters.size && newUrls.every(url => existingFilters.has(url))) { - console.log("No changes in the input URLs. Exiting."); return; // No change, so do nothing } @@ -626,9 +725,7 @@ pcUAButton.addEventListener("click", () => { // Save iframe URLs to chrome.storage.local if there are any if (iframeUrls.length > 0) { - chrome.storage.local.set({ lastUrls: iframeUrls }, () => { - console.log("Iframe URLs saved to chrome.storage.local:", iframeUrls); - }); + chrome.storage.local.set({ lastUrls: iframeUrls }); } // Update dynamic rules and reload the page @@ -638,9 +735,14 @@ pcUAButton.addEventListener("click", () => { removeRuleIds: rulesToRemove, }, () => { - console.log("Rules updated:", { added: newRules, removed: rulesToRemove }); - // Reload the page - window.location.reload(); + const iframeWrappers = document.querySelectorAll('.iframe-wrapper'); + iframeWrappers.forEach(wrapper => { + // get the iframe URL under the current iframe-wrapper + const src = wrapper.querySelector('iframe').getAttribute('src'); + // refresh the iframe + wrapper.querySelector('iframe').src = src; + }); + } ); } diff --git a/chromium/icon.png b/chromium/icon.png index 60accb79ec9aea2832d4a608f9f40a5c309e0228..5a1008b6f6824f4d287a1e09c592ad844f069f8a 100644 GIT binary patch literal 2745 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 PPK>pk7EFh<*ov|arV=?7dMQh`I+f0; zY$Xz*R7{E9Eyx-sOSX)4tl#JTntFde*Y*2e*Y^+jbzQDruh)Iw&+UHR&*$@T-}gjq zvo&Av>+)YQ3|qjmFx!D);!5a`{0n?(JpRiO_)o&ugtdzd|2SmV^YA|ZxW!&y3|psy z{zw70js4)G{K-EYPVV$}JL!MW=Md)a@4xP-m%Fda!Q+S4dHWnr9xz;vVM-XwY|E~I zl)mP`$C>_)tur;e6fJtVzS7ynCz$iLxNKKcVp=S7U6i-*%6rSz-)`o;tY6ZGQDU}h z?76Ub-wlT?vLChNJL&Xoxk_UvG!kOCuVt>#4w6aQBQaBbK6?6x(;wA6sT&_J8k`z^ zl2tSBY1ZA+hvU4@U8${4Yb`;@|Hr>;pX(;ElRfKLCF^+oc#{rKUUGKWkLA_y{Xov$ zH8^J@FOt$1!fHw4o35qI!^kqfRM3TE^ccOIZ0}%&`fKB=h23Q>SNIz|W5lsHD$Mx) z5>|;Z&tJXJrsE;=QH^TgUfkJMpnj=F4AXM=w-dag*Cp@GvJ;HaDGM;{=Hy+vrlpTf z!`!)=`xQ^umiMM(+_n1oqoh?QZqmEdg`@PtZUJv4kDL123hXvaZxBebvOI$outaJ$ zDXG*zEzkz{J{lsEm}qP#=$6(zAc<{lZw;?$e7a$J|A8S=@c05&ODexDlOl%sw#(iZ zPO7tVCv-iwtjm#8dGN#)-jYEZ0?4^}O-!t2xuvxfF!Y+Ry})3k|~ zjHkSxRMPToz0&s3#7Rz83=8h`4CrcelW*z&whkCc2`1?=Ha@3%&thd)0(Ko%bW$85 zeNv3)pP{Q4Fvys7)QZ@iUd$#QPQ+3|i zIL?F7E!cH`#b?*@!xV-{Mvv|B0=2?FpgVK0iECZQVzngj7Xs61YS=aY7S=lN5E-od zDlnM*&v{Ds+h+U#&L6u}L&BPU#IgZC;)(jy+LkX7pUnq+s{?I`Up7)gGwhxjL?OO=^3g zPvW&TafWnW7~+29?Sje?!@Hv-u8{#)E6y+nsj!KpZ8Ux~1Y@t&wG=eayYj#gd30t* z*Tq^%tk%y5x35^i!gAPRu0axH>&7TFpHus&64<`)$|Fbh)p(y+(LkN;Ql}QG(f$wqu({CjhW`#aM zW6xko@pAjASpBub>cXVjNQ~<#r-aQ+{7Wxg<}D*uc5%K8w`97N<@8$^LtJZTXc=jw zD>80+AKrn4dZot1CP&V)LO1Z{BNi@;VC-ZXJ=@mD2Ti4e1ew`dZ6k=F>w+6&%g$n? z?$(gF1Bv_$)IAxxfB5dmT4(7qTq{Z9+K^?qJ&zCLR&gNb7L4sECc)lULgO{!DgT*N z!g3ap#I%f@)A^~a5+po3TY_A+v3WJ`C2QdQgaVeM4*j1D#PV@zU1dybKD;$lTL_}* zt+i+IOda!TO$Az@Txm9SwS%LsCy zD^jHmWE1Mscx&P~cIf>E@HSkT&R@(*dk4I~FNSx{%4EJOD>M(u7KxD(3qn|-t9d*3 z1NB8Du^fph+|Zb}0lh+JpFTUE&|Xt4#{=ZtTWuvcBVC}3ZL{TK8Z|NWz=PA$*maUI z2aE4vu|kb_Xz7+c03p6k&eAn&z9-SJZ6?sSu>(I4%fAH@v*jho7{$itAie@EuVHm2 zW`R!~J|CNmoNT!BWu*1nPpr`5QJUW0b65EFwUKPkah4#1PGR}{(eV(|+Swu*x=%5w zZEwHo)JYt~KBF@EXYuvGg|n-8pIM9+Fk)4Vc@C!c(Fi|qjSn76Vuu3H$l+1eI$ObR zBw;aG28-sq#~q00yMtA^LK!8juQM8!%0L4e4<7L4h*x^sCR%F~yj!PZB=+J0OCJ`# zVMV$)Hwv8Z{x>&yhC06mkvlnG1{-VtNcXlClp%K4fL-vZoAhiOA6u9OEh8}r?x~a% z{w9`UGa`2Z$T_Oh0}tU9$Oa#1OsxI|tO}eTg~)9L>2ywc;LbLJD?sjg7z|(EXC-*U zN<-R>*l;nej4rx<=_n2BP5@dSU4MjQ$0eYfr=BJ+`$dgBwy;f79BUNt>6(9~Z^9H_ zK;FpjNmmUFB$fo10W9+SA;5Uyu&yMyV<7Qj#k8M6&l427o0805!199ViRFRQ{d2OF zzErL7DCqMp0wY~-@K-Hd#e0he2LaJ^In1A-Jj>PoRav#Xr51i z+Clyt+@2n2(&39~iIK$0epC4Ga;U!u#{7LuRd}0jhcu}L=S;*ySZV3}Bs4J)?694A z#ynvrg;dr8oHM=^(={uPuMsOV1IihF=6JDIXd1~n!Z?TYYBai5(&4(gYT$_o|JP#I zePIC|s9_0qW>RvQb{2va@{A1<+-QhgLo*(Dx<|Ik?NznRE0}f zS?(dR=K_!5QgKa>!9aS3uttqEtpznICU={SO~aeeLViqxua2eH_>%a650gq#zUg#t zE1w{+$oH$TipQQR^KQm*Zj5eO(&@x%xyFx2>LdW~<=Iw(f9UDnz@yL{FHqON3DlOs z0^aOx;p2tZpp3?{MDK+7d-m@B2p7?<){A6$%_P-Ex4Z_meHmqTQ!cxBX z=m~WFheP_<5*8QB8!eGe-#av0E4eo@Sv7Dc9t@sS_8!Cci z1Q!T`Arr~cy0kEGS1Dg`2RlJC66`k+j7qigDWwm3aiVYQujk#v4KqN+cqSJc`5MQn zwiQevk=5zKOnMCDEN&snEQQLvv)aXu8mFRd1UTIeG0}(bA(IF2$io4bH=^(NP?Xw& zby@LB!_3D)+(|^KCuB~aM>!Nw(fa2nJ-X~<#)@%HJmRBPh1D@0QbzHlc(e{vN ziRHJ`3y`^C8F7V$be<{Bc`~FQ-IShlZBfRppH@LvNvmT6x8DQ~9sDu7I%!HslSV1-1afck}fBCw{rWVo`WIj89*nL*ZQc+;Agr1y01TS9B)k@KP#nx`SRv zOsgjE96%ii^*3Q*-2Zln6}pO-0K5+l#PK~@UMSd9C9>j1<$3`MKY6AD(o z$G{f@*&u+zC6vpi@#+N2DZVZD{!(3rRGIyE?=__Qd;p9A5ldM+yAtVhsytYH+6%CJAvq$kc zu&LBY9=&vt@!aW%X_5p}s!m-vM6ZD?G%v^pcfR2NTw*zRL!M6v9(I+#7iN}eoCu!C z$zQ}=4bj;PJqc7sf^L{-4|CiSUUs=(Rz}fmB_S1=TbUT(0lp-2c zE^*VxB5I^b^_zi+ol_z|O1@?Fh0S*7DQhJD0#$;B-4Svo+%GMOp8`mu(+Zk-MUc;M-n+^dHU!=xOZ-aV!7?w%mUvo(`699>^ z=K}U|n6#XE;M1#x59#B!g45sz+-w`cKS)HVu(UQo4BLZ`7ceTtrX704v0)V;@Ha(G zSWORu)#W?xI8>-qR*5Q@Q-Qdony{l*GAY*uH+(Qk;|7AUtv^?27i-NJWm2?VVi5Lo zLVd@1;HTiWu}M$tIBH}qWe`{4KvG-zubRg~V&%c}n)iVg6!?6Avksy-3RZ62ihw<< zpj2bqmc;T;u-1X)l4O<2jsQvD;g^srR{$Fof5e7?zMZteE7Su|^q#GH@pc~-6VY=_ z=10aAUk7?$@&I>s!ur%Y44#rpuYsB<%2!7`|nU~9ss02pL>0r#L74T z&Y|EC$E@oi2tH!GFza_GSXJh6ZjF*KwSg{eL;MsN9MiZ8*fK_4xC4xC-6W-5tT)pD zLDoT;q`kIIwGeO!=Jw^Kd`rgoHS~EoAY;XHv1JwB^uS&CJ(O-)5|tyI$3WGMKgv>! zLxBht9ZKe#30N{2@o^{FigudK@Fuf6epVI$My)>xUm|qW{ou1>I)5p+7rV11oj+$ONC26%)Wuw%gzEF0At{tq&3NK>(6|(GY|oR;JcyZM zY*LmdNUSfb^kM7)J?tY?C0NeyByG<+Rbc^mHiq3>r1W9@6@4iT#IXA&+^TZQtD-y% z(;|tvDl)F}+gMo$v|{zJDG@WSDr`Y9o{V7%QCL!fuDX6USQGnVAyGLE5EE6=7#69* z?Cfc!3(Z-KRtTuraV?Uzb2jqjH(*>0^CQOw2HWGos)7D6TNqQB8ULl6HITp$WMz2; z|At}lwp@+!-7J`YM|`@AUYBpQ5W}ogneksuS+jw-x253jtHUIWeOjVYd*%;Fn}v4x zQdQxR#tzU9rs*@}1sE zaoqjdx9XOOdluf+tf^M}O#jhW&M!xswRt=71Bq=lPjW+TVAE=bKDUnN_$G7{wvE4# z<#dIA&0|jU*L0Ro=ve4Y?O#aB%uWk#-u&1V>iU|z#qKHo*+n{N)5V6DEsf=O$IJiu z<=e-(b8Q{+p#kZ|qt0IeYmv0g#ct^^Z7l@1q_aQ&GkYp@eR-+IW|!VlOKjQaf90Qd z_#T~G8d(Z88EedQ)ZS1=Nz64`!or5z_vZVup2!u`lM9=>@M&v2*<;jR8dDKoqld+h z88a!(y?E2f3#9{Q+yhj^#dV70(?Ku&@GN`y-BV2`s@Tn8eI>1|hjG&}^j4^UBZqS6 z391C5Q{dmji;Z|U_fz>=B|5w?JG6sw8bW|pn!2j+DP0#Lts}=5_gB}y2Ngcvq|OV* zIqtn@``SmOy-$TY!J;gShI)kFPhDL9rX;a#Z*Oj(#2Xa{U%u@9e#0}PD)NjYk4CdS zHG@w?7!Q-KC&_6S=l?xQd3kF5;^k6BF*9z}WlY|fIp+V}eV@O#wa@!XXA0)P``F=f z*k$W^OjgO4&V02Xc4p;tkWMO@biL_7JGA`qvqcKE?0a<$TB@2*i`mbX`KV>{t28o+ z-P^gGYS6gRMB+S_q(XWS$n6{aQkRn%1!a}nz)Qu4gY*@e}m{m`W``LUzou3?ggvw;tLqt%6&)J!>=NcO#&Ap7xwZ!knB|04`>Qu#qF zm;w@{6n-)zWA6KdIDH{WBb$FR9S!Tkry`$2Me4IX|!dPe?UUm>Z zJ&41L)!JQjA((xD2z&Btk}S0-@HpOTn#!NJbaU^Li203IU$i8X}EOEK) z^S=2qov+>D`SuS0!{Y(y zOO^?u!J~m0*-=($gvr6m{Gw!@(3nU1Z_%@(fTd?JIKU1}a=|lOTUW&mrIqu;=}IVBfFUWcvw?*YjoWf=1nO zdg8j*+Pta zRB%lu-;$fNz-gF-edydo^SFc^^g#RrfzN&#b6H$P78IX`(J#9t$S$%}Ov_F=eEWQv zS4yB^iy0YUqQ`5gYS>6F)=J$@meFaO*M;S1bh%9|jZqGNG+(CnYwjA%A>*NnNj>=P z%64%q-X=UphxFVDtgIwUyU*h0EOk2WG}x+Mcnb;=H2`w}Jpy`#@!yM^(}f;*jk?g^Gv?tk15N8NGyL9)^m&Od#O7(|WnxC6e3|CgvI{VbR*S7Ikchl3}lHzZq&ybR3)? zE0k55@wz%uPcu2DZo)N^rH=03ggS<*GXWBe6h3`Xu~2r0fvnhlGtNiv?4exK@DY8I zwz1f)(o8w3ftf|W898Uo(Du?(9f+AX!OXdl{)5?L!(6fLBHLlxvl-jvWpG&%*?i4 zE!kil7o z3VjlgHNL5vWY}>&X5IN=8n&7t@TiS(Tp3l7`)zy#Sd4VbADx>z%<65+y{9syx2NAQ zdY)WY=grWk%^Zc-HWo8Y;np$9F%6>u!zWhh(jNKBiOH!lzSRYD`ebOMaGB@O1uy8uLCvxJSW`&>Tu09_# z`BoL#aWX1)47hgwVftda;Rr4#{L6xo_QdGN} zu;0KmdLPxLM*7I@FxI7YJm0(75)7S>X^4u^ zltXN^w1>7E4-H*Kwyx|1tx*O>3vpT0#6Rg1dWNz)jAb7%hPE3Fop2=n6}8D&`YmzfVz!#V3MNy$WKHtE+q~RGHsRuxKF~94;dk4l!sh z^g#}TpiGNg3Byvzd8f~`<|L8qmR+({3o$-xO zXo)GJlLt#iw~H)GeI!TiC+NEo^z&5Vd&Q6MM1MCc)PH0P(6JTKnIs}z;z~sSKTCnH zK2jicq8p3^SyzXUCmr<4P@sVywcm6`a}v&zqmIf^L*!_q$$y3uvpY*LP$L*vp9RIP zC=-fV6S3u>4`GQsu!IdwWQh?%QZ+&Y>p1ei&NU*5GC)h)@OMT?qV=9Ihelfoi4uva zGASSk83Liv-w26Z7(~=f-$&jLLMA?$|bCuXPHOtl`iY8Z5#Fi_f< zYurCab9mpx(KwqNJGr|h{IT$#)a012$K`eu&8!KrXS>E&`ZzYsiRWC2ia8`p8@+d4 zhVV5*&OI zwj3mGq!V)_X|8N?%x~y!t4#fchaYBj#}}zF>Mz0EZWalmw_J9|L&>bk1*dnz{$*C) z+$E#&D9Rpi$AScrt?yfgdxQ-}Q&zc}#Q-+^=$pPY<>6ANM5of-PKg8ax*iRm@f~|D z^`W4&;{J3q_h!J(hPjBe;U-SbLR}D}U+o34%yQQ0(i)rR-3wdurPAvP|6AVN0;9Sp ziVkq{e=OqU0i3+kFC??Jey;?(8rB8&{k1+o;a;euaWoXs4e**9px_=H+^twbIqop0 z+8?G;bE5t1`l#4RBct}4LG5RAqhkB}&IJqA%5K1c|5JS2a;o)(Z*npvpJ#La?FlbNy$-~~!L;DXg&I}sGb!)%O9Nkx4zp%$ zdQG+5?GFWvjr|QE@G_i^7j2ksiSPuB>${)&r&~$xC@Dyd>F1wZE17sX-A<4Pr}MH| zmV)o+WikdIz!AORbFJh-*)&C2?F`sax_(&9)nCk2q5bSJL!9T zBUZ#Vr#4Mua;Hw=t;a&hdgqg6g8WZ3ao(ld(}gCzrq)+VO$SW4eFFke=^ubjn|RHz z@3c_ar2Fc`b@TDc?+>S6z)tC^u*jx!Aa$!@Z&9Ebc}A8tvX%4hX6l6A)6p$zeJWtZ z4WtJKqzCe{CNXB@r!v$L3(iGTZXcq3Gn1kvu3Pinbj%6%;UtHmdh$Bus(b#^99OK` z?jkMbx)ki>#e8*QAFc~{CS*vTmgjSVQ!P1z&SVcwERFQ2E`8Ag{F^2BQQ2FeP>+GX zO)-xDQHgQ9G-#ShDLdJ$SHAyseyC=Te*exPy(KgHs^z6Z_nDf=x4{W+6NO?%g~52t zof%`QZ^P0JhBMD(ACo>eAKoxs#x}fjD4=9l_`A5&id-nrtP_FCVj@Gb*Tug zsiJMY^J(*AZ%#c0GtmeY8hO~KprXKLp-^@e`i zBU*R9iwmX;%^K#0*Vi>4{W>Vo*RBb1V)#JUCfZ1)yNSoez_*e{f@?AT17TUSnGWk> z*qNOL`>E_##eZlT36?zd_|_h9&vCLN)30Ci?Q6Ci<^6b&jwZbv! zbk65VYQ*g-sShAbhNcSy;+SHH!1itvMbwS{HS~1rsjyY?+PW|?HkHL)oo5vbh5s~P zWtF(x9+dt~82xzuzbUYQ_-d|czQbE$pu)1{yjx3@tR^u{;Z^RS$z{+aitmS zsX`=&9Mw7kW$7E{%B~G^Xm!9?Eqx+ED@Mg01wvq7gP~`xL~ahEn`CSn+7g565Xm?w z%a6fd_htWzYp>8!7kJr2{ZJK=9NSPh|Ax7j$z)nGC5Yb%N&oC;B9)F<0ND9S;31Jk zL7E=-_Optp`l7hm5t&;>_Wgea)c7gjE#Qf4Cr8zY{vq?NxBvYVU(lVITF`ylyyfqL z&>E*61MySEpS)nm1*oX~h&hEQjV$JoPS`?^`GXY{ize=w+d9?ZUVHfecpm7XX+3VuK|{f&quosUAQVISc?bFg}?7KimuF zAKXt&PT4i0-Y|lsEl0a(Ly(C0-=9QOE&kUh4@;s~WwF*%KdPNi9kAF|A@!lR>s-(M zH&WH^>I}9O$S<+SSSiTjhVA7L8UcNbVJ z2Lw@2hsuCsUM2uy!dC)_QD%Wp?`v+RHXEV8OgjSUtSTL!{ltjRBjg4~+<>RD%BK$Fo)b(Pp z+nXTu`+xpl4Q-+ZHM2^;F*!)+Oc#RtB*DGvB3VAn`|}5XtO4p*z=EnsS$0OTnroBe zO7Ds{BLM&);Vq~b$iSY;hAwDn{?pqzwEGNHe1-Fq77_&%NvciFwK(L1V(HjBDJWNb z<=z|rXizbE_4(}B%(D{>;s`(|m!%73>K zVW0OD!guMiwB)|&O(iW5D$&<8WM{1840*5jTu`c}&Phu|B2NX$&MjX=3vQ*{AH5n8 z3gt{xY!ES3^;gNC8>{yXzL9n$6g@?#pRfb)>Xd zu(HXXMw_}Bv2qDQ?tTJOldCj{Ld6}w`&#Gu zvlZG{{5QQWye}1iceOi%o9QE`-B*|#N;~*m=rn#d3-n?Nt6t{d)$;nLUoE~tnrxy+fIRBow zb})K(scMNqynoT%RM=O2qEnF^3wK03sx%i>rGVe8?fFs7VsTmp9@hO-TKg0}!ZGUj&CRwSEJ9I;3Il;FG$U zLwKWiTQA9qf39aV`GW`pI2~VD^}Ii>SiOI4o8u{OJD)e1994E97||PQYgpi2o#KgC zSEvg6^XAG&j|6YWI|@cNac?6`=Yzlq7}V{kGd`?coaxzXe1y{ciIw*Fsq^OJTtEQ7 ziC`=CaJ+kD^hxZvy1wtd(m%hjo#b|uu70WpdkM%dUp_t&(HOht{Q#x8)cANrT>iBC zJg-Wavy9_%?L@3{xRtD~Z_L~M@09rX2gzCQmb@=@k_t)x0|&V;i$d_ZEB%aXqq?lL zWWL)UrD|WgA(oXYQY!@YyCF%GZHeZ6Cq+zcC_XiKYVRDS-kmZ%SReK!?2g^WNCxb~ zINK2lt22&NJ6Co$r^0m(UY%OuDZFvzM9l^~CFsjsjXHiHjek>eESDaZ!oMW%wTn9o zh;STl%7!aca7!oc!-Vv>g`k#x2W}wjH~=>p=!3`L9?8F(^?7i`lyvbGtPFRdUVKFs zvMlyR3(2@7#zhojG4@gjL03h%3B&e4n6#HA@T)k+rhr%G%l~{^0391eka0_0@d8cj z)|DHI*A8V0z80)5@x(vi)6J(t=;iwtJE!qYC1>R_p6?&2T`{~i=;xXzkw=d=6O%;`}cy)=nG zg)7*PN}bs>krF%UDbS}ex=;?{ZcmBjv*a0VPunHyB^OS&8sxVxm2?NhTYAdNgh-26 z4!ZfEQ+{*D+R((Ap3`$vC~%cN{o&kfmlz8{>HFEphEa5DsIg$`&ACSip4~Gf;2G>A z>palp&C=^`&rlwn9Y05(^9U~Wa7c!Q)9?4gS-6+r*9-SP%t|(R5$-xVkGl!t-O6<$ zw2G||O0s4(`opegKCs%rX(5l8g?}9UB3i7N2Y-uv%P$3^l)R^XGpvF9OParUl)0OH z8~*^CYu^xmpX`fsNs7Ct%pytyn07EHjJjv?@!CVAvaN7E$s6%io7#nYub7e&Um?(o ze|rKfa|!Clan!U-js|5#eF~hE)YoTc%uw>y6V+O-zBLDo6P7w={4Rezs`Jm=1fqd( zVK;K}(d>!iKx(fk)Z|h9B~3_ z^}maHrKvNpWp4{q3)l6BJ>G3c)Ye9}F!HW0*s@^Ha8%DorFzDGJ4F9mJS&SeMLoV2 zvb}=Uo1zJiD5s}N&Ns+;M^jJ562bB6}l31f}9RS(-9@e_Ql4T|z3}1`Au#X!4 zS(bWS1~np-+XQzB6=Y4Ep(Zp#CmF}dsHGPW6c*zG$jxQ_k|7c^DTGxLJEj?s@)}Tz zkszukpI7`vfxDvs1PR@lOxUqDX@ct*AR(3Cp#xBI3*&yQqA>ivzZS>vOU@WHf6>28MK!rDcATf4iVEE{q_=(q|d2dr=uqlRT<~8~T_KI7l zR6u22k*jy5B8wd(LH4MDOK$96%*aqR_Q_ClegUaFesNW}b9iFcF+fvxe#$S@Gc*$> zxSQt7)TbGHhH&Kp(xPdDkJxpq!x=MDDqZ<@FKx(xLV1nvXVWS7lHerhU8ak+VZ^7& z$gfQzjPmM*q8X5bFAOP8UBujIi=KL(dZ9p6Bzrw6Fz2a z-Nhh=ZUje6EHfJ9H}Tg@F2|4 z^N|uX_I8Eq1owHZ@sR{A0xwyl1LLX&Usw|TA_xXxL!A2=ek9}$p=994Hy8N!@-YiH z2FEV3N(&3ymia=b$ zuw@M$*?%Hll^l_EV1a>t+QuR?s==^pj2m`GBM6of_5u?$ee@bj^- ztqvzK$lBi*6CDjito1Yy#T~@9I))Vytf8Dn9dj0;rUyS{td}F+U_%jkhQkF!Up`$# zUk7$m)lFWBB<5~MeiHjuq$qnAVZfh62(NkIFCtR^J3(@@NSiB!In71pg)~vejRZh1u_hb@b0mhf-+T!YzgsN3qe#^pcGZ#APv|Dc3SK~xM6ScE1FhrH z#yS!|5z5mdqC7<%)c~}3RYL`XCX&kn8zj3xornz1eh)A(6A*iEDIfKAhF7n0n&~x`yrOYM(CJ^ju*i7F|+Vp z*^xi`VUpmL?x>PN;(yTs^80=gtUpKo*YVH~&fLXd{oVg<5(k2wsIEqw9pLn$S?4Et z4}iH|RX^#gfEib)K)HctzU(~E*NKA7edK02^Tw?OQF(K3T6W~y{$#Uuvi5xJ>weWA zBbX#$v>TBg{EL2A@#~ZrR)#hT{4V?;@(yb2=C+@_H^S8TAOA^fA&4CEd%5!&=Z0r{ z<2MeGs-Bm?9nNLEBo_Qq6|S-GJ@1agl`$D9pF_B$y6`MquB^X;kvjSNVN;aX12Iiy z5w+|-S%&RpM)p-^aN%Y~nL?CIC){p$NM~{j7tySfCNMWEF6OIdlBf(EuEB7KIjZgA ziAE$bjniaw#Uh6+CgJd_tVs<#E`!HK5MAMM6+AANHL-(7J$O`>HKD+x1w8&PYhu+d z?r-h>n!>lSIM@aFWsn(p(+f!^TG*6?~S;=wk&9>=b~+aQ?vf)&6 zT@$5cwfj+vnt8Z2L4>!6_Td`18Czghxsm8{3E0mo7kfziOIN2KeUkq#1pd8Uszy-Cz1>1EJ>q&4Rx*&x{lUq$%7_r-q+6D#VW%(n zGDwn|Y(oMu6=L0YimHDcerL}9v)V!+d6c^N-oR7VK+e@{xS6`G z{RRArW9qS9gVSaHm442A7>-+5ubrueEs%t8Fk|cKfKgps=NNPvx1%+ z+?L&0K@ar6DYqO0IIDPZxI)2K=QS`daErvOtYXJf#dK>QCp=CnGz9xz+F0ar<(I!# zN#Ar%w%roWdZ3eVBiKi3j5cK8GRyaW{=UjjllIg#c;Rgr{GgP<2O3?g={q9w65Ds!tQle$YLcAk2Y*A$&ScS zTEDC4TVToX=RCdd(_amDSA5GqUW)y{|9y`$SR3BN-xG1a4s~YzVQZFU!annV0EzV& AK>z>% diff --git a/chromium/manifest.json b/chromium/manifest.json index 38427b2..b0c8885 100644 --- a/chromium/manifest.json +++ b/chromium/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Tabless", - "version": "1.6", + "version": "1.7", "permissions": [ "declarativeNetRequest", "storage" diff --git a/firefox/custom_page.js b/firefox/custom_page.js index 70cd00e..00433c3 100644 --- a/firefox/custom_page.js +++ b/firefox/custom_page.js @@ -25,7 +25,7 @@ let iframeGap = 20; // Default gap document.addEventListener("DOMContentLoaded", () => { chrome.storage.local.get(["iframeUrls", "iframeSettings", "group", "lastUrls"], (data) => { const urls = data.lastUrls || []; - const group = data.group || { one: '', two: '', three: '', four: '' }; + const group = data.group || { Star: '', Sailing: '', Flower: '', Coffee: '' }; const settings = data.iframeSettings || { width: 375, height: 667, gap: 20 }; iframeWidth = settings.width; @@ -36,27 +36,25 @@ document.addEventListener("DOMContentLoaded", () => { iframeHeightInput.value = iframeHeight; iframeGapInput.value = iframeGap; - oneUrlsInput.value = group.one; - twoUrlsInput.value = group.two; - threeUrlsInput.value = group.three; - fourUrlsInput.value = group.four; + oneUrlsInput.value = group.Star; + twoUrlsInput.value = group.Sailing; + threeUrlsInput.value = group.Flower; + fourUrlsInput.value = group.Coffee; const iframeContainer = document.querySelector('#iframeContainer'); iframeContainer.style.gap = `${iframeGap}px`; // Set the new gap - // urls.forEach((url) => createIframe(url)); - buttonID = ['oneButton', 'twoButton', 'threeButton', 'fourButton']; // Explicit mapping of button IDs to group keys const buttonToGroupMap = { - oneButton: 'one', - twoButton: 'two', - threeButton: 'three', - fourButton: 'four', + oneButton: 'Star', + twoButton: 'Sailing', + threeButton: 'Flower', + fourButton: 'Coffee', }; // Iterate through buttonToGroupMap - Object.entries(buttonToGroupMap).forEach(([buttonId, groupKey]) => { - const button = document.getElementById(buttonId); // Get button by ID + Object.entries(buttonToGroupMap).forEach(([buttonID, groupKey]) => { + const button = document.getElementById(buttonID); // Get button by ID const urls = group[groupKey]; // Get URLs for the group key const split = document.getElementById('split-end'); // Get button by ID @@ -64,11 +62,18 @@ document.addEventListener("DOMContentLoaded", () => { split.style.display = ''; // Bind click event if group has URLs function open() { + + const iframeWrappers = document.querySelectorAll('.iframe-wrapper'); + iframeWrappers.forEach(wrapper => { + wrapper.remove(); + }); addIframe(urls); // Add your specific click event logic here + document.title = buttonToGroupMap[buttonID]; } button.removeEventListener('click', open); button.addEventListener('click', open); + } else { // Hide button if no URLs in the group button.style.display = 'none'; @@ -146,73 +151,158 @@ function createIframe(url) { getTitleFromUrl(url); title.addEventListener("click", () => { - // Get iframeUrls from chrome.storage.local - chrome.storage.local.get('iframeUrls', (data) => { - const urls = data.iframeUrls || []; - const index = urls.indexOf(url); // Find the current URL's index - - if (index === -1) { - return; // URL not found in storage, exit early - } - - - // Create the index selector dropdown - const selector = document.createElement("select"); - selector.style.position = 'absolute'; // Position it dynamically on the page - selector.style.zIndex = '1000'; // Ensure it's on top of other elements - - // Add options to the dropdown for each URL in iframeUrls - urls.forEach((url, idx) => { - const option = document.createElement("option"); - option.value = idx; - option.textContent = `${idx + 1}. ${url}`; - selector.appendChild(option); - }); - - // Set the current URL as the selected option - selector.value = index; - - // Get the bounding rect of the title element - const titleRect = title.getBoundingClientRect(); - - // Set the dropdown position to appear next to the title (adjust these values if necessary) - selector.style.top = `${titleRect.top + window.scrollY}px`; // 5px offset from the bottom of title - selector.style.left = `${titleRect.left + window.scrollX}px`; // Align with left of title - - // Append the selector to the body (or any specific container) - document.body.appendChild(selector); - - // Add event listener to remove the selector when clicking outside or on a different element - const removeSelector = () => { - document.body.removeChild(selector); - }; - - // Remove the selector when clicking outside the selector or the iframe container - document.addEventListener('click', (event) => { - if (!selector.contains(event.target) && !titleBar.contains(event.target)) { - removeSelector(); + // Get iframeUrls and group from chrome.storage.local + chrome.storage.local.get(['iframeUrls', 'group'], (data) => { + const iframeUrls = data.iframeUrls || []; + const group = data.group || {}; + + const currentTitle = document.title; // Get the current title and remove leading/trailing spaces + + // Check if the current title exists in the group object + if (group[currentTitle]) { + + // The title exists in the group, so we will update the group + const urls = group[currentTitle].split(";"); // Assume URLs are stored as a semicolon-separated string + + const index = urls.indexOf(url) !== -1 ? urls.indexOf(url) : urls.indexOf(url.replace(/^https?:\/\//, '')); // Find the current URL's index + + if (index === -1) { + return; // URL not found in the group, exit early } - }, { once: true }); - - // Add an event listener for when the user selects an index - selector.addEventListener("change", () => { - const selectedIndex = parseInt(selector.value); // Get selected index - - // Swap the URL at the current index with the selected index - const temp = urls[index]; - urls[index] = urls[selectedIndex]; - urls[selectedIndex] = temp; - - // Save the updated iframeUrls to chrome.storage.local - chrome.storage.local.set({ iframeUrls: urls }, () => { - // Optionally, update the title or any other UI elements here - title.textContent = urls[selectedIndex]; // Update the title to the selected URL - document.body.removeChild(selector); // Remove the selector from the DOM after selection - window.location.reload(); // Reload the page to reflect the changes + + // Create the index selector dropdown + const selector = document.createElement("select"); + selector.style.position = 'absolute'; // Position it dynamically on the page + selector.style.zIndex = '1000'; // Ensure it's on top of other elements + + // Add options to the dropdown for each URL in the group + urls.forEach((url, idx) => { + const option = document.createElement("option"); + option.value = idx; + option.textContent = `${idx + 1}. ${url}`; + selector.appendChild(option); }); - }); + + // Set the current URL as the selected option + selector.value = index; + + // Get the bounding rect of the title element + const titleRect = title.getBoundingClientRect(); + + // Set the dropdown position to appear next to the title + selector.style.top = `${titleRect.top + window.scrollY + titleRect.height + 5}px`; // Position below the title + selector.style.left = `${titleRect.left + window.scrollX}px`; // Align with left of title + + // Append the selector to the body + document.body.appendChild(selector); + + // Add event listener to remove the selector when clicking outside + const removeSelector = () => { + document.body.removeChild(selector); + }; + + // Remove the selector when clicking outside or on a different element + document.addEventListener('click', (event) => { + if (!selector.contains(event.target) && !title.contains(event.target)) { + removeSelector(); + } + }, { once: true }); + + // Add an event listener for when the user selects an index + selector.addEventListener("change", () => { + const selectedIndex = parseInt(selector.value); // Get selected index + + // Swap the URL at the current index with the selected index + const temp = urls[index]; + urls[index] = urls[selectedIndex]; + urls[selectedIndex] = temp; + + // Update the group object in chrome.storage.local + group[currentTitle] = urls.join(";"); // Store URLs as a semicolon-separated string + + chrome.storage.local.set({ group: group }, () => { + // Optionally, update the title or any other UI elements + title.textContent = urls[selectedIndex]; // Update the title to the selected URL + document.body.removeChild(selector); // Remove the selector from the DOM + const iframeWrappers = document.querySelectorAll('.iframe-wrapper'); + iframeWrappers.forEach(wrapper => { + wrapper.remove(); + }); + addIframe(urls.join(";")); + }); + }); + } else { + + // Current title is not in the group, proceed with iframeUrls logic + const index = iframeUrls.indexOf(url); // Find the current URL's index in iframeUrls + + if (index === -1) { + return; // URL not found in iframeUrls, exit early + } + + // Create the index selector dropdown + const selector = document.createElement("select"); + selector.style.position = 'absolute'; // Position it dynamically on the page + selector.style.zIndex = '1000'; // Ensure it's on top of other elements + + // Add options to the dropdown for each URL in iframeUrls + iframeUrls.forEach((url, idx) => { + const option = document.createElement("option"); + option.value = idx; + option.textContent = `${idx + 1}. ${url}`; + selector.appendChild(option); + }); + + // Set the current URL as the selected option + selector.value = index; + + // Get the bounding rect of the title element + const titleRect = title.getBoundingClientRect(); + + // Set the dropdown position to appear next to the title + selector.style.top = `${titleRect.top + window.scrollY + titleRect.height + 5}px`; // Position below the title + selector.style.left = `${titleRect.left + window.scrollX}px`; // Align with left of title + + // Append the selector to the body + document.body.appendChild(selector); + + // Add event listener to remove the selector when clicking outside + const removeSelector = () => { + document.body.removeChild(selector); + }; + + // Remove the selector when clicking outside or on a different element + document.addEventListener('click', (event) => { + if (!selector.contains(event.target) && !title.contains(event.target)) { + removeSelector(); + } + }, { once: true }); + + // Add an event listener for when the user selects an index + selector.addEventListener("change", () => { + const selectedIndex = parseInt(selector.value); // Get selected index + + // Swap the URL at the current index with the selected index + const temp = iframeUrls[index]; + iframeUrls[index] = iframeUrls[selectedIndex]; + iframeUrls[selectedIndex] = temp; + + // Save the updated iframeUrls to chrome.storage.local + chrome.storage.local.set({ iframeUrls: iframeUrls }, () => { + // Optionally, update the title or any other UI elements + title.textContent = iframeUrls[selectedIndex]; // Update the title to the selected URL + document.body.removeChild(selector); // Remove the selector from the DOM + const iframeWrappers = document.querySelectorAll('.iframe-wrapper'); + iframeWrappers.forEach(wrapper => { + wrapper.remove(); + }); + addIframe(iframeUrls.join(";")); + }); + }); + } }); }); + const removeButton = document.createElement("button"); removeButton.innerHTML = ` @@ -232,7 +322,10 @@ function createIframe(url) { delete data.size[url]; // Remove the size settings for the current URL } iframeWrapper.remove(); - saveUrls(); + const iframeWrappers = document.querySelectorAll('.iframe-wrapper'); + if (iframeWrappers.length === 0) { + document.title = ''; + } }); const refreshButton = document.createElement("button"); @@ -299,9 +392,7 @@ function createIframe(url) { data.size = data.size || {}; data.size[url] = { width, height }; // Update the iframeSettings.url directly - chrome.storage.local.set({ size: data.size }, () => { - // console.log("New iframe size saved:", { width, height }); - }); + chrome.storage.local.set({ size: data.size }); } else { alert("Invalid input. Please enter the size in the format 'widthxheight' (e.g., '600x800')."); } @@ -430,6 +521,11 @@ saveSettingsButton.addEventListener("click", () => { gap: iframeGap, }, }, () => { + if (hasGapChanged) { + + const iframeContainer = document.getElementById('iframeContainer'); + iframeContainer.style.gap = `${iframeGap}px`; // Set the new gap + } // Fetch stored iframe-specific sizes chrome.storage.local.get(["size"], (data) => { const sizeData = data.size || {}; @@ -483,20 +579,19 @@ saveEditButton.addEventListener("click", () => { // Save to local storage chrome.storage.local.set({ group: { - one: oneUrls, - two: twoUrls, - three: threeUrls, - four: fourUrls + Star: oneUrls, + Sailing: twoUrls, + Flower: threeUrls, + Coffee: fourUrls }, }, () => { chrome.storage.local.get(["group"], (data) => { - const group = data.group || { one: '', two: '', three: '', four: '' }; - const buttonID = ['oneButton', 'twoButton', 'threeButton', 'fourButton']; + const group = data.group || { Star: '', Sailing: '', Flower: '', Coffee: '' }; const buttonToGroupMap = { - oneButton: 'one', - twoButton: 'two', - threeButton: 'three', - fourButton: 'four', + oneButton: 'Star', + twoButton: 'Sailing', + threeButton: 'Flower', + fourButton: 'Coffee', }; const split = document.getElementById('split-end'); @@ -504,19 +599,24 @@ saveEditButton.addEventListener("click", () => { let hasUrls = false; // Iterate through buttonToGroupMap - Object.entries(buttonToGroupMap).forEach(([buttonId, groupKey]) => { - const button = document.getElementById(buttonId); + Object.entries(buttonToGroupMap).forEach(([buttonID, groupKey]) => { + const button = document.getElementById(buttonID); const urls = group[groupKey]; if (urls && urls.length > 0) { hasUrls = true; button.style.display = ''; // Show the button - + // Remove existing event listener if any - button.replaceWith(button.cloneNode(true)); - const newButton = document.getElementById(buttonId); + button.replaceWith(button.cloneNode(true)); + const newButton = document.getElementById(buttonID); newButton.addEventListener("click", () => { + const iframeWrappers = document.querySelectorAll('.iframe-wrapper'); + iframeWrappers.forEach(wrapper => { + wrapper.remove(); + }); addIframe(urls); // Add iframe logic + document.title = buttonToGroupMap[buttonID]; // Set the document title }); } else { button.style.display = 'none'; // Hide the button if no URLs @@ -537,12 +637,12 @@ saveEditButton.addEventListener("click", () => { editAllButton.addEventListener("click", async () => { chrome.storage.local.get("group", (data) => { - const group = data.group || { one: '', two: '', three: '', four: '' }; + const group = data.group || { Star: '', Sailing: '', Flower: '', Coffee: '' }; - oneUrlsInput.value = group.one; - twoUrlsInput.value = group.two; - threeUrlsInput.value = group.three; - fourUrlsInput.value = group.four; + oneUrlsInput.value = group.Star; + twoUrlsInput.value = group.Sailing; + threeUrlsInput.value = group.Flower; + fourUrlsInput.value = group.Coffee; editContainer.style.display = editContainer.style.display === "none" ? "flex" : "none"; }) @@ -550,7 +650,7 @@ editAllButton.addEventListener("click", async () => { deleteAllButton.addEventListener("click", async () => { - + document.title = ""; const iframeWrappers = document.querySelectorAll('.iframe-wrapper'); iframeWrappers.forEach(wrapper => { wrapper.remove(); @@ -589,7 +689,6 @@ pcUAButton.addEventListener("click", () => { // If the input hasn't changed, do nothing if (newUrls.length === existingFilters.size && newUrls.every(url => existingFilters.has(url))) { - console.log("No changes in the input URLs. Exiting."); return; // No change, so do nothing } @@ -626,9 +725,7 @@ pcUAButton.addEventListener("click", () => { // Save iframe URLs to chrome.storage.local if there are any if (iframeUrls.length > 0) { - chrome.storage.local.set({ lastUrls: iframeUrls }, () => { - console.log("Iframe URLs saved to chrome.storage.local:", iframeUrls); - }); + chrome.storage.local.set({ lastUrls: iframeUrls }); } // Update dynamic rules and reload the page @@ -638,9 +735,14 @@ pcUAButton.addEventListener("click", () => { removeRuleIds: rulesToRemove, }, () => { - console.log("Rules updated:", { added: newRules, removed: rulesToRemove }); - // Reload the page - window.location.reload(); + const iframeWrappers = document.querySelectorAll('.iframe-wrapper'); + iframeWrappers.forEach(wrapper => { + // get the iframe URL under the current iframe-wrapper + const src = wrapper.querySelector('iframe').getAttribute('src'); + // refresh the iframe + wrapper.querySelector('iframe').src = src; + }); + } ); } diff --git a/firefox/manifest.json b/firefox/manifest.json index 5fd209e..4f080b2 100644 --- a/firefox/manifest.json +++ b/firefox/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Tabless", - "version": "1.6", + "version": "1.7", "permissions": [ "declarativeNetRequest", "storage"