Search code examples
javascriptgoogle-chrome-extension

Chrome extension checkboxes not removing styles


I have a Chrome extension that injects style sheets using multiple checkboxes. When checked adds the style sheets, when unchecked removes the style sheets. There is a button that add all and removes all styles.

What is working.

  • Checking and unchecking the individual checkboxes adds and removes the styles
  • Checking the All all button adds all styles to the page.

What is not working

  • Unchecking the Check all button (aria-pressed=false) does not remove the styles.
  • If all styles are added using the Add all button, none of the individual checkboxes work.

Can someone please explain why the functionality is not working. If I can get this to work, the next step is to use chrome.storage.local to save the state of the checkbox when the popup.html closes, but that is a whole new learning curve.

I should use a radio button group with check all yes/no rather than the button. And I've probably used way to much code for this functionality.

Any code guidance is appreciated.

POPUP.HTML

<!DOCTYPE html>
<html>

<head>
    <link rel="stylesheet" href="css/popup.css">
</head>

<body>
    <div class="ws-bm-aria-matrices-button" id="ws-bm-aria-matrices-parent">
        <fieldset>
            <legend>Options</legend>
        <button type="button" id="chkAllOptions" class="pressed" aria-pressed="false">All options</button>
            <ul>
                <li><label for="option01" class="switch--label">
                        <span class="label">Option 1</span>
                    </label>
                    <input id="option01" type="checkbox" name="chkAll">
                </li>
                <li><label for="option02" class="switch--label">
                        <span class="label">Option 2</span>
                    </label>
                    <input id="option02" type="checkbox" name="chkAll">
                </li>
                <li><label for="option03" class="switch--label">
                        <span class="label">Option 3</span>
                    </label>
                    <input id="option03" type="checkbox" name="chkAll">
                </li>
            </ul>
        </fieldset>
    </div>
    <script src="popup.js"></script>
</body>

</html>

POPUP.JS

let a = document.getElementById("chkAllOptions");
let b = document.getElementsByName('chkAll');
let c = document.getElementById("option01");
let d = document.getElementById("option02");
let e = document.getElementById("option03");

//Check uncheck all
a.addEventListener("click", async () => {
    let [tab] = await chrome.tabs.query({
        active: true,
        currentWindow: true
    });
    
  a.classList.toggle("pressed");
  a.setAttribute(
      'aria-pressed', 
      a.getAttribute('aria-pressed') === 'false' 
        ? 'true' 
        : 'false'
    );
   if (a.getAttribute('aria-pressed') === 'true') {
     for (let i = 0; i < b.length; i++) { 
       b[i].checked = true;
       b[i].setAttribute("aria-checked","true");
         
  try {
    chrome.scripting.insertCSS({
      target: {
        tabId: tab.id,
      },
      files: ["css/option01.css" , "css/option02.css" , "css/option03.css"],
    });
  } catch (err) {
    console.error(`failed to insert CSS: ${err}`);
  }
         
     }
   } else if (a.getAttribute('aria-pressed') === 'false') {
     for (let i = 0; i < b.length; i++) {
       b[i].checked = false;
       b[i].setAttribute("aria-checked","false");
     }
       
    try {
    await chrome.scripting.removeCSS({
      target: {
        tabId: tab.id,
      },
      files: ["css/option01.css" , "css/option02.css" , "css/option03.css"],
    });
  } catch (err) {
    console.error(`failed to remove CSS: ${err}`);
  }   
       
       
   }
 
 });
 
 //Individual checkboxes
 
 c.addEventListener("click", async () => {
    let [tab] = await chrome.tabs.query({
        active: true,
        currentWindow: true
    });
    
    c.setAttribute('aria-checked', c.getAttribute('aria-checked') === 'true' ? 'false' : 'true');

    if (c.getAttribute('aria-checked') === 'true') {

        try {
            await chrome.scripting.insertCSS({
                target: {
                    tabId: tab.id,
                },
                files: ["css/option01.css"],
            });
        } catch (err) {
            console.error(`failed to insert option 1 CSS: ${err}`);
        }

    } else if (c.getAttribute('aria-checked') === 'false') {

        try {
            await chrome.scripting.removeCSS({
                target: {
                    tabId: tab.id,
                },
                files: ["css/option01.css"],
            });
        } catch (err) {
            console.error(`failed to remove option 1 CSS: ${err}`);
        }

    }

});

d.addEventListener("click", async () => {
    let [tab] = await chrome.tabs.query({
        active: true,
        currentWindow: true
    });
    
    d.setAttribute('aria-checked', d.getAttribute('aria-checked') === 'true' ? 'false' : 'true');
    
    if (d.getAttribute('aria-checked') === 'true') {

        try {
            await chrome.scripting.insertCSS({
                target: {
                    tabId: tab.id,
                },
                files: ["css/option 2.css"],
            });
        } catch (err) {
            console.error(`failed to insert landmark CSS: ${err}`);
        }

    } else if (d.getAttribute('aria-checked') === 'false') {

        try {
            await chrome.scripting.removeCSS({
                target: {
                    tabId: tab.id,
                },
                files: ["css/option 2.css"],
            });
        } catch (err) {
            console.error(`failed to remove Option 2 CSS: ${err}`);
        }

    }

});

e.addEventListener("click", async () => {
    let [tab] = await chrome.tabs.query({
        active: true,
        currentWindow: true
    });
    
    e.setAttribute('aria-checked', e.getAttribute('aria-checked') === 'true' ? 'false' : 'true');
    
    if (e.getAttribute('aria-checked') === 'true') {

        try {
            await chrome.scripting.insertCSS({
                target: {
                    tabId: tab.id,
                },
                files: ["css/Option03.css"],
            });
        } catch (err) {
            console.error(`failed to insert option 3 CSS: ${err}`);
        }

    } else if (e.getAttribute('aria-checked') === 'false') {

        try {
            await chrome.scripting.removeCSS({
                target: {
                    tabId: tab.id,
                },
                files: ["css/option03.css"],
            });
        } catch (err) {
            console.error(`failed to remove Option 3 CSS: ${err}`);
        }

    }

});

Solution

  • There's a small but very important detail in the documentation of the removeCSS method, emphasis mine:

    injection
    CSSInjection
    The details of the styles to remove. Note that the css, files, and origin properties must exactly match the stylesheet inserted through insertCSS.

    What this means in practice: if you insert 3 stylesheets at once, trying to remove them one by one will fail (since it does not match exactly the files used before) and vice-versa.

    You should change your mass-insert and mass-remove logic to add/remove them one by one.