DW42 DW42 - 9 months ago 51
HTML Question

Chrome Extension set storage value on checkbox click

I am working on a Google Chrome extension which hides, moves, and otherwise alters elements of the current page, utilizing contentscripts to do so. I am working on a page which has a few elements I change, so I have a storage.sync value set for each. Due to the drastic nature of the changes each option effects, I have the toggles for each in my popup. I have tried to have each checkbox set the storage.sync value for the id of the checkbox to the boolean value of the checkbox using jQuery, specifically jQuery.click and jQuery.each. My popup's html is:

<html>
<head>
<title>Options</title>
<script src="jquery-3.1.1.min.js"></script>
<script src="popup.js"></script>
</head>
<body style="width: 400px">
<h3>Settings</h3>
<input class="option" id="opt1" type="checkbox">Option 1.</input><br>
<input class="option" id="opt2" type="checkbox">Option 2.</input><br>
<input class="option" id="opt3" type="checkbox">Option 3.</input>
<button id="other">TBI</button>
</body>
</html>


where 'jquery-3.1.1.min' is the minified jQuery source and popup.js is:

$(document).ready(function() {
$('.option').each(function(index, elem) {
chrome.storage.sync.get(elem.id, function (value) {
elem.checked = value.fix;
});
elem.change(function() {
chrome.storage.sync.set({this.id: this.checked);
});
});
});


I have also tried the replacing
this
with everything from
elem
to
$(this)[0]
, as well as
$(elem)
, but each time I get errors of a different source. In general,
elem
produces
Uncaught SyntaxError: Unexpected token .
and
this
produces
Uncaught SyntaxError: Unexpected token this
.

Why does this occur? How can I avoid this? I am primarily a python coder, so I expect I am misunderstanding the scope of each value or the meaning of
this
. What I don't understand is how that translates into
Unexpected token
errors. Thank you!

Answer Source
  1. this.id is an invalid key in an object literal.
    You can use {[this.id]: this.checked} if you're okay with ES2015 requirement.
    Or use a temporary object variable: var o = {}; o[this.id] = this.checked;
  2. Typo: missing } in the object literal.
  3. chrome.storage is asynchronous so elem.change is attached before the value is actually retrieved, which might be not what you really want. However, in this case it's not a big deal: you just write the same value back to chrome.storage.
  4. It's better to read all values in one go by providing an array of keys:

    chrome.storage.sync.get(
        $('.option').map((i, el) => el.id),
        data => {
            $.each(data, (id, value) => $(`#${id}`)[0].checked = value);
            $('.option').change(function() {
                chrome.storage.sync.set({[this.id]: this.checked});
            });
        }
    );