JS, issue with keeping array data in sessionStorage - javascript

Here is the problematic code:
let newFriend = event.target.id;
let friends;
if (sessionStorage.getItem('friends') === null || sessionStorage.getItem('friends') === undefined || sessionStorage.getItem('friends') === '') {
console.log('DEV_NO FRIENDS!sessionStorage[\'friends\']: ' + sessionStorage.getItem('friends'));
friends = [newFriend];
} else {
let currentFriends = sessionStorage.getItem('friends').split(',');
console.log(currentFriends.length);
// let currentFriends = JSON.parse(sessionStorage.getItem('friends'));
console.log('DEV_sessionStorage friends: ' + currentFriends);
console.log('DEV_inArray condition: ' + $.inArray(newFriend, currentFriends));
if (!($.inArray(newFriend, currentFriends) !== -1)) {
console.log('DEV_if not in array!');
friends = currentFriends.push(newFriend);
console.log('DEV_friends in if: ' + friends);
}
}
let data = {friends: friends};
It is hooked on image tag. The sessionStorage fills on successful login like so:
if (response['friends'] !== undefined) {
sessionStorage.setItem('friends', response['friends']);
} else {
sessionStorage.removeItem('friends');
}
Or is updated like so, if new friend is added:
ajax(url, 'GET', 'none', 'Kinvey', function(response) {
sessionStorage.setItem('friends', response['friends']);
});
The idea is: a user can add friends to his friends list. The friend is 'PUT' into my app's back-end, inside a column called 'friends'. Then sessionStorage is updated to store the new friend. To my knowledge sessionStorage supports only strings, so I thought lets store the friends as string, separated by ",". Then I would pick that up ('currentFriends') and split that string into array. Then push the next item and send the data back to the server, then update sessionStorage. But I simply cannot do it - I've been trying for over 3 hours now. As you can see with the numerous console.log()s, for some reason I cannot process my data accordingly and I have no idea what am I doing wrong. Sorry for the long post, but I'm really stuck in here..
Bottom line: as #dfasoro kindly explained - when working with REST one should always make sure he keeps his data in JSON strings. My second problem was that array.push() returns integer (length of array) instead of new array.

I hope this will help you, I have helped you refactor your code and removed unneccesaries, I hope the inline comments help you as well.
IMAGE HOOK CODE
let newFriend = event.target.id;
let friends = [];
if (sessionStorage.getItem('friends')) {
try {
//this will throw an error if invalid array json is in friends sessionStorage
friends = JSON.parse(sessionStorage.getItem('friends'));
}
catch (e) { }
}
//is friend in the array?
//if not add and store back into sessionStorage
if (friends.indexOf(newFriend) == -1) {
friends.push(newFriend);
sessionStorage.setItem('friends', JSON.stringify(friends));
}
let data = {friends: friends};
//continue with your image hook code
LOGIN CODE
//login code
if (response['friends']) {
sessionStorage.setItem('friends', JSON.stringify(response['friends']));
} else {
sessionStorage.removeItem('friends');
}
PUT CODE
//update PUT code
ajax(url, 'GET', 'none', 'Kinvey', function(response) {
sessionStorage.setItem('friends', JSON.stringify(response['friends']));
});
You basically store the data as JSON string and retrieve as JSON object. You also don't need the null, undefined, empty test etc. You are basically trying to test for a falsy value.
I also really hope that your response object is a standard JSON object mapped to a friend array and not a comma separated list of friends e.g.
{"friends": [4, 5, 3, 2]} and not `{"friends": "4, 5, 3, 2"}"

The above works perfect as sessionStorage only uses a key value pair.
Though I also use sessionJS to get/set/delete data to/from sessionStorage
maybe this will also help you.

Related

Parsing strings from local storage with vanilla JavaScript [duplicate]

This is my code. I am trying since a couple of days to create an Array of Objects, which I will then store in Local Storage. Here is the problem, I need to first Get the existing value from Local Storage.
I then need to add the new data object to the existing array. I then convert it into JSON so that I can store it back in the local storage.
onRegisterSubmit(){
const user = {
a: this.a,
b: this.b,
c: this.c,
id: Date.now()
}
var abc = [];
var get = JSON.parse(localStorage.getItem('user'));
abc = [get];
abc.push(user);
localStorage.setItem('user', JSON.stringify(abc));
console.log(JSON.stringify(abc));
console.log(get);
}
I want the JSON to be an array of objects like this,
[{"hour":1,"minute":21,"ampm":"PM","repeatDays":[],"message":"","todayOrTomorrow":"Tomorrow","isRepeatMode":false,"isEnabled":false,"id":"1493797882440"},{"hour":1,"minute":24,"ampm":"PM","repeatDays":[],"message":"","todayOrTomorrow":"Tomorrow","isRepeatMode":false,"isEnabled":false,"id":"1493797896257"},{"hour":6,"minute":14,"ampm":"PM","repeatDays":[],"message":"","todayOrTomorrow":"Tomorrow","isRepeatMode":false,"isEnabled":false,"id":"1493815470408"}]
This is my JSON.
[[[[[[[{"id":1493820594019},{"id":1493820606448}],{"id":1493820609111}],{"id":1493820610150}],{"id":1493820610553}],{"id":1493820610827}],{"id":1493820611015}],{"id":1493820612018}]
I've been trying for several days and any help will be greatly appreciated.
The issues with that code are:
You're wrapping the result you get in an array, but in theory, you want to already have an array.
You're storing user, not get or abc. (You removed that with an edit.)
To store the array, do what you're doing:
localStorage.setItem("users", JSON.stringify(users));
To get the array:
users = JSON.parse(localStorage.getItem("users") || "[]");
Note how that provides a default (empty array) if getItem returns null because we've never stored our users there.
To add a user to the array:
users.push({id: 1, foo: "bar"});
Example (live on jsFiddle [Stack Snippets don't allow local storage]):
(function() { // Scoping function to avoid creating globals
// Loading
var users = JSON.parse(localStorage.getItem("users") || "[]");
console.log("# of users: " + users.length);
users.forEach(function(user, index) {
console.log("[" + index + "]: " + user.id);
});
// Modifying
var user = {
id: Math.floor(Math.random() * 1000000)
};
users.push(user);
console.log("Added user #" + user.id);
// Saving
localStorage.setItem("users", JSON.stringify(users));
})();
That shows you the list of current users in the console, adding one each time you refresh the page.
Try something like this:-
link https://jsfiddle.net/sureshraina/nLexkyfw/1/
var mydatas = new Array();
mydatas[0] = "data";
mydatas[1] = "data1";
mydatas[2] = "data2";
localStorage["mydatas"] = JSON.stringify(mydatas);
var datas = JSON.parse(localStorage["mydatas"]);
See this post.
You can't store Objects, you have to store a String. So the workaround is to stringify your Object before you store it (for example, you could use change it to a JSON object, store it, and read it again when needed).

Complex JSON obj and jQuery or Javascript map to specific key, value

I am banging my head trying to figure this out. And it should not be this hard. I am obviously missing a step.
I am pulling data from: openaq.org
The object I get back is based on a JSON object.
For now, I am using jQuery to parse the object and I am getting to the sub portion of the object that hold the specific parameter I want but I can't get to the specific key,value pair.
The object does not come back in the same order all the time. So when I tried to originally set up my call I did something like
obj.results.measurements[0].
Well since the obj can come back in an random order, I went back to find the key,value pair again and it was the wrong value, throwing my visual off.
That said, I have looked at use jQuery's find() on JSON object and for some reason can not get what I need from the object I am given by openaq.org.
One version of the object looks like this:
{"meta":{"name":"openaq-api","license":"CC BY 4.0d","website":"https://u50g7n0cbj.execute-api.us-east-1.amazonaws.com/","page":1,"limit":100,"found":1},"results":[{"location":"Metro Lofts","city":null,"country":"US","coordinates":{"latitude":39.731,"longitude":-104.9888},"measurements":[{"parameter":"pm10","value":49.9,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"},{"parameter":"pm1","value":24,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"},{"parameter":"um100","value":0,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"um025","value":0.28,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"um010","value":4.1,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"pm25","value":41.1,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"}]}]}
I am trying to get the "pm25" value.
The code I have tried is this:
function getAirQualityJson(){
$.ajax({
url: 'https://api.openaq.org/v2/latest?coordinates=39.73915,-104.9847',
type: 'GET',
dataType: "json"
// data: data ,
}).done(function(json){
console.log("the json is" + JSON.stringify(json));
console.log("the json internal is" + JSON.stringify(json.results));
var obj = json.results;
var pm25 = "";
//console.log(JSON.stringify(json.results.measurements[0]["parameter"]));
$.each(json.results[0], function(i,items){
//console.log("obj item:" + JSON.stringify(obj[0].measurements));
$.each(obj[0].measurements, function(y,things){
//console.log("each measurement:" + JSON.stringify(obj[0].measurements[0].value));//get each measurement
//pm 2.5
//Can come back in random order, get value from the key "pm25"
// pm25 = JSON.stringify(obj[0].measurements[2].value);
pm25 = JSON.stringify(obj[0].measurements[0].value);
console.log("pm25 is: " + pm25); // not right
});
});
//Trying Grep and map below too. Not working
jQuery.map(obj, function(objThing)
{ console.log("map it 1:" + JSON.stringify(objThing.measurements.parameter));
if(objThing.measurements.parameter === "pm25"){
// return objThing; // or return obj.name, whatever.
console.log("map it:" + objThing);
}else{
console.log("in else for pm25 map");
}
});
jQuery.grep(obj, function(otherObj) {
//return otherObj.parameter === "pm25";
console.log("Grep it" + otherObj.measurements.parameter === "pm25");
});
});
}
getAirQualityJson();
https://jsfiddle.net/7quL0asz/
The loop is running through I as you can see I tried [2] which was the original placement of the 'pm25' value but then it switched up it's spot to the 3rd or 4th spot, so it is unpredictable.
I tried jQuery Grep and Map but it came back undefined or false.
So my question is, how would I parse this to get the 'pm25' key,value. After that, I can get the rest if I need them.
Thank you in advance for all the help.
You can use array#find and optional chaining to do this,
because we are using optional chaining, undefined will be returned if a property is missing.
Demo:
let data = {"meta":{"name":"openaq-api","license":"CC BY 4.0d","website":"https://u50g7n0cbj.execute-api.us-east-1.amazonaws.com/","page":1,"limit":100,"found":1},"results":[{"location":"Metro Lofts","city":null,"country":"US","coordinates":{"latitude":39.731,"longitude":-104.9888},"measurements":[{"parameter":"pm10","value":49.9,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"},{"parameter":"pm1","value":24,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"},{"parameter":"um100","value":0,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"um025","value":0.28,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"um010","value":4.1,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"pm25","value":41.1,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"}]}]}
let found = data?.results?.[0]?.measurements?.find?.(
({ parameter }) => parameter === "pm25"
);
console.log(found);
You can iterate over measurements and find the object you need:
const data = '{"meta":{"name":"openaq-api","license":"CC BY 4.0d","website":"https://u50g7n0cbj.execute-api.us-east-1.amazonaws.com/","page":1,"limit":100,"found":1},"results":[{"location":"Metro Lofts","city":null,"country":"US","coordinates":{"latitude":39.731,"longitude":-104.9888},"measurements":[{"parameter":"pm10","value":49.9,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"},{"parameter":"pm1","value":24,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"},{"parameter":"um100","value":0,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"um025","value":0.28,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"um010","value":4.1,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"pm25","value":41.1,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"}]}]}';
const json = JSON.parse(data);
let value = null;
const measurements = json?.results?.[0]?.measurements ?? null;
if(measurements)
for (const item of measurements)
if (item.parameter === 'pm25') {
value = item.value;
break;
}
if (value) {
// here you can use the value
console.log(value);
}
else {
// here you should handle the case where 'pm25' is not found
}

Javascript - How to pull data from Google Firebase randomly?

I'd like all my Firebase content to load randomly every time you refresh, but I can't seem to get all my Firebase data into a dictionary where I can randomize them.
I have a global array and I'm trying to push my files in there and then iterate through them. But Javascript thinks the array is empty because the timing is off.
var randomStore = new Array;
function homeSetup() {
if(ref.toString() == featuredRef.toString()){
addFeaturedImages();
}
console.log('randomStore length is ' + randomStore.length);
}
function addFeaturedImages(){
featuredRef.on("child_added", function(snapshot) {
var doc = {
// 'name': snapshot.key, //name is the id
'artist': snapshot.val().artist,
'author': snapshot.val().author,
'projectTitle': snapshot.val().projectTitle,
'text': snapshot.val().text
};
randomStore.push(doc);
console.log('randomStore length HERE is ' + randomStore.length);
});
}
Considering how the code is typed, I would assume that the 'randomStore length HERE is' log would be typed first, but instead I get this:
randomStore length is 0
randomStore length HERE is 1
randomStore length HERE is 2
randomStore length HERE is 3
If I got my data into a different array, then I could manipulate it to sort randomly and stuff like that, but I can't seem to get it in there properly.
You mentioned the timing is off? What did you mean by that ?
Have you heard of Javascript Promise's ?
http://www.html5rocks.com/en/tutorials/es6/promises/
This post explains promises very good. Read this very carefully, because if you are working with firebase, you will be using promises on daily!
Instead of using featuredRef.on("child_added") use featuredRef.once('value'). This should get you the whole array at once. Attach a then listener where you continue with the work of homeSetup.
function homeSetup() {
var cb = function(randomStore) {
console.log('randomStore length is ' + randomStore.length);
//....
};
if(ref.toString() == featuredRef.toString()){
addFeaturedImages(cb);
} /* else if(...) {
addFooImages(cb)
}*/
}
function addFeaturedImages(cb){
featuredRef.once("value", function(snapshot) {
//TODO: transform elements of the array?
cb(snapshot.val());
});
}
Code untested, but I should get you started.

How can I delete specific rows in parse.com?

I have objects in Parse called "Post" and within that, I have columns called "title" and "content". I am trying to ask the user for an input value and save this as "remove". If the user's input value ("remove") matches a "title" value already saved in parse.com, I want to delete the entire row in parse, so that both the "title", "content" and everything else in the row is deleted. The deleting part is not working so I am wondering if my code is actually making it go through all the data saved in parse and find the one that matches the user's input and then delete it.
What am I doing incorrectly and what can I change to make it delete the entire row?
Thank you in advance.
function getPosts(){
var query = new Parse.Query(Post);
query.find({
success: function(results){
for(var i in results){
var title = results[i].get("title");
var content = results[i].get("content");
var remove = $("#post-remove").val();
console.log("Remove: "+remove);
console.log("MAC Address: " +title);
console.log("place: "+content);
if (title == remove)
{
window.alert("The MAC address matches.");
console.log(remove+" matches " + title+ " and is located in " +content);
var Post = Parse.Object.extend("Post");
var query = new Parse.Query(Post);
query.find("objectId", {
success: function(yourObj){
//console.log(yourObj);
//Post.destroy({}); //if title matches remove, delete the Post (title and content) (but it's not deleting it)
Post.remove("title");
Post.remove("content");
}
});
}
}
}
});
}
To clarify and add a bit to #JakeT's acceptable answer:
1) find objects to delete like this:
function postsMatching(title) {
var Post = Parse.Object.extend("Post");
var query = new Parse.Query(Post);
query.equalTo("title", title);
return query.find();
}
2) Delete an array of parse objects like this:
Parse.Object.destroyAll(posts);
3) Put the two ideas together (returning a promise to find then delete) like this:
var title = $("#post-remove").val();
postsMatching(title).then(function(posts) {
console.log("deleting " + JSON.stringify(posts));
Parse.Object.destroyAll(posts);
}, function(error) {
console.log("error " + JSON.stringify(error));
});
First of, you can use the Parse.Query.equalTo(key, value) method to filter for the Post/s you are looking for. That will render a lot of your logic unnecessary.
Additionally, since most parse calls are asynchronous, I would suggest learning about Parse Promises and using those instead of the call backs you're using.
Finally, you don't need a second nested query, since you already have the object you are trying to destroy. You just need to call destroy() on that object, and if you have some extra content you need to take care of deleting (i.e., your 'content' is a pointer to another object that is owned only by the Post you are deleting), you should set up a beforeDestroy() trigger for the Post object in your cloud code that will delete that pointer as well.

Loop through all Mongo collections and execute query

First of, I'm quite new to mongodb. Here's my question I've not been able to find a solution to.
Let's say I have 3 different collections.
mongos> show collections
collectionA
collectionB
collectionC
I want to create a script that iterates over all collections ind this database and find the last inserted timestamp in each of these collections. Here's what works inside mongos.
var last_element = db.collectionA.find().sort({_id:-1}).limit(1);
printjson(last_element.next()._id.getTimestamp());
ISODate("2014-08-28T06:45:47Z")
1. Problem (Iterate over all collections)
Is there any possibility to to sth. like.
var my_collections = show collections;
my_collections.forEach(function(current_collection){
print(current_collection);
});
Problem here, the assignment for my_collections does not work.
I get SyntaxError: Unexpected identifier. Do I need to quote the 'show' statement ? Is it even possible ?
2. Problem (storing collection in js var)
I can workaround Problem 1 by doing this:
var my_collections = ["collectionA", "collectionB", "collectionC"];
my_collections.forEach(function(current_collection){
var last_element = db.current_collection.find().sort({_id:-1}).limit(1);
print(current_collection);
printjson(last_element.next()._id.getTimestamp());
});
The last_element.next() produces the following error:
error hasNext: false at src/mongo/shell/query.js:124
It seems that last_element isn't saved correctly.
Any suggestions on what I'm doing wrong??
UPDATE
Neils answer lead me to this solution. In addition to his code I had to check if the function getTimestamp really exist. For some 'virtual' collections there seem to be no _id property.
db.getCollectionNames().forEach(function(collname) {
var last_element = db[collname].find().sort({_id:-1}).limit(1);
if(last_element.hasNext()){
var next = last_element.next();
if(next._id !== undefined && typeof next._id.getTimestamp == 'function'){
printjson(collname + " >> "+next._id.getTimestamp());
}else{
print(collname + " undefined!! (getTimestamp N/A)")
}
}
});
There is the db.getCollectionNames() helper method that does this for you. You can then implement your code:
db.getCollectionNames().forEach(function(collname) {
// find the last item in a collection
var last_element = db[collname].find().sort({_id:-1}).limit(1);
// check that it's not empty
if (last_element.hasNext()) {
// print its timestamp
printjson(last_element.next()._id.getTimestamp());
}
})
You probably also want a .hasNext() check in there to cater for possible empty collections.
Rename the collection name present in all the records using the following script:
db = db.getSiblingDB("admin");
dbs = db.runCommand({ "listDatabases": 1 }).databases;
dbs.forEach(function(database) {
db = db.getSiblingDB(database.name);
db.currentname.renameCollection("newname");
});

Categories