Saving and accessing API results in a variable in Chrome extension - javascript

I'm making a Chrome extension that pulls a large amount of data from an API and uses it to modify content on a page. Because the amount of data is so large, I'd like to be able to save it once in the browser and be able to access it instead of doing an API call each time a page loads.
It's my understanding this can be done by putting the API call in the background page and then calling the variable from the background page in the content script. I've also tried storing the data in local storage. Neither method is working for me and I don't understand what I'm doing wrong.
In my code in the background page, I have the API results stored in a variable. I'm calling it in the content script like this:
var background = chrome.extension.getBackgroundPage();
var myData = background.APIData; //where APIData is the variable I set in the background page
My attempt to use local storage looks like this:
//Background page
chrome.storage.sync.set({'value': APIData}, function() {
// Notify that we saved.
console.log('APIData saved to storage');
});
//Content script
var myData = localStorage["APIData"];
As of this moment, the extension isn't even loading in the page using the code where I'm trying to access local storage. The extension will load with the other method but the data doesn't seem to be there. I know my API call is working because the extension works when I put it all in the content script. But that creates the problem where I'm calling the API each time the page loads. Help please!

Examine your code closely. You are setting the data to two different bins.
First, you call chrome.storage.sync.set and set "value" to the value of APIData.
Second, you call localStorage['APIData'] which refers to a separate storage bin and property name.
Two solutions here, the first being the preferred way to set/get persistent data in a Chrome extension:
A1) set it with chrome.storage.sync.set( { value:data } )
A2) get it with chrome.storage.sync.get( null, function( storage ){ storage.value } )
B1) set it with localStorage.value = data
B2) get it with localStorage.value

Related

How do you save an array to session storage?

I've read a few similar threads, but the solutions are not working for me. The page I am working on has filters for a gallery of images. Each time I click on a filter the images with reload according to that filter via a JSON file.
If I want to apply multiple filters I would need the ones chosen prior to the reload to save in an array variable.
This is the code I have for this
let filterArray = []
sessionStorage.setItem('filterArray', JSON.stringify(filterArray))
let savedArr = JSON.parse(sessionStorage.getItem('filterArray'))
Right now I don't have the page reload set up but after clicking on a filter and refreshing the page I would expect to be able to log the 'savedArr' variable but when I do I get this:
Uncaught ReferenceError: savedArr is not defined
at :1:13
You can't log savedArr after you refresh the page, you need to redefine it.
The data in session storage will persist, but your variable declarations will not.
Call the declaration line again after you reload the page and you will have access to the data.
let savedArr = JSON.parse(sessionStorage.getItem('filterArray'))

Attempting to use a global array inside of a JS file shared between 2 HTML files and failing

So I have one HTML page which consists of a bunch of form elements for the user to fill out. I push all the selections that the user makes into one global variable, allTheData[] inside my only Javascript file.
Then I have a 2nd HTML page which loads in after a user clicks a button. This HTML page is supposed to take some of the data inside the allTheData array and display it. I am calling the function to display allTheData by using:
window.onload = function () {
if (window.location.href.indexOf('Two') > -1) {
carousel();
}
}
function carousel() {
console.log("oh");
alert(allTheData.toString());
}
However, I am finding that nothing gets displayed in my 2nd HTML page and the allTheData array appears to be empty despite it getting it filled out previously in the 1st HTML page. I am pretty confident that I am correctly pushing data into the allTheData array because when I use alert(allTheData.toString()) while i'm still inside my 1st HTML page, all the data gets displayed.
I think there's something happening during my transition from the 1st to 2nd HTML page that causes the allTheData array to empty or something but I am not sure what it is. Please help a newbie out!
Web Storage: This sounds like a job for the window.sessionStorage object, which along with its cousin window.localStorage allows data-as-strings to be saved in the users browser for use across pages on the same domain.
However, keep in mind that they are both Cookie-like features and therefore their effectiveness depends on the user's Cookie preference for each domain.
A simple condition will determine if the web storage option is available, like so...
if (window.sessionStorage) {
// continue with app ...
} else {
// inform user about web storage
// and ask them to accept Cookies
// before reloading the page (or whatever)
}
Saving to and retrieving from web storage requires conversion to-and-from String data types, usually via JSON methods like so...
// save to...
var array = ['item0', 'item1', 2, 3, 'IV'];
sessionStorage.myApp = JSON.stringify(array);
// retrieve from...
var array = JSON.parse(sessionStorage.myApp);
There are more specific methods available than these. Further details and compatibility tables etc in Using the Web Storage API # MDN.
Hope that helps. :)

html5 localstorage not working the way I want

I am using HTML5's localstorage to save two variables and load them when the user refreshes the page but something doesn't work properly when loading the saved item:
var's:
var cookies = 0;
var cursors = 0;
saving code:
window.setInterval(function(){
var save = [cookies, cursors];
localStorage["save"] = JSON.stringify(save);
console.log("Saved game");
}, 1000);
loading code:
function load() {
var state = JSON.parse(localStorage["save"]);
console.log("Loaded game");
}
What my console show's on page load:
[13,1]
Loaded game
[0,0]
Saved game
[0,0]
Saved game
[0,0]
Saved game
Etc.
The load() function gets called on body load (<body onload="load()">
and I DO get the console message "Loaded game"...
You syntax seems fine. However, JSLint recommends using dot notation on localStorage:
localStorage.save = JSON.stringify(save);
and
var state = JSON.parse(localStorage.save);
Then you can just add your state variable to the console.log statement to check it:
console.log("Loaded game: "+state);
Remember, your values have been saved as an array, so you'll have to access them with state[0] and state[1] to get the individual values.
There is nothing wrong with your localStorage access. Also, you don't need to try sessionStorage if is localStorage what you are looking for.
The problem, I think, is with how are you dealing with your data.
Judging by your code, you are reading the localStorage data and storing it into a local variable called state and doing nothing more with it.
Fact: if you are REALLY getting to save your data to localStorage with the
localStorage["save"] = JSON.stringify(save);
then the
var state = JSON.parse(localStorage["save"]);
would actually work, if performed anytime after the previous snippet. So, if your application is actually getting to run the snippet where you save the data, then later when you run the load function, the local variable state will have the content [0, 0].

Using AngularJS to process custom localStorage data

I wrote a bookmarklet that retrieves information from a page and stores it in JSON format in local storage (converting it to a string first, of course).
I would like a web app I am writing to be able to process this data, on the fly, preferably as it gets saved to the localStorage.
Right now i can change the item in LS via the console and refresh the page and the new data appears but I would like it to be live and seamless.
Any advice on how to go about this? I found several localStorage modules for angularJS and I tried them but they don't seem to allow me to retrieve from LS if the data is already there in LS.
In response to answer:
$scope.$watch(
function(){
return $window.localStorage.getItem('TestData');
},
function(newValueInStorage){
$scope.testingLS = newValueInStorage;
}
)
I tried this and I still get the data displayed by just doing a {{ testingLS }} in the view template but when I go and change the TestData key in local storage via the console it doesn't update instantly. (for now, I am just testing it without the bookmarklet with just a simple string inside TestData
There is few ways to do it
One of will be to populate correct model on scope when saving to localStorage
The other that I can think of at this moment is to setup watcher
$watch(
function(){
return localstorage object
},
function(newValueInStorage){
$scope.modelFromLS = JSON.parse(newValueInsStorage)
}
)
---edit---
as per James comment you need something that will handle the fact that data has changed in different tab and $digest process need to run for watch to be recalculated
http://plnkr.co/edit/zlS3wL65meBeA8KkV5KH?p=preview
window.addEventListener('focus', function(){
console.log('focus')
$scope.$digest()
})

Losing context reference

I am encountering a 'small' problem when making a new object in the options page.
In the options page I create a few objects and save them as general settings. These objects have method to communicate with different API's. But as soon as I get one of those objects to work with, I lose the context on the page I am.
For example:
The options page I create an object that has a method 'request' and I send an ajax request to some api with this method. When I call this on an other page the ajax request is logged within the options page. When I close the options page I lose all context of the logs it makes.
Is there a way to force the context reference to the current page? or did I make a mistake with creating objects on the wrong pages/saving them and retrieving them on a page that needs them? (IE Should I only save the data I need to create objects on the page itself? (which seems like alot of overhead for the the same thing(?)).
Thanks in advance.
EDIT
I have an option page which creates an Object lets call it MyApi. I create a new MyApi and store it in chrome.storage.local . When a user has some text selected and clicks on the context menu I open a new page(selectedText.html) which shows the selected text and some API calls are made, which are mostly ajax requests. The moment I get the object from storage in selectedText.html and make any request with MyApi I see no logs in the network tab of the ajax requests, neither any console logs. But with my options page open I see everything in there.
EDIT2
save : function()
{
var obj = {'api':this.data};
chrome.storage.local.set(obj,function() { if(chrome.runtime.lastError) console.warn(chrome.runtime.lastError); });
}
This is in the background script.
You could achieve what you want this way:
Define your object/function/whatever in the background page.
Use chrome.runtime.getBackgroundPage() to get a hold on the background pages window object.
Execute the desired method, passing as argument an object of the local context. (Of course you have to modify the function to accept and make use of such an argument.)
Example:
In background.js:
function myFunc(winObj, msg) {
winObj.console.log(msg);
}
In otherPage.js:
chrome.runtime.getBackgroundPage(function(bgPage) {
bgPage.myFunc(window, "This will be logged in 'otherPage.html' !");
});
It is not the cleanest solution, but it might work...

Categories

Resources