v1.1! New "Click all similar features" button! New icons! Overall improved the codebase.

This commit is contained in:
Ad5001 2021-08-27 22:02:52 +02:00
parent 9d88437c3a
commit f2dd5c9525
Signed by: Ad5001
GPG key ID: EF45F9C6AFE20160
12 changed files with 365 additions and 321 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
.kdev4/
*.kdev4

View file

@ -10,6 +10,10 @@ This extension is rather simple and allows you to check or uncheck all your chec
One button and no more checkboxes ticked.
This extension also features another functionality for websites that do not use checkboxes, but buttons instead: the "Click all similar buttons" feature.
![Image of unchecker's context menu](https://apps.ad5001.eu/img/en/unchecker/contextmenu.png)
By using this feature on an "Off" or "Disable" button, it click all buttons with the same label, similar to how all checkboxes are unticked when using the normal button.
## "I've seen an issue"
If you have any issue (like a website not working), don't hesitate to create an issue on https://github.com/Ad5001/unchecker/issues
If you have any issue (like a website not working), don't hesitate to create an issue on https://git.ad5001.eu/Ad5001/unchecker/issues

View file

@ -1,90 +0,0 @@
const UNCHK_SCRIPT = `
function disable_checkboxes(element){
document.body.querySelectorAll('input[type="checkbox"]').forEach(function(el){
el.checked = false
})
}
disable_checkboxes(document.body)
document.body.querySelectorAll('iframe').forEach(function(el){disable_checkboxes(el.contentDocument || el.contentWindow.document)})
`
const CHK_SCRIPT = `
function check_checkboxes(element){
document.body.querySelectorAll('input[type="checkbox"]').forEach(function(el){
el.checked = true
})
}
check_checkboxes(document.body)
document.body.querySelectorAll('iframe').forEach(function(el){check_checkboxes(el.contentDocument || el.contentWindow.document)})
`
const TITLE_APPLY = "Uncheck all checkboxes";
const TITLE_REMOVE = "Check all checkboxes";
const APPLICABLE_PROTOCOLS = ["http:", "https:"];
/*
Toggle Script: based on the current title, insert or remove the Script.
Update the page action's title and icon to reflect its state.
*/
function toggleScript(tab) {
function gotTitle(title) {
if (title === TITLE_APPLY) {
browser.browserAction.setIcon({tabId: tab.id, path: "icons/off.svg"});
browser.browserAction.setTitle({tabId: tab.id, title: TITLE_REMOVE});
browser.tabs.executeScript({
code: UNCHK_SCRIPT
});
} else {
browser.browserAction.setIcon({tabId: tab.id, path: "icons/on.svg"});
browser.browserAction.setTitle({tabId: tab.id, title: TITLE_APPLY});
browser.tabs.executeScript({
code: CHK_SCRIPT
});
}
}
var gettingTitle = browser.browserAction.getTitle({tabId: tab.id});
gettingTitle.then(gotTitle);
}
/*
Returns true only if the URL's protocol is in APPLICABLE_PROTOCOLS.
*/
function protocolIsApplicable(url) {
var anchor = document.createElement('a');
anchor.href = url;
return APPLICABLE_PROTOCOLS.includes(anchor.protocol);
}
/*
Initialize the page action: set icon and title, then show.
Only operates on tabs whose URL's protocol is applicable.
*/
function initializebrowserAction(tab) {
if (protocolIsApplicable(tab.url)) {
browser.browserAction.setIcon({tabId: tab.id, path: "icons/on.svg"});
browser.browserAction.setTitle({tabId: tab.id, title: TITLE_APPLY});
browser.browserAction.show(tab.id);
}
}
/*
When first loaded, initialize the page action for all tabs.
*/
var gettingAllTabs = browser.tabs.query({});
gettingAllTabs.then((tabs) => {
for (let tab of tabs) {
initializebrowserAction(tab);
}
});
/*
Each time a tab is updated, reset the page action for that tab.
*/
browser.tabs.onUpdated.addListener((id, changeInfo, tab) => {
initializebrowserAction(tab);
});
/*
Toggle Script when the page action is clicked.
*/
browser.browserAction.onClicked.addListener(toggleScript);

60
clickall.js Normal file
View file

@ -0,0 +1,60 @@
/**
* Unchecker - Simple extension letting you uncheck all checkboxes on a page
* Copyright (c) Ad5001 2021
*
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/.
**/
// This file handles all clicking automaticly all similar buttons (e.g : same text & element name)
const CLICK_ALL_SCRIPT = `
var bound, selectedElements, clickedButton, buttonText, classes, query, sameElements;
// Get the potential selected button
bound = browser.menus.getTargetElement(targetElementId).getBoundingClientRect();
selectedElements = document.elementsFromPoint(bound.x+bound.width/2, bound.y+bound.height/2)
// Leftover debug for positioning
//console.log(bound, browser.menus.getTargetElement(targetElementId), selectedElements)
//var div = document.createElement("div"); div.style.background = "black"; div.style.position = "absolute";
//div.style.left = bound.x+bound.width/2-5 +"px"; div.style.top = bound.y+bound.height/2-5 + "px";
//div.style.width = "10px"; div.style.height = "10px";
//document.body.appendChild(div);
selectedElements = selectedElements.filter(x => ["BUTTON","A","INPUT"].indexOf(x.tagName) > -1)
// If a button is selected
if(selectedElements.length > 0) {
clickedButton = selectedElements[0]
// Gather element that will be used in similar buttons (same text content).
buttonText = clickedButton.textContent.trim()
// Find the similar buttons
query = clickedButton.localName + (clickedButton.tagName == "INPUT" ? "[type=" + clickedButton.type + "]" : "")
sameElements = document.querySelectorAll(query)
sameElements = Array.from(sameElements).filter(btn => btn.textContent.trim() == buttonText)
// Click them automaticly.
sameElements.forEach(btn => {
btn.click()
})
}
` // Requires targetElementId to be defined beforehands
const CLICK_ALL_TITLE = "Click all similar buttons";
const CLICK_ALL_MENU_CONTEXTS = ["editable", "image", "link", "page"];
function clickAllSimilarButtons(info, tab) {
browser.tabs.executeScript(tab.id, {
frameId: info.frameId,
code: `var targetElementId = ${info.targetElementId};${CLICK_ALL_SCRIPT}`,
});
}
browser.menus.create({
id: "unchecker-clickall",
title: CLICK_ALL_TITLE,
icons: {
"16": "icons/click.svg",
"32": "icons/click.svg"
},
contexts: CLICK_ALL_MENU_CONTEXTS,
onclick(info, tab) { clickAllSimilarButtons(info, tab) }
});

10
icons/click.svg Normal file
View file

@ -0,0 +1,10 @@
<svg id="SVGRoot" width="32" height="32" version="1.1" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<g fill="#808080">
<path d="m15.78 7.583 16 12.279-6.78 1.138 4.256 8.676-3.902 1.907-4.281-8.758-5.293 4.581z"/>
<g fill-rule="evenodd" stroke-width="1.8898">
<path d="m0 3v12s0 3 3 3h9v-4h-6s-2 0-2-2v-6c0-2 2-2 2-2h20c2 0 2 2 2 2v6l4 3.1172v-12.117c0-3-3-3-3-3h-26s-3 0-3 3z"/>
<path d="m0 19h4s0 2 2 2h6v4h-8c-4 0-4-4-4-4z"/>
<path d="m0 26h4s0 2 2 2h6v4h-8c-4 0-4-4-4-4z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 523 B

BIN
icons/off.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -1,100 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="20px"
version="1.1"
viewBox="0 0 20 20"
width="20px"
id="svg12"
sodipodi:docname="off.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata16">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1008"
id="namedview14"
showgrid="false"
inkscape:zoom="16"
inkscape:cx="16.458466"
inkscape:cy="9.7844187"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg12"
inkscape:measure-start="0,0"
inkscape:measure-end="0,0" />
<desc
id="desc4" />
<defs
id="defs6" />
<g
id="Page-1"
transform="matrix(0.5,0,0,0.5,0,5)"
style="fill:#333333;fill-rule:evenodd;stroke:none;stroke-width:1">
<g
id="Core"
transform="translate(-170,-86)"
style="fill:#333333">
<g
id="check-circle-outline-blank"
transform="translate(170,86)"
style="fill:#333333">
<path
d="M 10,0 C 4.5,0 0,4.5 0,10 0,15.5 4.5,20 10,20 15.5,20 20,15.5 20,10 20,4.5 15.5,0 10,0 Z m 0.0078,17 C 5.6078125,17 3.0054175,14.4 3.0054175,10 3.0054175,5.6 5.6,3 10,3 c 4.4,0 8,2.6 8,7 0,4.4 -3.592187,7 -7.992187,7 z"
id="Shape"
inkscape:connector-curvature="0"
style="fill:#333333"
sodipodi:nodetypes="ssssssssss" />
</g>
</g>
</g>
<rect
style="fill:#333333;stroke-width:1.14508271"
id="rect3724"
width="10"
height="1.4978296"
x="5"
y="5" />
<path
id="Shape-3"
style="fill:#333333;fill-rule:evenodd;stroke:none;stroke-width:0.5"
d="m 15,5 c -1.017755,0 -1.962173,0.3127537 -2.75,0.84375 0.06776,-0.00146 0.135653,-0.00264 0.203125,-0.00391 0.07613,-0.00143 0.150419,-0.00252 0.226563,-0.00195 0.107746,0.00134 0.215832,0.013662 0.322265,0.029297 0.05838,0.00958 0.116918,0.017699 0.175781,0.023437 0.03789,0.00358 0.07532,0.00511 0.113282,0.00781 0.580099,0.04116 0.886095,0.3036967 0.978515,0.59375 0.0069,-0.00202 0.0044,-0.00987 0.01367,-0.00977 0.0087,9.5e-5 0.01863,4.569e-4 0.02734,0 0.01238,-7.539e-4 0.02471,-0.00151 0.03711,-0.00195 0.01247,-7.873e-4 0.02467,-7.906e-4 0.03711,-0.00195 0.01191,-0.00129 0.02325,-0.00269 0.03516,-0.00391 0.01032,-0.00105 0.0209,-0.00131 0.03125,-0.00195 0.0094,-5.48e-4 0.01993,-0.00162 0.0293,-0.00195 0.0077,-2.774e-4 0.01376,1.611e-4 0.02148,0 0.0069,-1.759e-4 0.01459,-0.0014 0.02149,-0.00195 0.0088,-6.666e-4 0.01848,4.1e-4 0.02734,0 0.0089,-1.831e-4 0.01652,-0.00124 0.02539,-0.00195 0.0096,-7.737e-4 0.01964,-0.00142 0.0293,-0.00195 0.0087,-4.687e-4 0.01669,-0.00172 0.02539,-0.00195 0.01071,-2.653e-4 0.02248,1.18e-4 0.0332,0 0.01016,-1.074e-4 0.02109,6.47e-5 0.03125,0 0.0083,-4.83e-5 0.01518,3.37e-5 0.02344,0 h 0.0078 c 0.03112,-1.145e-4 0.04211,0.011967 0.04297,0.025391 0.0032,4.11e-5 0.0063,8.44e-5 0.0098,0 0.0067,-2.785e-4 0.01282,-6.63e-4 0.01953,0 0.0073,1.893e-4 0.01461,0.00413 0.02148,0.00586 0.002,6.216e-4 0.0039,0.00162 0.0059,0.00195 0.0091,-0.00812 0.0092,-0.021484 0.0293,-0.021484 h 0.02344 0.0039 c 0.01171,0 0.01082,0.00813 0.01758,0.011719 0.0082,-0.00404 0.0064,-0.013672 0.01953,-0.013672 h 0.01758 0.01563 c 0.02707,0 0.035,0.014347 0.04102,0.027344 0.002,-4.51e-5 0.0039,0 0.0059,0 2.2,0 3.498047,1.3 3.498047,3.5 0,2.2 -1.301953,3.5 -3.501953,3.5 -0.0027,0 -0.0052,7.3e-5 -0.0078,0 -0.0081,0.0091 -0.01029,0.02096 -0.03125,0.02148 -0.0095,2.39e-4 -0.01786,-4.07e-4 -0.02734,0 -0.0083,3.76e-4 -0.01709,0.0012 -0.02539,0.002 -0.0084,7.66e-4 -0.0071,-0.0066 -0.01367,-0.0078 -0.0059,6.91e-4 -0.01163,0.0016 -0.01758,0.002 -0.0086,6.27e-4 -0.01673,0.0021 -0.02539,0.002 h -0.02344 -0.02539 -0.02734 -0.02734 -0.02344 c -0.0024,0 -0.0017,-0.0018 -0.0039,-0.002 -0.132239,0.349342 -1.840827,0.622525 -0.816406,0.992188 -0.01305,-0.0033 -0.03016,-0.0066 -0.04492,-0.0098 -0.0065,-0.0014 -0.0069,7.6e-5 -0.01172,-0.002 0.0093,-0.0011 0.007,-5.28e-4 -0.01367,-0.002 -0.03387,-0.0018 -0.0677,-0.0039 -0.101562,-0.0059 -0.01115,-6.69e-4 -0.02205,-0.0013 -0.0332,-0.002 -0.07846,-0.0052 -0.156196,-0.01103 -0.234374,-0.01953 -0.09564,-0.01086 -0.190534,-0.02318 -0.285157,-0.04102 -0.118534,-0.02245 -0.236979,-0.04664 -0.353515,-0.07813 -0.101479,-0.02835 -0.20318,-0.05719 -0.302735,-0.0918 -0.07283,-0.0246 -0.147154,-0.04915 -0.216797,-0.08203 -0.03706,-0.01699 -0.07384,-0.03472 -0.111328,-0.05078 C 12.993489,14.675558 13.959976,15 15,15 c 2.75,0 5,-2.25 5,-5 0,-2.75 -2.25,-5 -5,-5 z m -2.625,7.710938 c 0.0015,0.0029 0.0044,0.0049 0.0059,0.0078 0.0072,0.0031 0.01426,0.0066 0.02149,0.0098 -0.0088,-0.0062 -0.01858,-0.01128 -0.02734,-0.01758 z" />
<rect
style="fill:#333333;stroke-width:1.14615846"
id="rect3724-6"
width="10"
height="1.5006453"
x="5"
y="13.5" />
<circle
style="fill:#333333;stroke-width:1.42857134"
id="path3807"
cx="5"
cy="10"
r="5" />
<svg width="20px" height="20px" version="1.1" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path d="m5 5c-2.77 0-5 2.23-5 5s2.23 5 5 5h10c2.77 0 5-2.23 5-5s-2.23-5-5-5h-10zm0 2h10c1.662 0 3 1.338 3 3s-1.338 3-3 3h-10c-1.662 0-3-1.338-3-3s1.338-3 3-3z" fill="#808080" fill-rule="evenodd" stroke-width="1.8898"/>
<rect y="5" width="10" height="10" ry="5" fill="#808080" fill-rule="evenodd" stroke-width="2.0692"/>
</svg>

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 432 B

View file

@ -1,104 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="20px"
version="1.1"
viewBox="0 0 20 20"
width="20px"
id="svg12"
sodipodi:docname="on.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata16">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1008"
id="namedview14"
showgrid="false"
inkscape:zoom="16"
inkscape:cx="16.458466"
inkscape:cy="9.7844187"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg12"
inkscape:measure-start="0,0"
inkscape:measure-end="0,0" />
<desc
id="desc4" />
<defs
id="defs6" />
<g
id="Page-1"
transform="matrix(-0.5,0,0,0.5,20,5)"
style="fill:#333333;fill-rule:evenodd;stroke:none;stroke-width:1">
<g
id="Core"
transform="translate(-170,-86)"
style="fill:#333333">
<g
id="check-circle-outline-blank"
transform="translate(170,86)"
style="fill:#333333">
<path
d="M 10,0 C 4.5,0 0,4.5 0,10 0,15.5 4.5,20 10,20 15.5,20 20,15.5 20,10 20,4.5 15.5,0 10,0 Z m 0.0078,17 C 5.6078125,17 3.0054175,14.4 3.0054175,10 3.0054175,5.6 5.6,3 10,3 c 4.4,0 8,2.6 8,7 0,4.4 -3.592187,7 -7.992187,7 z"
id="Shape"
inkscape:connector-curvature="0"
style="fill:#333333"
sodipodi:nodetypes="ssssssssss" />
</g>
</g>
</g>
<rect
style="fill:#0000ff;stroke-width:1.14508271"
id="rect3724"
width="10"
height="1.4978296"
x="-15"
y="5"
transform="scale(-1,1)" />
<path
id="Shape-3"
style="fill:#0000ff;fill-rule:evenodd;stroke:none;stroke-width:0.5"
d="M 5,5 C 6.017755,5 6.962173,5.3127537 7.75,5.84375 7.68224,5.84229 7.614347,5.84111 7.546875,5.83984 7.470745,5.83841 7.396456,5.83732 7.320312,5.83789 7.212566,5.83923 7.10448,5.851552 6.998047,5.867187 6.939667,5.876767 6.881129,5.884886 6.822266,5.890624 c -0.03789,0.00358 -0.07532,0.00511 -0.113282,0.00781 -0.580099,0.04116 -0.886095,0.3036967 -0.978515,0.59375 -0.0069,-0.00202 -0.0044,-0.00987 -0.01367,-0.00977 -0.0087,9.5e-5 -0.01863,4.569e-4 -0.02734,0 -0.01238,-7.539e-4 -0.02471,-0.00151 -0.03711,-0.00195 -0.01247,-7.873e-4 -0.02467,-7.906e-4 -0.03711,-0.00195 -0.01191,-0.00129 -0.02325,-0.00269 -0.03516,-0.00391 -0.01032,-0.00105 -0.0209,-0.00131 -0.03125,-0.00195 -0.0094,-5.48e-4 -0.01993,-0.00162 -0.0293,-0.00195 -0.0077,-2.774e-4 -0.01376,1.611e-4 -0.02148,0 -0.0069,-1.759e-4 -0.01459,-0.0014 -0.02149,-0.00195 -0.0088,-6.666e-4 -0.01848,4.1e-4 -0.02734,0 -0.0089,-1.831e-4 -0.01652,-0.00124 -0.02539,-0.00195 -0.0096,-7.737e-4 -0.01964,-0.00142 -0.0293,-0.00195 -0.0087,-4.687e-4 -0.01669,-0.00172 -0.02539,-0.00195 -0.01071,-2.653e-4 -0.02248,1.18e-4 -0.0332,0 -0.01016,-1.074e-4 -0.02109,6.47e-5 -0.03125,0 -0.0083,-4.83e-5 -0.01518,3.37e-5 -0.02344,0 h -0.0078 c -0.03112,-1.145e-4 -0.04211,0.011967 -0.04297,0.025391 -0.0032,4.11e-5 -0.0063,8.44e-5 -0.0098,0 -0.0067,-2.785e-4 -0.01282,-6.63e-4 -0.01953,0 -0.0073,1.893e-4 -0.01461,0.00413 -0.02148,0.00586 -0.002,6.216e-4 -0.0039,0.00162 -0.0059,0.00195 -0.0091,-0.00812 -0.0092,-0.021484 -0.0293,-0.021484 h -0.02344 -0.0039 c -0.01171,0 -0.01082,0.00813 -0.01758,0.011719 -0.0082,-0.00404 -0.0064,-0.013672 -0.01953,-0.013672 h -0.01758 -0.01563 c -0.02707,0 -0.035,0.014347 -0.04102,0.027344 -0.002,-4.51e-5 -0.0039,0 -0.0059,0 -2.2,0 -3.498047,1.3 -3.498047,3.5 0,2.2 1.301953,3.5 3.501953,3.5 0.0027,0 0.0052,7.3e-5 0.0078,0 0.0081,0.0091 0.01029,0.02096 0.03125,0.02148 0.0095,2.39e-4 0.01786,-4.07e-4 0.02734,0 0.0083,3.76e-4 0.01709,0.0012 0.02539,0.002 0.0084,7.66e-4 0.0071,-0.0066 0.01367,-0.0078 0.0059,6.91e-4 0.01163,0.0016 0.01758,0.002 0.0086,6.27e-4 0.01673,0.0021 0.02539,0.002 h 0.02344 0.02539 0.02734 0.02734 0.02344 c 0.0024,0 0.0017,-0.0018 0.0039,-0.002 0.132239,0.349342 1.840827,0.622525 0.816406,0.992188 0.01305,-0.0033 0.03016,-0.0066 0.04492,-0.0098 0.0065,-0.0014 0.0069,7.6e-5 0.01172,-0.002 -0.0093,-0.0011 -0.007,-5.28e-4 0.01367,-0.002 0.03387,-0.0018 0.0677,-0.0039 0.101562,-0.0059 0.01115,-6.69e-4 0.02205,-0.0013 0.0332,-0.002 0.07846,-0.0052 0.156196,-0.01103 0.234374,-0.01953 0.09564,-0.01086 0.190534,-0.02318 0.285157,-0.04102 0.118534,-0.02245 0.236979,-0.04664 0.353515,-0.07813 0.101479,-0.02835 0.20318,-0.05719 0.302735,-0.0918 0.07283,-0.0246 0.147154,-0.04915 0.216797,-0.08203 0.03706,-0.01699 0.07384,-0.03472 0.111328,-0.05078 C 7.006511,14.675558 6.040024,15 5,15 2.25,15 0,12.75 0,10 0,7.25 2.25,5 5,5 Z m 2.625,7.710938 c -0.0015,0.0029 -0.0044,0.0049 -0.0059,0.0078 -0.0072,0.0031 -0.01426,0.0066 -0.02149,0.0098 0.0088,-0.0062 0.01858,-0.01128 0.02734,-0.01758 z"
inkscape:connector-curvature="0" />
<rect
style="fill:#0000ff;stroke-width:1.14615846"
id="rect3724-6"
width="10"
height="1.5006453"
x="-15"
y="13.5"
transform="scale(-1,1)" />
<circle
style="fill:#0000ff;stroke-width:1.42857134"
id="path3807"
cx="-15"
cy="10"
r="5"
transform="scale(-1,1)" />
<svg width="20px" height="20px" version="1.1" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path d="m5 5c-2.77 0-5 2.23-5 5s2.23 5 5 5h10c2.77 0 5-2.23 5-5s-2.23-5-5-5h-10zm0 2h10c1.662 0 3 1.338 3 3s-1.338 3-3 3h-10c-1.662 0-3-1.338-3-3s1.338-3 3-3z" fill="#2a7fff" fill-rule="evenodd" stroke-width="1.8898"/>
<rect x="10" y="5" width="10" height="10" ry="5" fill="#2a7fff" fill-rule="evenodd" stroke-width="2.0692"/>
</svg>

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 439 B

View file

@ -1,34 +1,38 @@
{
"description": "Simple extension letting you uncheck all checkboxes on a page.",
"manifest_version": 2,
"name": "unchecker",
"version": "1.0",
"author": "Ad5001",
"developer": {
"name": "Ad5001",
"url": "https://ad5001.eu"
},
"applications": {
"gecko": {
"id": "unchecker@ad5001.eu",
"strict_min_version": "42.0"
}
},
"homepage_url": "https://github.com/Ad5001/unchecker",
"description": "Simple extension letting you uncheck all checkboxes on a page.",
"manifest_version": 2,
"name": "unchecker",
"version": "1.1",
"author": "Ad5001",
"developer": {
"name": "Ad5001",
"url": "https://ad5001.eu"
},
"applications": {
"gecko": {
"id": "unchecker@ad5001.eu",
"strict_min_version": "60.0"
}
},
"homepage_url": "https://apps.ad5001.eu/unchecker/",
"background": {
"scripts": ["background.js"]
},
"background": {
"scripts": ["uncheck.js", "clickall.js"]
},
"browser_action": {
"default_icon": "icons/off.svg",
"browser_style": true
},
"permissions": [
"activeTab",
"tabs"
]
"browser_action": {
"default_icon": "icons/on.svg",
"browser_style": true
},
"icons": {
"48": "icons/off.svg",
"96": "icons/off.svg"
},
"permissions": [
"activeTab",
"tabs",
"menus"
]
}

85
test/test.html Normal file
View file

@ -0,0 +1,85 @@
<!--
* Unchecker - Simple extension letting you uncheck all checkboxes on a page
* Copyright (c) Ad5001 2021
*
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/.
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Unchecker tests</title>
<style>
legend {
background-color: #000;
color: #fff;
padding: 3px 6px;
}
.toggled {
border-color: blue;
}
input {
margin: .4rem;
}
</style>
<script src="test.js"></script>
</head>
<body>
<fieldset>
<legend>Example radio list</legend>
<input type="radio" id="choice-value1" name="choice-value">
<label for="choice-value">Example, irrelevant choice value 1</label><br/>
<input type="radio" id="choice-value2" name="choice-value">
<label for="choice-value">Example, irrelevant choice value 2</label><br/>
</fieldset>
<br>
<fieldset>
<legend>Third party partners example</legend>
<input type="checkbox" id="ga-choice" checked="true">
<label for="ga-choice">Google Analytics</label><br/>
<input type="checkbox" id="facebook-ads" checked="true">
<label for="facebook-ads">Facebook Partnering</label><br/>
<input type="checkbox" id="amazon-sales" checked="true">
<label for="amazon-sales">Amazon</label><br/>
<input type="checkbox" id="salesforce" checked="true">
<label for="salesforce">Salesforce</label><br/>
</fieldset>
<br>
<fieldset>
<legend>Third party partners second</legend>
<table>
<tr>
<td>Google Analytics</td>
<td><button role="toggle" class="toggled" name="ga-choice">On</button></td>
<td><button role="toggle" name="ga-choice">Off</button></td>
</tr>
<tr>
<td>Facebook Partnering</td>
<td><button role="toggle" class="toggled" name="facebook-ads">On</button></td>
<td><button role="toggle" name="facebook-ads">Off</button></td>
</tr>
<tr>
<td>Amazon</td>
<td><button role="toggle" class="toggled" name="amazon-sales">On</button></td>
<td><button role="toggle" name="amazon-sales">Off</button></td>
</tr>
<tr>
<td>Salesforce</td>
<td><button role="toggle" class="toggled" name="salesforce">On</button></td>
<td><button role="toggle" name="salesforce">Off</button></td>
</tr>
</table>
</fieldset>
</body>
</html>

18
test/test.js Normal file
View file

@ -0,0 +1,18 @@
/**
* Unchecker - Simple extension letting you uncheck all checkboxes on a page
* Copyright (c) Ad5001 2021
*
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/.
**/
window.addEventListener("load", () => {
document.querySelectorAll("button[role=toggle]").forEach(button => {
button.addEventListener("click", () => {
Array.from(document.querySelectorAll("button[role=toggle]")).filter(btn => btn.name == button.name).forEach(btn => {
btn.classList.remove("toggled")
})
button.classList.add("toggled")
})
})
})

146
uncheck.js Normal file
View file

@ -0,0 +1,146 @@
/**
* Unchecker - Simple extension letting you uncheck all checkboxes on a page
* Copyright (c) Ad5001 2021
*
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/.
**/
const UNCHK_SCRIPT = `
function disable_checkboxes(element){
document.body.querySelectorAll('input[type="checkbox"]').forEach(function(el){
el.checked = false
})
}
disable_checkboxes(document.body)
document.body.querySelectorAll('iframe').forEach(function(el){disable_checkboxes(el.contentDocument || el.contentWindow.document)})
`
const CHK_SCRIPT = `
function check_checkboxes(element){
document.body.querySelectorAll('input[type="checkbox"]').forEach(function(el){
el.checked = true
})
}
check_checkboxes(document.body)
document.body.querySelectorAll('iframe').forEach(function(el){check_checkboxes(el.contentDocument || el.contentWindow.document)})
`
const TITLE_APPLY = "Uncheck all checkboxes";
const TITLE_REMOVE = "Check all checkboxes";
const APPLICABLE_PROTOCOLS = ["http:", "https:"];
const MENU_CONTEXTS = ["editable", "image", "link", "page"];
/**
* Toggle Script: based on the current title, insert or remove the Script.
* Update the page action's title and icon, aswell as the context menu item to reflect its state.
**/
function toggleScript(tab) {
function gotTitle(title) {
if (title === TITLE_APPLY) {
browser.browserAction.setIcon({tabId: tab.id, path: "icons/off.svg"});
browser.browserAction.setTitle({tabId: tab.id, title: TITLE_REMOVE});
browser.menus.remove("unchecker-main").then(function() {
browser.menus.create({
id: "unchecker-main",
title: TITLE_REMOVE,
icons: {
"16": "icons/off.svg"
},
contexts: MENU_CONTEXTS,
onclick(info,tab) { toggleScript(tab) }
});
}, function(){})
browser.tabs.executeScript({
code: UNCHK_SCRIPT
});
} else {
browser.browserAction.setIcon({tabId: tab.id, path: "icons/on.svg"});
browser.browserAction.setTitle({tabId: tab.id, title: TITLE_APPLY});
browser.menus.remove("unchecker-main").then(function() {
browser.menus.create({
id: "unchecker-main",
title: TITLE_APPLY,
icons: {
"16": "icons/on.svg"
},
contexts: MENU_CONTEXTS,
onclick(info,tab) { toggleScript(tab) }
});
}, function(){})
browser.tabs.executeScript({
code: CHK_SCRIPT
});
}
}
var gettingTitle = browser.browserAction.getTitle({tabId: tab.id});
gettingTitle.then(gotTitle);
}
/**
* Returns true only if the URL's protocol is in APPLICABLE_PROTOCOLS.
**/
function protocolIsApplicable(url) {
let anchor = document.createElement('a');
anchor.href = url;
return APPLICABLE_PROTOCOLS.includes(anchor.protocol);
}
/**
* Initialize the page action: set icon and title, then show.
* Only operates on tabs whose URL's protocol is applicable.
**/
function initializebrowserAction(tab, createMenu) {
if(protocolIsApplicable(tab.url)) {
browser.browserAction.setIcon({tabId: tab.id, path: "icons/on.svg"});
browser.browserAction.setTitle({tabId: tab.id, title: TITLE_APPLY});
browser.browserAction.show(tab.id);
}
if(createMenu) {
browser.menus.remove("unchecker-main").then(function() {
browser.menus.create({
id: "unchecker-main",
title: TITLE_APPLY,
icons: {
"16": "icons/on.svg"
},
contexts: MENU_CONTEXTS,
onclick(info,tab) { toggleScript(tab) }
});
}, function(){})
}
}
/**
* When first loaded, initialize the page action for all tabs.
**/
browser.menus.create({
id: "unchecker-main",
title: TITLE_APPLY,
icons: {
"16": "icons/on.svg"
},
contexts: MENU_CONTEXTS,
onclick(info,tab) { toggleScript(tab) }
});
let gettingAllTabs = browser.tabs.query({});
gettingAllTabs.then((tabs) => {
for (let tab of tabs) {
initializebrowserAction(tab, false);
}
});
/**
* Each time a tab is updated, reset the page action for that tab.
**/
browser.tabs.onUpdated.addListener((id, changeInfo, tab) => {
initializebrowserAction(tab, true);
});
/**
* Toggle Script when the page action is clicked.
**/
browser.browserAction.onClicked.addListener(toggleScript);