Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON load function reads keys from other programs

EDIT: after some comments, i realize that i need to prefix my JSON keys better. I'm adding a bounty because learning this is important to me.

I am making a form and i save it to JSON. Then I made a function to display the form data on a table below it. The problem is that when the page loads, it loads data from another program I made that has a different key. In fact, it loads all keys in local Storage from anything. It will display the right data, but the incorrect data is displayed as undefined.

Here is the function that calls the data.

getData: function () {
        var ORMcount = localStorage.length, i = 0;
        if (ORMcount > 0) {
            var renderData = "<table>";
            renderData += "<tr><td>ORM Matrix</td></tr><br /><tr><th>Plan</th><th>Reward</th><th>Risks</th><th></th></tr>";
            for (i = 0; i < ORMcount; i += 1) {
                var key = localStorage.key(i); //Get Key 
                var ORM = localStorage.getItem(key); //Get Data
                try{
                   var data = JSON.parse(ORM); //Parse Data
                }
                catch(err) {
                  continue;
                }
                renderData += "<td>"+ data.Plan + "</td>";
                renderData += "<td>" + data.Reward + "</td>";
                renderData += "<td>" + data.Risk + "</td>";
                renderData += "<td class='xData' data-id='xData' data-index='"+key+"'>" + "x" + "</td></tr>";
                //set a data-id and data-index to this element, we need them to select the correct information.
                renderData += "<tr><td>&nbsp;</td></tr>"
            }
            renderData += "</table>";
            dvcontainer.innerHTML = renderData;


            Array.prototype.map.call(document.querySelectorAll("td[data-id='xData']"), function(element){
                  element.addEventListener("click", deleteRow, false); //attach a click handler to all delete buttons
            } );
        }
    }

If anyone can assist me in what i am doing wrong i would greatly appreciate it.

like image 456
MrEhawk82 Avatar asked Nov 01 '22 01:11

MrEhawk82


1 Answers

it looks like you have several applications/websites running from the same origin. local-storage uses a same-origin-policy, meaning all your scripts from one origin will access the same data.

Data placed in local storage is per origin (the combination of protocol, hostname, and port number as defined in the same origin policy) (the data is available to all scripts loaded from pages from the same origin that previously stored the data) and persists after the browser is closed.

from Wikipedia: Web storage

because your different application scripts share one local-storage, they have to save the data in a way that won't conflict with each other.

Option A. Use one local-storage key per application/website

this option would be the recommended way. the MDN: DOM Storage Guide says:

Keep in mind that everything you store in any of the storages described in this page is converted to string using its .toString method before being stored. So trying to store a common object will result in string "[object Object]" to be stored instead of the object or its JSON representation. Using native JSON parsing and serialization methods provided by the browser is a good and common way for storing objects in string format.

use one json array for all the rows and store it under one key in local-storage. to append rows, parse the json, append the data to the array, and save it back as a string into local-storage. this way your application will just use one key in local-storage, which should be unique to your app.

the json should look similar to this:

[
    {Plan: 1, Reward: 1},
    {Plan: 2, Reward: 2},
    {Plan: 3, Reward: 3},
]

to append rows do:

var dataStr = localStorage.getItem('APPNAME-DATA');
var data = JSON.parse(dataStr);

data.push({Plan: 4, Reward: 4});

dataStr = JSON.stringify(data);
localStorage.setItem('APPNAME-DATA', dataStr);

i see you use the key name for the data-index attribute of the table cell. as there is no key names with this solution, store the key-name in the object as well. for example: data.push({Key: 'keyname', Plan: 4, Reward: 4});. Ideally use another name, with more meaning than Key.

Option B. Use a prefix on the local storage keys

name the keys APPNAME-KEYNAME. later when you iterate over the keys, check if the key-name starts with APPNAME-. if not continue to the next item.

...
for (i = 0; i < ORMcount; i += 1) {
    var key = localStorage.key(i); //Get Key 

    if ( key.indexOf('APPNAME-') !== 0 ) {
        continue;
    }
...
like image 133
dreamlab Avatar answered Nov 15 '22 06:11

dreamlab