This question already has an answer here:
Store an array with chrome.storage.local
(1 answer)
Closed 7 years ago.
So I'm in a bit of a dillema right now. I can't seem to be able to add an Array in chrome.storage and later retrieving it. Here's the code I have right now:
function() {
chrome.storage.sync.get({ObjectName: []}, function (result) {
var ObjectName = result.ObjectName;
ObjectName.push({ArrayName: document.getElementById("field")});
});
Now to retrieve it and display it:
chrome.storage.sync.get({ArrayName: function(value) {
for(i=0; i<value.length; i++) {
document.write(value)
};
The error I am getting, which might be as simple as a syntax issue, amounts to:
Error: Invocation of form get(object) doesn't match definition get(optional string or array or object keys, function callback)
You have to use set method to set values to chrome.storage
Here's an example of how to do it
To store an array to chrome storage using set
var testArray=["test", "teste", "testes"];
chrome.storage.sync.set({
list:testArray
}, function() {
console.log("added to list");
});
To get the arrayValue using get and modify if by calling updatemethod
chrome.storage.sync.get({
list:[]; //put defaultvalues if any
},
function(data) {
console.log(data.list);
update(data.list); //storing the storage value in a variable and passing to update function
}
);
function update(array)
{
array.push("testAdd");
//then call the set to update with modified value
chrome.storage.sync.set({
list:array
}, function() {
console.log("added to list with new values");
});
}
Related
This question already has answers here:
Increment counter with Cloud Functions for Firebase
(3 answers)
Closed 3 years ago.
I am trying to update my map value with set function on a document but can't figure out how to update a specific map value.
In my firestore db there is a field called 'stats' and it is a map, inside of stats there is a key:value (likes_count: total), I want to update the total value for likes_count on my document, looks something like this:
stats: {
likes_count: 8
}
I want to update that value in the map with a cloud function trigger.
With regular fields I can easily set the value but not sure how to update a specific value in a map but here is my code for the function:
exports.userReceivedLikeTrigger = functions.firestore
.document(ENVIRONMENT_PATH + 'user_likes/{userLikeId}')
.onCreate((change, context) => {
const data = change.data();
return database.doc(ENVIRONMENT_PATH + "users/" + data.postOwnerRef)
.get()
.then(snapshot => {
if (snapshot.exists) {
let count = snapshot.data().stats.receivedLikes;
if (!count) {
count = 0;
}
// Then return a promise of a set operation to update the count
return database.doc(snapshot.ref.path).set({
// BREAKS HERE with stats.likesCount
stats.likesCount: count + 1
}, , {merge: true});
} else {
console.log("User is null");
return null
}
});
});
What is the error log?
Its a theory but with .set() its trying to make a new document (idk how merge:true works on this), but it can't make a value for stats.likesCount if there is no field stats already.
You can try to change .set() to .update() operation, it will do.
But its also not recommended to increment value with such a way. You better use
return db.doc(${path}).update({
stats.likesCount: admin.firestore.FieldValue.increment(1)
});
Because if there are multiple functions triggered, it can fail easily write incorrent data in likesCount field, but FieldValue.increment(1) works as a transaction so its safe to use in this case.
I have lots of packets that come through to my javascript via web sockets, each of these packets have a packet id, I want to create some sort of array or object that assigns each packet id a function to call, which would handle that packet.
I also want to include the 'packetData' parameter to all functions that are called, so it can get the other parts of data inside the function in order to handle the packet appropriately.
Heres what I have so far...
I listen for a message on WebSockets...
socket.onmessage = function (e) {
onPacket(JSON.parse(e.data));
};
Then I pass it to this function, I send my data in JSON format so I parse it to a key value object, then pass it to this function...
function onPacket(packetData) {
const packetId = packetData['packet_id'];
// TODO: Call the function...
}
The part I am stuck with is how do I create the array or keyvalue object to call the function? I store all my functions in a seperate file called "packet_events.js"
I did have a go at doing it myself (the object key value) but I was told it isn't valid JS, I'm stuck and sort of need some help, can anyone help?
My attempt:
var incomingHeaders = {
1: packetOne(),
};
If I still haven't made it clear, I want something like this, but with an array to save me constantly writing if statements..
function onPacket(packetData) {
const packetId = packetData['packet_id'];
if (packetId == 1) {
packetOne(packetData);
}
if (packetId == 2) {
packetTwo(packetData);
}
if (packetId == 3) {
packetThree(packetData);
}
}
Use object instead of arrays and create maping of ids into functions e.g.
var idToFunction = {
0: packetOne,
1: packetTwo,
2: packetThree
}
then inside onPacket your retrievied function based on id and executes it
function onPacket(packetData) {
const packetId = packetData['packet_id'];
var processPacket = idToFunction[packetId];
if (processPacket) {
processPacket(packetData);
}
else {
throw new Error("Invalid packed id: "+packetId);
}
}
Step 1: Create a function object that holds mapping from your packedId to your function.
Step 2: Iterate over the packets array to call the respective function.
Follow the snippet:
function packetOne() {
console.log('one')
}
function packetTwo() {
console.log('two')
}
let functionObject = {
1: packetOne,
2: packetTwo,
}
let packets = [
{ packetId: 1},
{ packetId: 2}
]
packets.forEach(function(packet){
functionObject[packet.packetId]()
})
I'm using Parse.com as my backend and after Query how can I fill an array with all the data inside the Parse object? how can I avoid re-mapping? example:
$scope.addContList = contacts.map(function(obj) { // re-map!!!!
return {name: obj.get("name")}; // mapping object using obj.get()
});
I'm mapping my Parse object's properties one by one: name: obj.get("name"), etc. is there a better way?
$scope.addContList = [];
var ActivityContact = Parse.Object.extend("ActivityContact2");
var query = new Parse.Query(ActivityContact);
query.equalTo("activityId", $scope.objId);
query.find({
success: function(contacts) {
console.log("Successfully retrieved " + contacts.length + " contact.");
$scope.$apply(function() {
/*$scope.addContList = contacts.map(function(obj) {
return {name: obj.get("name")}; // mapping object using obj.get()
});*/
for (var i = 0; i < contacts.length; i++) {
$scope.addContList.push(contacts.ALL_PROPERTIES); // contacts.ALL_PROPERTIES does not exist, I'm looking a way to do that and avoid mapping?
}
});
console.log("--->>>"+JSON.stringify($scope.addContList, null, 4));
},
error: function(object, error) {
// The object was not retrieved successfully.
// error is a Parse.Error with an error code and message.
}
});
Should I use Underscore library, is that the only way to go?
I have seen some ppl using PFQuery but I don't know what is that, is PFQuery better for this?
Thanks!
The other answers are correct, but I think it's unnecessary to launch a digest cycle every time you add an item from contacts to $scope.addContList. Something like this should be sufficient:
query.find({
success: function (contacts) {
$scope.apply(function () {
// 1) shallow-copy the list of contacts...
// (this is essentially what you are trying to do now)
$scope.addContList = contacts.slice();
// or 2) just assign the reference directly
$scope.addContList = contacts;
// or 3) transform the Parse.Object instances into
// plain JavaScript objects
$scope.addContList = contacts.map(function (c) {
return c.toJSON();
});
});
},
error: function (object, error) {
// The object was not retrieved successfully.
// error is a Parse.Error with an error code and message.
}
});
Options 1) and 2) will correspond to a template similar to
<div ng-repeat="cont in addContList">{{ cont.get('name') }}</div>
while option 3) can be used like
<div ng-repeat="cont in addContList">{{ cont.name }}</div>
If you change
$scope.addContList = contacts[i];
to:
$scope.addContList.push(contacts[i]);
you should be good to go. Your previous code was re-assigning addContList to be each element in the contacts array, instead of adding the element to it. So at the end of your for loop, $scope.addContList would just be the last contact in your contacts array.
Change:
$scope.addContList = contacts[i];
to
$scope.addContList.push(contacts[i]);
Is it possible to include related field on save i.e.
save(null, {
success: function(updatedObject) {
// Is there a way to include another field which is an array of pointers either here or before save()?
},
error: function() {
...
}
});
Only when you query for an item can you get included objects, by using the include method.
var query = new Parse.Query('myClass');
query.include('arrayOfPointersColumn');
query.first().then(function(result) {
// you can access the full parse objects inside the result object.
var otherObjects = result.get('arrayOfPointersColumn');
console.log(otherObjects);
});
I'm trying to make a Chrome extension. For that extension, I need some info that is dynamically created, but I want that data to be added even later on (on a different page).
This is some sort of data that i want to be always accessible (when the plugin runs):
var villages = new Array();
villages[0][0] = "village1";
villages[0][1] = "1325848";
villages[1][0] = "village2";
villages[1][1] = "8744351";
villages[2][0] = "village3";
villages[2][1] = "8952187";
As you can see, the array is multi-dimensional. This because I want to store the names [0] and the village id 1 together.
Does anybody knows a good way of handling this problem?
I've looked at this: jQuery Cookie
But don't know if that is a proper way of handling the problem.
Alternatively do I have to create some kind of XML file that will contain all the values?
UPDATE:
This is a skeleton example, if you want to store just village.id and village.name, just change the default data, that still works.
I have changed all code for you, you will see how to iterate array and get villages data below code.
At first I should say that It's really bad practice to save data in a multidimensional array.
You should use object, it makes your data tidy, than you can manipulate it easily.
Here is an example object for your situation,
var village = {
id: "1325848",
name : "village1"
};
console.log(village.id); //1325848
console.log(village.name); //village1
This was a basic get started example.
Here is the solution for your problem with localstorage and javascript object.
var ExtensionDataName = "myfirstextensiondata";
var ExtensionData = {
dataVersion: 3, //if you want to set a new default data, you must update "dataVersion".
villages: []
};
//default data
ExtensionData.villages.push(
{id: "1325848", name: "village1"},
{id: "8744351", name: "village2"},
{id: "8952187", name: "village3"}
);
function DB_setValue(name, value, callback) {
var obj = {};
obj[name] = value;
console.log("Data Saved!");
chrome.storage.local.set(obj, function() {
if(callback) callback();
});
}
function DB_load(callback) {
chrome.storage.local.get(ExtensionDataName, function(r) {
if (isEmpty(r[ExtensionDataName])) {
DB_setValue(ExtensionDataName, ExtensionData, callback);
} else if (r[ExtensionDataName].dataVersion != ExtensionData.dataVersion) {
DB_setValue(ExtensionDataName, ExtensionData, callback);
} else {
ExtensionData = r[ExtensionDataName];
callback();
}
});
}
function DB_save(callback) {
DB_setValue(ExtensionDataName, ExtensionData, function() {
if(callback) callback();
});
}
function DB_clear(callback) {
chrome.storage.local.remove(ExtensionDataName, function() {
if(callback) callback();
});
}
function isEmpty(obj) {
for(var prop in obj) {
if(obj.hasOwnProperty(prop))
return false;
}
return true;
}
DB_load(function() {
//YOUR MAIN CODE WILL BE HERE
console.log(ExtensionData);
console.log(ExtensionData.villages); //array of villages
console.log(ExtensionData.villages[0]); //first village object
console.log(ExtensionData.villages[0].id); //first village id
console.log(ExtensionData.villages[0].name); //first village name
//HOW TO ITERATE VILLAGES
for (var i = 0; i < ExtensionData.villages.length; i++) {
console.log(ExtensionData.villages[i].id); //village id
console.log(ExtensionData.villages[i].name); //village name
}
});
QUESTIONS:
Does the ExtensionDataName to be the same? or can i change that?
ExtensionDataName is used as a name when your data is saved to localstorage, it's just a name of your data collection. Therefore of course you can change it, do what you want, it's up to you.
what is the goal that you achief when you change the number of this line:
dataVersion: 3, //if you want to set a new default data, you must update "dataVersion"?
At the first time when user run this extension there is no data in the localstorage. So default village list is used,
In my example default village list is,
[
{id: "1325848", name: "village1"},
{id: "8744351", name: "village2"},
{id: "8952187", name: "village3"}
]
this default list is saved to localstorage. After than when extension runs again(not first time), the default list is not important anymore, because there is a village list stored in localstorage, so it loads village list from localstorage.
For example if you want to add a new village during the runtime of extension you can do it like this,
ExtensionData.villages.push({id: "1215555", name: "village4"});
DB_save();
So what is the goal of dataVersion?
If you look DB_load() function, it's used there. It checks whether dataVersion is still same, If it's not same, It decides that
"There is a updated default data so I should clear localstorage and reload new data to localstorage"
So If you don't change this lines,
ExtensionData.villages.push(
{id: "1325848", name: "village1"},
{id: "8744351", name: "village2"},
{id: "8952187", name: "village3"}
);
Than you won't change dataVersion