Store Array in Chrome Extension - javascript

I'm currently making a Chrome Extension, and I'm at the last stage of it, storing the users preferences.
I know Local Storage will store strings, and at this stage I'm getting awway with just using strings, but as the storage requirements get bigger, a 2 dimentional array is required. I've seen that Local Storage is not capable of storaing an array, but you can use JSON. I've never used JSON, and when looking at examples, I do not understand how to do so.
for (i=1;i<=localStorage["totalwebsites"];i++) {
// Get the title of the current item
var title = localStorage["websitetitle" + i];
// Create the new context menu item, and get its menuItemId to store in the right localStorage string
var menuItemId = chrome.contextMenus.create({parentId: ParentID, title: title, contexts:["selection"], onclick: searchFromContext});
// Store the created menu items menuItemId in the array so we know which item was chosen later on
websitesarray[menuItemId] = localStorage["websiteurl" + i];
}
As you can see, this gets very messy, very quick, when using strings. I was hoping for totalwebsites to become a count of the items in the array, and websitetitle and websiteurl to be in the 2 dimetional array.
I don't see how you would do this in JSON, or at least how this could be permanently stored in Chrome itself. I'm guessing you'd have to convert it back to Local Storage Strings at some point or something? I don't think I'm getting this.
Any help/pointers would be much appreciated, I can't find much :(

Don't worry, JSON is super easy! Assuming that your websites are stored in websitesarray:
// To load:
websitesarray = JSON.parse(localstorage.websites);
// To store:
localstorage.websites = JSON.stringify(websitesarray);
Make sure you have a sane way to handle the case where localstorage.websites isn't set yet, as JSON.parse will throw a fit if its input is empty.

Related

Most efficient way to link an object in one array with an object in another array

Beginner and self-taught coder here (always open to learning please correct me) and I'm making a web app through pretty much exclusively HTML CSS and Javascript (I don't really want to use PHP or hosting-side processing because I don't know much about web security and it makes me nervous about uploading data to my hosted site).
Very unsure about the most efficient way to do this so I'm going to try to describe it below and I'd really appreciate your input.
My main question: Is there a more efficient way to do this?
The app eventually will have a javascript canvas, where it will draw an object ('track') at a specific location. This object will then move to another location based off nested data in an array ('step') when the user moves to the next item in an array.
As of now, how I'm going about it is having:
storing the location values in the steps array
have an array of 'tracks' for what shape/color/etc will be drawn on the canvas
linking the two elements by an arbitrary ID that is in both 'steps array' and 'tracks' array
A visual representation of what this might look like
steps[stepNumber].movedTracksInStep[movedTracksInStepNumber] holds object:
{track ID,
X location,
y location}
separate array trackList
trackList[trackNumber] holds object:
{track ID,
shape,
color,
bunchastuff}
I choose to do it like this because I figured it would be better to store the location in the steps array, store the visual data in a separate array, so that way it's not repeating the same data every step.
My question:
Is there a more efficient way to do this, especially in terms of search functions? I'm a newbie so there very well might be something I am missing.
Currently, I just have to search through all of the ID tracks in the step and see if there is a match. I'm wondering if there is a more direct way to link the two together than having to search each time.
I've thought about perhaps having all the data for the visual representation in the first step and then not having to repeat it (though I'm not quite sure how that would work), or having the numbers of arrays match up (but this would change if the user deletes a track or adds a track).
Thank you! Let me know if you need me to explain more.
Objects in JS are stored and copied "by reference", so if you assign value of one object to another, value will not be copied, but reference link will be created. Below is the example close to your code, check inline comments. And you can adopt this behavior to your task:
// Your tracks information
const trackList = {
1: {
shape: "rect",
color: "green",
bunchastuff: "foo"
}
};
// Your steps data
const steps = {
1: {
1: {
// Here we create reference to track 1 in
// trackList object data, without copying it
track: trackList[1],
x: 100,
y: 50
}
}
};
// Print step info
console.log("before track info edit:", steps[1][1].track);
// Update data in track 1
trackList[1].shape = "round";
// Print step info again and we'll
// see, that it also updated
console.log("after track info edit:", steps[1][1].track);
You can read more about object references here: https://javascript.info/object-copy

javascript - Set vs Map - which is faster?

Set and Map both are newer data types in es6 and for certain situations both can be used.
e.g - if i want to store all unique elements, i can use Set as well as Map with true as value.
const data: string[] ;
// console.log('data', data[0])
const set = new Set();
const map = new Map<string, boolean>();
data.forEach((item) => {
map.set(item, true);
});
data.forEach((item) => {
set.add(item);
});
Both works, but i was wondering which one is faster ?
Update 1
I am looking for which of the data structure is faster in case of storing data.
checking if value exist using -
map.has(<value>)
set.has(<value>)
deleting values
Also i can understand true is redundant and not used anywhere, but i am just trying to show how map and set can be used alternatively.
What matters is speed.
In the most basic sense:
Maps are for holding key-value pairs
Sets are for holding values
The true in your map is completely redundant ... if a key exists, that automatically implies, that it is true/exists - so you will never ever need to use the value of the key-value pair in the map (so why use the map at all, if you're never gonna make use of what it is actually for? - to me that sounds like a set/array with extra steps)
If you just want to store values use an array or set. - Which of the two depends on what you are trying to do.
The question of "which is faster" can't really be answered properly, because it largely depends on what you are trying to do with the stored values. (What you are trying to do also determines what data structure to use)
So choose whatever data structure you think fits your needs best, and when you run into a problem that another would fix, you can always change it later/convert from one into another.
And the more you use them and the more you see what they can and can not do, the better you'll get at determining which to use from the start (for a given problem)

Dynamic Array in Local Session

I'm having issues with the logic of using Local session variables. So I understand that HTML5 allows you to set and get these local storage variables.
I've read through this post: adding objects to array in localStorage
and understood that by using SetItem, you will rewrite the variable that you have set and thus for a dynamic array, you will need to get the variable first before pushing a new value.
So the problem I'm having, and I dont't even know if it's possible, is that I want to have, for example, a index.html page which accepts a user input and adds it into an array that needs to be persistent. When the user reloads the same page, the previous input will still be in the same array. From what I read from the post mentioned previously, you will rewrite the variable if you use SetItem. However, if I don't use setItem, how will I be able to specify that the array is to be a local Storage variable... I'm sorry if I confused anyone... because I am quite confused myself. Thanks in advance.
All of your assumptions are correct. You can only write to localStorage using setItem, and when setItem is called, you overwrite whatever value exist there. Therefore, the only way to add an item to an array in localStorage is to get the array from localStorage, manipulate it and then put it back with the new items.
// Check if we already have an array in local storage.
var x = localStorage.getItem("myArray");
// If not, create the array.
if (x === null) x = [];
// If so, decode the array.
else x = JSON.parse(x);
// Add our new item.
x.push("value 1");
// Encode the array.
x = JSON.stringify(x);
// Add back to LocalStorage.
localStorage.setItem("myArray", x);
This could done by the following approach:
var myInput = document.getElementById("myInput").value; // user data
var myList = JSON.parse(localStorage.getItem("myList")); // retrieve the list from LS
if(!Array.isArray(myList)) { // if LS list is not ok, instantiate new array
myList = [];
}
myList.push(myInput); // append user data to the list
localStorage.setItem("myList", JSON.stringify(myList)); // save the list back to LS

Better to store array in localstorage or many variables?

Take for example a case where I have thousands of students.
So I'd have an array of objects.
students = [
{ "name":"mickey", "id","1" },
{ "name":"donald", "id","2" }
{ "name":"goofy", "id","3" }
...
];
The way I currently save this into my localstorage is:
localStorage.setItem('students', JSON.stringify(students));
And the way I retrieve this from the localstorage is:
var data = localStorage.getItem('students');
students = JSON.parse(data);
Now, whenever I make a change to a single student, I must save ALL the
students to the localStorage.
students[0].name = "newname";
localStorage.setItem('students', JSON.stringify(students));
I was wondering if it'd be better instead of keeping an array, to maybe have
thousands of variables
localStorage.setItem('student1', JSON.stringify(students[0]));
localStorage.setItem('student2', JSON.stringify(students[1]));
localStorage.setItem('student3', JSON.stringify(students[2]));
...
That way a student can get saved individually without saving the rest?
I'll potentially have many "students".. Thousands. So which way is better,
array or many variables inside the localstorage?
Note: I know I should probably be using IndexedDB, but I need to use LocalStorage for now. Thanks
For your particular case it would probably be easier to store the students in one localStorage key and using JSON parse to reconstruct your object, add to it, then stringifying it again and it would be easier than splitting it up by each student to different keys.
If you don't have so many data layers that you really need a real local database like IndexedDB, a single key and a JSON string value is probably OK for your case.
There is limitation for the size of local storage and older browsers won't support it.
It is better to store in an array for couple reasons:
Can use loops to process them
No JSON needed
Always growable

storing and retrieving 100-element array

I am using Greasemonkey/Tampermonkey to visit pages and make a change to a 100-element table based on what's on the current page.
Short term storage and array manipulation works fine, but I want to store the data permanently. I have tried GM_getValue/GM_setValue, GM_SuperValue, localStorage, and indexedDB, but I am clearly missing something fundamental.
Nothing seems to allow me to write the array into the permanent storage and then read it back into a variable where I can access each element, such that variablename[32] is actually the 32nd element in the table (Well, 33rd if you start counting at zero, which I do).
I need access to the entire 100-element table while the script is running, because I need to output some or all of it on the page itself. In the most basic case, I have a for loop which goes from 0 to 99, printing out the value of variablename[i] each time.
I have no predisposition to any method, I just want the frickin' thing to work in a Greasemonkey/Tampermonkey script.
Towards the top of the script I have this:
for (var i = 0; i <= 99; i++) {
currentData[i] = localStorage.getItem(currentData[i]);
}
The purpose of the above section is to read the 100 entries into the currentData array. That doesn't actually work for me now, probably because I'm not storing things properly in the first place.
In the middle, after modifying one of the elements, I want to replace it by doing this:
localStorage.setItem(
currentData[specificElementToChange], differentStuff);
The purpose of the above is to alter one of the 100 lines of data and store it permanently, so the next time the code at the top is read, it will pull out all 100 entries, with a single element changed by the above line.
That's the general principle.
I can't tell if what I'm doing isn't working because of some security issue with Firefox/Chrome or if what I want to do (permanently storing an array where each time I access a given page, one element changes) is impossible.
It's important that I access the array using the variable[element] format, but beyond that, any way I can store this data and retrieve it simply is fine with me.
I think you're going about this wrong. LocalStorage stores strings so the simplest way to store an array in LocalStorage is to stringify it into JSON and store the JSON. Then, when reading it back, you parse the JSON back into an array.
So, to read it in, you do this:
var currentData = JSON.parse(localStorage.getItem("currentData") || "[]");
To save your data, you do this:
localStorage.setItem("currentData", JSON.stringify(currentData));
Working demo: http://jsfiddle.net/jfriend00/6g5s6k1L/
When doing it this way, currentData is a variable that contains a normal array (after you've read in the data from LocalStorage). You can add items to it with .push(), read items with a numeric index such as:
var lastItem = currentData[currentData.length - 1];
Or, change an item in the array with:
currentData[0] = "newValue";
Of course, it's just a normal array, so you can use any array methods on it.

Categories