MaryPanda
MaryPanda

Reputation: 35

Save chrome extension options to chrome.storage?

I'm making a chrome extension that has an options.html page.

On the options page I have 3 checkboxes. When one of the checkboxes is checked/unchecked the value of that checkbox is saved to- or removed from chrome.storage using chrome.storage.sync.set(). But I can't seem to retrieve the data once it is saved using chrome.storage.sync.get().

Here's the code I have:

options.html:

<div class="checkboxes">
    <input id="test1" name="test1" type="checkbox">       
    <input id="test2" name="test2" type="checkbox">
    <input id="test3" name="test3" type="checkbox">
</div>

options.js:

$(document).ready(function() {

  var storage = chrome.storage.sync;

  //Retrieve existing settings
  $(':checkbox').each(function() {
    $(this).prop('checked', function() {
      var name = this.name;
      storage.get(name, function(test){
        console.log(test[name]);
      });
    });
  });

  $(".checkboxes").on("change", ":checkbox", saveSettings);

  //Save or delete settings
  function saveSettings() {
    var name = this.name;   

    if($(this).is(':checked')) {
      storage.set({name:'checked'},function(){
        console.log("saved");
      });
    }
    else {
      storage.remove(name, function(){
        console.log("removed");
      });
    }
  }

});

Above outputs:

console.log(test[name]); > undefined
console.log("saved");    > saved
console.log("removed");  > removed

Why do I get "undefined"?

I tired the same thing using localStorage which worked fine on only option.js. But when I tried to retrieve the stored data on background.js it didn't work. I figured their localStorage details are not accessible to each other.

I should also mention I'm not the best at javascript/jquery and I'm still learning, so please excuse my mistakes.

Upvotes: 1

Views: 5947

Answers (1)

Rob W
Rob W

Reputation: 348962

You've got two main issues:

  1. chrome.storage.sync.get is asynchronous, while the function in jQuery.fn.prop(propertyName, function(index, oldPropertyValue) ) must synchronously return the desired value.
  2. storage.set({name:'checked'}, ...); will create a property called "name" with value "checked", not a property with the name as specified in the name variable with value "checked".

To solve the first problem, swap the order of operations: First read the preference, then set the property:

//Retrieve existing settings
$(':checkbox').each(function(index, element) {
    var name = this.name;
    storage.get(name, function(items) {
        element.checked = items[name]; // true  OR  false / undefined (=false)
    });
});

To solve the second issue, first create an object, assign the new property, and save the result. Note: Since a checkbox can only have two states, I recommend to not save the string "checked", but use a boolean (true / false):

function saveSettings() {
    var name = this.name;
    var items = {};
    items[name] = this.checked;
    storage.set(items, function() {
        console.log("saved");
    });
}

PS. When you're certain that you're dealing with checkboxes, use element.checked instead of $(element).is(':checked'). The former is shorter and faster. Using jQuery adds no value here. See also: When to use Vanilla JavaScript vs. jQuery?

Upvotes: 7

Related Questions