Chrome extension and local storage - javascript

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

Related

javascript How to check the same data is available for the second time

I have a tricky requirement which im not able to fix.
I have a button and if i click on that button, Im getting below data from a REST web service ..
{
"results": [{
"Reqdate": "\/Date(1520899200000)\/",
"Tooltip": "13.03.2018 Blood Donation Approved ",
"Legendid": "GROUP_LEVEL1"
},{
"Reqdate": "\/Date(1523836800000)\/",
"Tooltip": "16.04.2018 Privilege Leave Sent ",
"Legendid": "BADVALUE_LIGHT",
},{
"Reqdate": "\/Date(1524528000000)\/",
"Tooltip": "24.04.2018 Privilege Leave Sent ",
"Legendid": "BADVALUE_LIGHT",
}]
}
If im getting the above data for the first time. Im going to display one section. Now again if i click on the same button, If i get the same data in the service then i have to hide the section. But im not able to check the same data for the second time.
Im trying to fix this issue by storing the data in a variable like below..
var firstTimeResults = data.results;
Now im not able to check if the same data is coming for the second time. Actually im not able to produce the sample code too. Im sorry for that
Can someone please help me to fix this issue.
I am not fully understand your problem but I think you can store your data as JSON and check if the same data is return from the second time onwards?
Code example
// Variable declaration
var firstTimeResults = null;
// When data return
var dataJson = JSON.stringify(data.results);
if (firstTimeResults === null) {
firstTimeResults = dataJson;
}
else {
// check to see if the data is the same as the firstTimeResults
var isSame = firstTimeResults === dataJson;
if (isSame) {
// Same
} else {
// Not the same
}
}
You can simply try with Lodash library.
It makes JavaScript easier to work with arrays, numbers, objects, strings, etc.
https://lodash.com/
var firstResult = null;
var secondResult;
var showSection;
function getData() {
// here goes your API request to get the data
};
function onButtonClick() {
this.getData().then(function(value) {
if !(firstResult) {
firstResult = value;
showSection = true;
return;
}
secondResult = value;
if (_.isEqual(firstResult, secondResult)) {
showSection = false;
}
})
};
Hope this will be helpful to you!

Storing data with JavaScript in the browser

I am trying to create a simple app that allows users to select the dev who they are pairing with on that day and then a set a timer so they switch.
Currently, I am storing all the information in Firebase, but that seems like overkill.
Is there a way I can store data in the browser with JavaScript, such as in a cookie? The info I would need to store would be a small object like so:
obj1 = { name: 'rob', pairName: 'chris', timeLeft: 15 }
Or does Firebase make more sense?
I need it to persist, so that if I refresh, it does not 'reset' the data.
I am not asking how to do it, just advice and the ideal path :)
try this! =)
var DB = function(){
this.Read = function(index){
if(this.Test()){
return JSON.parse(localStorage[index]).data;
}
},
this.Write = function(index, data){
localStorage[index] = JSON.stringify({data : data});
}
this.Test = function(){
return typeof localStorage == typeof {};
}
}
// example:
var x = new DB(); // new data base
x.Write('food', ['food','bar','google']); // write data
console.log(x.Read('food')); // get data!

LocalStorage strategy for user and message data

I am looking for a simple strategy to store user data, as well as messages. I was thinking of using different key values like some random token (Ynjk_nkjSNKJN) for users and some real ids (1,2,3) for messages.
Has anyone ever had that problem?
The reason is that I would like to keep localStorage always up to date with new messages from the server, but users should not be deleted during an update.
Thanks
You can handle "tables" in localStorage this way:
//columns should be an array of column literals
function createTable(tableName, columns) {
db[tableName] = {rows: {}, columns: columns};
}
function insertInto(tableName, row, id) {
var newRow = {};
for (var columnName in row) {
if (db[tableName].columns.indexOf(columnName) === -1) {
//invalid column
return false;
}
newRow[columnName] = row[columnName];
}
db[tableName].rows[id] = newRow;
return true;
}
function getIDs(tableName, where) {
var IDs = [];
for (var id in db[tableName].rows) {
if (where(db[tableName].rows[id])) {
IDs[IDs.length]=id;
}
}
return IDs;
}
function update(tableName, where, what) {
what(tableName, getIDs(tableName, where));
}
function deleteRecord(tableName, where) {
var removeIDs = getIDs(tableName, where);
for (var id in removeIDs) {
//Could be done by regexes, but I am not fluent with them and I am lazy to check them out
delete db[tableName].rows[removeIDs[id]];
}
}
function select(tableName, where) {
var IDs = getIDs(tableName, where);
var result = {};
for (var id in db[tableName].rows) {
result[id] = db[tableName].rows[id];
}
return result;
}
function dropTable(tableName) {
delete db[tableName];
}
You probably see that this is only a minimalistic implementation, but with the same approach you can implement altering, joins, grouping and so on. My focus here was just to illustrate how you can create a database. Let's go to the next step, storing the database into localStorage:
localStorage.setItem("db", JSON.stringify(db));
You will need to be able to convert back the local storage item to object, especially because you want to reuse your database even after reload. Let's see how you should initialize db:
var db = !!localStorage.getItem("db") ? angular.fromJson(localStorage.getItem("db")) : {};
Localstorage is a key-value store, which stores everything in string format. So, the messages will be identified by one key (e.g. "messages") and the users another key (e.g. "users").
Then you need to create 2 (angular) services one for the messages and one for the users. Both will interface with localstorage (using the respective keys) and will perform the operations that you want.
If you provide us with more information then we could help you a bit more.

Cant get the current id of a data from local Storage using jquery

I am working on an app to store data offline. My problem is when I try to retrieve the data from local storage for update/edit, it keeps calling only the id of the first item, and not calling the id of the data in view.
Please what am I doing wrong?
Here is my code for loading employees:
// load cases from localStorage
var employees;
if (localStorage.getItem('employees')) {
employees = JSON.parse(localStorage.getItem('employees'));
} else {
// If no cases, create and save them
employees = [];
// offling storing of our cases
localStorage.setItem('employees', JSON.stringify(employees));
}
// show case listing in list view page
var showEmployees = function () {
//erase existing content
$('#employee_list').html('');
//insert each employee
for (var i = 0; i<employees.length; i++) {
addEmployees(employees[i]);
}
};
Here is my code to add an employee to list view:
//add an eliment to list view
var addEmployees = function (empData) {
//HTML content of one list element
var listElementHTML = '<li><a class="employee_list" ui-btn ui-btn-e ui-btn-icon-right ui-icon-carat-r" data-transition="fade" data-split-icon="delete" href="#item'+empData.id+'">' + empData.employeename + '<br> ' + empData.dateofbirth + '</br></a></li>';
//appending the HTML code to list view
$('#employee_list').append(listElementHTML);
};
Here is my code for Edit function:
//User input to edit form
$('#edit_employee_page').on('click' , function () {
var editEmployee = JSON.stringify({
id: employees.length+1,
employeeno: $('#employeeno').val(),
employeename:$('#employeename').val(),
stateoforigine:$('#stateoforigine').val(),
employeephone: $('#employeephone').val(),
dateofbirth:$('#dateofbirth').val()
});
//Alter the slected data
localStorage.setItem("employees", JSON.stringify(employees));
return true;
});
for (var i in employees) {
var id = JSON.parse(localStorage.getItem(employees[i]));
}
Here is my code for the Edit button:
//register Edit button
$('.edit_button').live('click', function (e) {
alert('I was Cliked!');
e.stopPropagation();
$.each(employees, function(a, b) {
//if(b.id == employees[i]){
$('#id').val(b.id);
$('#employeeno').val(b.employeeno);
$('#employeename').val(b.employeename);
$("#stateoforigine").val(i.stateoforigine);
$('#employeephone').val(b.employeephone);
$('#dateofbirth').val(b.dateofbirth);
$("#id").attr("readonly","readonly");
$('#employeeno').focus();
$.mobile.changePage('#edit_employee_page');
return false;
//}
});
});
Here is my local Storage:
[
{"id":1,
"employeeno":"DEF/234/20014",
"employeename":"Bill Gates",
"stateoforigine":"Osun",
"employeephone":"080765432",
"dateofbirth":"12/11/1965"},
{"id":2,
"employeeno":"DEF/234/20014",
"employeename":"Bill Gates",
"stateoforigine":"Osun",
"employeephone":"080765432",
"dateofbirth":"12/11/1966"},
{"id":3,
"employeeno":"DEF/234/20014",
"employeename":"Bill Gates",
"stateoforigine":"Osun",
"employeephone":"080765432",
"dateofbirth":"12/11/1966"},
{"id":4,
"employeeno":"DAST/003/2003",
"employeename":"Gold Base",
"stateoforigine":"",
"employeephone":"",
"dateofbirth":"12/03/1986"}
]
Thanks for helping me out
The way you are storing your employees into localStorage is correct, but the way you are getting them out is incorrect. You stored your employees by stating:
localStorage.setItem("employees", JSON.stringify(employees));
So, in order to retrieve them, you must use:
var employees = JSON.parse(localStorage.getItem("employees"));
You see, you stored the data as a string with a key of "employees"; therefore, you can only retrieve it by that key. Since all data stored in localStorage is saved as a string, you must use JSON.parse() to convert the data back into an object - an array in this case. Then you can iterate over your employees.
Update:
You should be running this code as soon as the page is rendered (see below). I'm not sure how you're doing that - if you're using an IIFE or jQuery's document.ready() function. I don't think it's necessary to store an empty array into localStorage if none were loaded initially, so, I took your else clause out.
var employees = [];
if (localStorage.getItem('employees') !== null) {
employees = JSON.parse(localStorage.getItem('employees'));
}
Debug this line-by-line when it runs and make positive your employees variable contains data. If it doesn't contain data, well then, there's nothing to edit.
If, however, there is data, then execute your showEmployees() function. Oddly, I'm not seeing in your code where you actually call this. Is it bound to a button or action in your UI? Also, what is that for loop doing after your $('#edit_employee_page') click event function? It's trying to read data from localStorage improperly and it does nothing.
I think if you simply stepped through your code one line at a time using breakpoints and desk-checking your inputs/outputs you'd find out where you're going wrong.
It also appears that there's a disconnect in your code. May be you left out some lines; you define a string editEmployee but out of the blues you store JSON.stringify(employees) whereas employees is not defined in your code:
$('#edit_employee_page').on('click' , function(){
var editEmployee = JSON.stringify({
id: employees.length+1,
//........
});
//Alter the slected data
localStorage.setItem("employees", JSON.stringify(employees));
return true;
});
I had a similar task to do . I did it this way.
I passed the dynamic Id to be passed as an id attribute
id="'+empData.id+'"
and then inside the
$('.edit_button').live('click', function (e) {
alert('I was Cliked!');
var empId=$(this).attr('id');
rest of the code is same.

Meteor method reactivity doesn't work

I'm not experienced in Javascript but I've read a ton of articles about Meteor reactivity but still can't figure out why it is not working in my case.
When a new product is added, I want to be recalculated total cost and use it in the totalCost helper so it's almost real time visible in the browser.
Can someone please take a look at my code and try to figure out some logic error? Everything except the reactivity is working on my computer.
I have got this method in /models/Product.js :
Meteor.methods({
totalProductCost: function() {
var pipeline = [
{$match: {owner: Meteor.userId()}},
{$group: {_id: null, cost: {$sum: "$cost"}}}
];
var data = Products.aggregate(pipeline)["0"].cost;
return (data === undefined) ? 0 : data;
}
});
Then I've got layout.js in client folder:
if (Meteor.isClient) {
var handle = Meteor.subscribe("Products", Meteor.userId());
ProductManager = {
_productItems: null,
_dep: new Tracker.Dependency(),
getProducts: function () {
this._dep.depend();
return this._productItems;
},
setProducts: function (value) {
if (value !== this._productItems) {
this._productItems = value;
this._dep.changed();
}
},
getTotalCost: function () {
return ReactiveMethod.call('totalProductCost');
}
}
// TRACKER
Tracker.autorun(function () {
if (handle.ready()) {
ProductManager.setProducts(Products.find().fetch());
}
});
// HELPERS
Template.boxOverview.helpers({
"totalCost" : function () {
return ProductManager.getTotalCost();
},
});
}
It seems that you used a collection.aggregate in a method. If you need reactivity, you need to use a publication rather than a method (or you need to call the method each time you want to refresh). However, if you use your aggregation inside your publication (I assume you use a package for it) you will loose reactivity as well.
What I would advise you is to use a publication without aggregate function. You calculate your product cost by creating a new field and adding it to your cursor. Once, you do that, if you want to keep reactivity, it is necessary to use to use cursor.observeChanges() or just cursor.observe().
Have a look at this example:
var self = this;
// Modify the document we are sending to the client.
function filter(doc) {
var length = doc.item.length;
// White list the fields you want to publish.
var docToPublish = _.pick(doc, [
'someOtherField'
]);
// Add your custom fields.
docToPublish.itemLength = length;
return docToPublish;
}
var handle = myCollection.find({}, {fields: {item:1, someOtherField:1}})
// Use observe since it gives us the the old and new document when something is changing.
// If this becomes a performance issue then consider using observeChanges,
// but its usually a lot simpler to use observe in cases like this.
.observe({
added: function(doc) {
self.added("myCollection", doc._id, filter(doc));
},
changed: function(newDocument, oldDocument)
// When the item count is changing, send update to client.
if (newDocument.item.length !== oldDocument.item.length)
self.changed("myCollection", newDocument._id, filter(newDocument));
},
removed: function(doc) {
self.removed("myCollection", doc._id);
});
self.ready();
self.onStop(function () {
handle.stop();
});
This is taken from here.

Categories

Resources