2

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.

Eliran Malka
  • 15,821
  • 6
  • 77
  • 100
greenfern
  • 29
  • 2
  • 1
    How are the items in localStorage set in the first place? Are you creating them yourself before your `for` loop, or do they already exist? You might be better off storing your array as one single item instead of storing each individual index as its own item. You can do this using JSON: http://stackoverflow.com/a/3357615/551093 – Christian Jul 19 '15 at 00:30
  • The first time I run the script, I set default values for each of the elements. The plan is to comment out that line after the first successful run, and from then on only change one element at a time. I've never gotten the whole thing working though, so I've never followed through with the plan. – greenfern Jul 19 '15 at 01:05
  • Storing the array as one item is no good, because each element is itself a complex string of a defined length. I'm actually fudging a two-dimensional array by using a one-dimensional array with multiple entries in each individual string. Or trying to anyway. Is the basic principle of storing/reading variable[i] even possible? – greenfern Jul 19 '15 at 01:09
  • I'm not sure what a _"complex string of a defined length"_ has to do with using `JSON.stringify()` to store it as one item, then using `JSON.parse()` to turn it back into an array. Nor do I understand why you'd need to fudge a two-dimensional array, rather than just using a two-dimensional array. Despite your detailed description, from an outsiders point of view, it's extremely difficult to figure out what you're actually trying to do (sorry). I think the best thing would be for you to create a jsFiddle with everything you have so far (including the HTML). That should help us to help you. – Christian Jul 19 '15 at 01:24
  • What I really want to do is store a 100 x 200 array. I read that you can't store 2D arrays, so I went for an array of 100 elements, each 200 characters long. Maybe this was unclear thinking. I don't understand, however, if simply calling something variable[i] during the set will allow me to recover variable[i] with a corresponding get. The 1 to 100 was easy to access, the 200 axis was a pain, but I could muck around with it using substr. There was at least clarity with one axis. Can you actually set variable[x][y] and later get variable[x][y] and expect the same data back? – greenfern Jul 19 '15 at 02:14
  • That _still_ doesn't explain why you can't store it as JSON. Anyway, where did you read that? Sure, you can't have a two-dimensional array in the traditional sense of `variable[x,y]`, but you can absolutely have an array of arrays (`variable[x][y]`), which is exactly the same. I don't know what you mean by _"expect the same data back"_. Variables don't change by themselves; if you set a variable to a specific value, then that value will be stored in that variable. Here's a demo of a 100x200 array: https://jsfiddle.net/qpuxxvfc/ – Christian Jul 19 '15 at 03:47
  • My problem was never with handling the data once it was existent within the current Tampermonkey pass, it was about storing that data in a way that wasn't wiped out with each new pass. I was trying to write a particular element into the stored space, and it wasn't working. jfriend00 pointed out that the way to think of it was to import the giant blob, modify it in a temporary space, and export the ENTIRE giant blob. Don't try to tinker with bits of the stored info, just load it all in, change it, and push it ALL back out. – greenfern Jul 20 '15 at 20:16

1 Answers1

6

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.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Pardon my supreme ignorance, but there is still a disconnect in my brain. I see how you're using push to add elements to a list. I could create my initial "array" this way. But how would I access and modify, say, the 10th thing on that list, and then insert it back into the proper place, so the whole thing stays the same size, but with a different 10th element? I am sure this is a matter of me looking at the problem from the wrong perspective, so I appreciate your patience. – greenfern Jul 19 '15 at 02:22
  • @greenfern - `currentData` is an array once you've loaded it and you access it like any other array. `var item = currentData[10];` or `currentData[3] = "foo";` It all depends upon what you want to do with the array, but arrays are usually accessed by numeric index. Objects are accessed by property name. – jfriend00 Jul 19 '15 at 02:33
  • I set up the initial values using push. And I changed a specific element using `currentData[x] = "newValue"` And during that run-through, all the data is good. But when I try to read it back in, on the next pass using `var currentData = JSON.parse(localStorage.getItem("currentData") || "[]");` the data is just not there. It's undefined. This is the same problem I've had all along. I've manipulated the data in numerous ways during the first pass, but I can never successfully recover the data on the next click. Does changing the value of currentData[x] change the stored value in the file? – greenfern Jul 19 '15 at 03:56
  • A-HA! I was forgetting the vital `localStorage.setItem("currentData", JSON.stringify(currentData));` step! The darn thing is working now! Thank you for your patience while I was banging my head against the wall. The jsFiddle made it clear to me. – greenfern Jul 19 '15 at 04:05
  • @greenfern - Any time you change the data, you have to resave it to LocalStorage (or save it at some other convenient time). The array is just a live array in your Javascript. It only gets saved to LocalStorage when you execute the line I have above that saves it to LocalStorage. You can't access an array directly that is in LocalStorage as LocalStorage just stores strings, not arrays. – jfriend00 Jul 19 '15 at 04:06