I have a function that get a value that needs to be accesed across multiple pages (function below).
var currentProperty = '';
function goTo(ele){
var firstLine = ele.getAttribute('value');
var user = firebase.auth().currentUser;
var ref = firebase.database().ref().child("users").child(user.uid).child('rentingAddresses');
ref.orderByChild("firstLine").equalTo(firstLine).once("value", function(snapshot) {
snapshot.forEach(function(child) {
currentProperty = child.key;
console.log(currentProperty);
});
});
}
When the function is fired, it saves the value into the variable but when I access it on another page the value has gone. I've tried using the following method:
window.onload = function() {
var currentProperty = 'nothing'
localStorage.setItem("prop", currentProperty);
}
function goTo(ele){
var firstLine = ele.getAttribute('value');
var user = firebase.auth().currentUser;
var ref = firebase.database().ref().child("users").child(user.uid).child('rentingAddresses');
ref.orderByChild("firstLine").equalTo(firstLine).once("value", function(snapshot) {
snapshot.forEach(function(child) {
currentProperty = child.key;
console.log(currentProperty);
});
});
}
But it doesnt seem to work either. Is there any other way to retain the value once I leave the page containing the function?
TYIA.
There are a few problems in your code:
You're never setting the value that you read from the database into local storage.
You're never reading the value from local storage in the code you provided.
setting the value that you read from the database into local storage
You're only setting the value to local storage once in:
window.onload = function() {
var currentProperty = 'nothing'
localStorage.setItem("prop", currentProperty);
}
This means that every time the page loads you set prop='nothing' in local storage. Nothing else ever happens.
You'll probably also want to write the value that you read from the database into local storage. In that case, you should do so in the callback from your once("value" handler:
ref.orderByChild("firstLine").equalTo(firstLine).once("value", function(snapshot) {
snapshot.forEach(function(child) {
currentProperty = child.key;
localStorage.setItem("prop", currentProperty);
});
});
With this change you'll be updating the local storage to the value that you read from the database.
reading the value from local storage in the next page
You'll need to read the value back from local storage in the next page. Given the code you've already shown, I expect you'll do this with something like:
window.onload = function() {
var currentProperty = localStorage.getItem("prop");
// TODO: do something with currentProperty
}
Note that could also simply re-read the value from the database and using it:
ref.orderByChild("firstLine").equalTo(firstLine).once("value", function(snapshot) {
snapshot.forEach(function(child) {
currentProperty = child.key;
// TODO: do something with currentProperty
});
});
Related
I'm trying to create a database with "users" and their data in it. Strangely it doesn't put() new variables in it when I try to for the third time. To do all this I create a local database dblocal and replicate this DB to the remote db called dbremote. At first I create a document with one variable.
function newuser() {
if (window.document.consent_form.consent_to_share.value) {
var id = "p" + Date.now() + "-" + Math.floor(Math.random() * 10000);
var dblocal = new PouchDB(id);
var consenttoshare = window.document.consent_form.consent_to_share.value;
document.cookie = id;
var dbremote = 'http://localhost:5984/experiment';
dblocal.put({
_id: id,
consent: consenttoshare
});
dblocal.replicate.to(dbremote, {live: true});
}
}
This all worked well, in another js file I'm trying to add a variable to the same document by executing the following function putdb(). Im doing this in the following way (as said in their documentation is the right way):
function putdb () {
if (document.cookie){
var id = document.cookie;
var loggedin = "True";
var dblocal = new PouchDB(id);
dblocal.get(id).then(function (doc) {
doc.loggedin = loggedin;
return dblocal.put(doc);
}).then(function () {
return dblocal.get(id);
}).then(function (doc) {
console.log(doc);
var dbremote = 'http://localhost:5984/experiment';
dblocal.replicate.to(dbremote, {live: true});
});
}
}
This succesfully added the variable loggedin to the document as I wanted. However upon trying to add information to this document for the third time (again in another js file), nothing happens. I used exactly the same approach as before but only use different variables.
function putdb (checked) {
if (document.cookie) {
var id = document.cookie;
var checkedlist = [];
for (i = 0; i < checked; i++) {
checkedlist.push($("input[type=checkbox]:checked")[i].value)
}
var playlistname = document.getElementById("playlistname").value;
var dblocal = new PouchDB(id);
dblocal.get(id).then(function (doc) {
doc.checkedlist = checkedlist;
doc.playlistname = playlistname;
return dblocal.put(doc);
}).then(function () {
return dblocal.get(id);
}).then(function (doc) {
console.log(doc);
var dbremote = 'http://localhost:5984/experiment';
dblocal.replicate.to(dbremote, {live: true});
});
}
}
I checked all variables, they are correct.
I tried plain text variables.
The script does run.
I tried to add information to the document the way I did the first time.
None of all this seems to add another variable to the document as I wanted in the last function. I think it has to do with the way pouchDB works which I don't know. help is much appreciated!
There are a number of problems in your code that results in bad usage of PouchDB, and may lead to problems.
First of all, it does not make a lot of sense to give your document the same id as the name of your database. Assuming you want a one database per user approach, there are two approaches you can follow.
Multiple document approach
You can instead make multiple documents within the same database with different id's. For instance, your 'consent' information may be stored like this:
var id = "p" + Date.now() + "-" + Math.floor(Math.random() * 10000);
let dblocal = new PouchDB(id);
document.cookie = id;
let dbremote = 'http://localhost:5984/experiment';
dblocal.put({
_id: "consent",
consent: window.document.consent_form.consent_to_share.value
});
dblocal.replicate.to(dbremote, {live: true});
While your playlist information is stored like this:
dblocal.put({
_id: "playlist",
name: playlistname,
itemsChecked: checkedlist
});
Single-document approach
The second option is to store a single document containing all the information you want to store that is associated to a user. In this approach you will want to fetch the existing document and update it when there is new information. Assuming you named your document global-state (i.e. replace "consent" in the first code snippet with "global-state"), the following code will update a document:
dblocal.get("global-state").then((doc)=>{
doc.loggedIn = true; // or change any other information you want
return dblocal.put(doc);
}).then((response)=>{
//handle response
}).catch((err)=>{
console.log(err);
});
Furthermore, you should only call the
dblocal.replicate.to(dbremote, {live: true});
function once because the 'live' option specifies that future changes will automatically be replicated to the remote database.
I'm fetching the top news from hacker news API which is using firebase. I'm planning to build a progressive web app hence, I'm planning to cache the results into the localstorage.
The current code is here, which fetch and render the top stories. The code is here:
var ref = new Firebase("http://hacker-news.firebaseio.com/v0/");
var itemRef = ref.child('item');
var topStories = [];
var storyCallback = function(snapshot) {
var story = snapshot.val();
var html = '';
if(story.score) {
html = '<i>'+story.score+'</i> '+story.title+''
}
document.getElementById(topStories.indexOf(story.id)).innerHTML = html;
}
ref.child('topstories').once('value', function(snapshot) {
topStories = snapshot.val();
for(var i = 0; i < topStories.length; i++) {
var element = document.createElement("P");
element.id = i;
document.getElementById('items').appendChild(element);
itemRef.child(topStories[i]).on('value', storyCallback);
}
});
ref.child('topstories').on('child_changed', function(snapshot, prevChildName) {
var ref = snapshot.ref()
var index = ref.name();
var oldItemId = topStories[index];
itemRef.child(oldItemId).off();
var newItemId = snapshot.val();
topStories[index] = newItemId
itemRef.child(newItemId).on('value', storyCallback);
});
If I add each stories into the localstorage (by tweaking the above code), how can I skip fetching it from firebase the next time (if it already presents and doesn't changed)?
Note that doesn't change part is important because I can easily get from local storage using the key, how ever it should be in sync with firebase as well. So wondering whether firebase has some way to handle this
If I'm not missing any point you can simply check whether they already exists in local storage or not
if(localStorage.getItem('key')){
//display here
}else{
//fetch
//save for next time
localStorage.setItem('key', JSON.stringify('yourdata'));
//and display here
}
Also you can generalize your function for fetching, display or rendering so you can call at multiple place.
I'm using a index.js file and a check.js file in Node.js. I use check.js to check every 500 ms if some value in my databases has changed. If so, the value of variable currentInput changes. I want to use this variable currentInput in index.js so, that I get the current value of it. I tried searching about in but the solutions I've found don't give me the current value back.
In check.js:
var currentInput;
.
.
.
var check = function(){
pool.query('SELECT someValue FROM table WHERE id=1',function(err,rows){
if(err) throw err;
var newInput = rows[0].someValue;
if(currentInput!=newInput){
currentInput=newInput;
}
console.log('Current value:', currentInput);
});
setTimeout(check, 500);
}
In index.js I'd like to use it something like:
var x = function(currentInput);
You can export your function as a module. Then load it and call from index.js.
check.js
exports.check = function() {
pool.query('SELECT someValue FROM table WHERE id=1',function(err,rows){
if(err) throw err;
var newInput = rows[0].someValue;
if(currentInput!=newInput){
currentInput=newInput;
}
return currentInput);
});
};
index.js
var check = require("./path/to/check.js");
setTimeout(function(){
var x = check.check;
}, 500);
You can use the GLOBAL variable. The GLOBAL variable is (yes you were right) global.
For example:
//set the variable
global.currentInput = newInput;
// OR
global['currentInput'] = newInput;
//get the value
var x = global.currentInput;
// OR
var x = global['currentInput'];
Note that this may not be the most efficient way of doing this, and people do not like this way at all (https://stackoverflow.com/a/32483803/4413576)
To use the global variable in different files, they have to be "connected with each other".
// index.js
require('./check.js')
I have a slider and I want to be able to set the value into local storage so that I can use this value dynamically on a web page.
The part I need help with is chrome.storage.local.set(v);.
$('#slider').on('change', function () {
var v = $(this).val();
$( 'div').each(function () {
this.style.setProperty( 'margin', '10px '+v+'px', 'important' );
});
chrome.storage.local.set(v);
});
The variable works perfectly, I just need to be able to save it into localstorage so I can use it. It works before page reload, so all I need now is to be able to put it into storage so on reloading that page it saves the value.
update: is this what you were saying to do?
$('#slider').on('change', function () {
var v = $(this).val();
var theKeyForV = chrome.storage.local.get({"keyforv" : v},
chrome.storage.local.set({"keyforv" : v},
function(){
// callback (what goes here?)
});
$( 'div').each(function () {
this.style.setProperty( 'margin', '10px '+theKeyForV+'px', 'important' );
});
});
You can use this way:
// Set
var dataObj = {};
dataObj["key1"] = "vaule1";
// dataObj["key2"] = "vaule2"; // if you want to set value more than one key.
chrome.storage.local.set(dataObj, function() {
if(!chrome.runtime.lastError){
// set storage value successfully.
}
});
// Get
var dataObj = ["key1"];
// var dataObj = ["key1", "key2"]; // if you want to get value more than one key.
chrome.storage.local.get(dataObj, function (callback){
if(callback && callback["key1"]){
// To Do: handle callback["key1"].
}
});
// Remove
var dataObj = ["key1"];
// var dataObj = ["key1", "key2"]; // if you want to remove value more than one key.
chrome.storage.local.remove(dataObj, function(callback) {
if(!chrome.runtime.lastError){
// remove successfully.
}
});
To learn more, see chrome.storage
You may need to pay a little more attention to the api. chrome.storage.local is of type StorageArea. As such, the first (and only mandatory) argument to chrome.storage.local.set is “An object which gives each key/value pair to update”. You’re only giving the second half of that object. Try:
chrome.storage.local.set({"sidemargins":v});
I want to update a div with a list of anchors that I generate from a local database in chrome. It's pretty simple stuff, but as soon as I try to add the data to the main.js file via a callback everything suddenly becomes undefined. Or the array length is set to 0. ( When it's really 18. )
Initially, I tried to install it into a new array and pass it back that way.
Is there a setting that I need to specify in the chrome manifest.json in order to allow for communication with the database API? I've checked, but all I've been able to find was 'unlimited storage'
The code is as follows:
window.main = {};
window.main.classes = {};
(function(awe){
awe.Data = function(opts){
opts = opts || new Object();
return this.init(opts);
};
awe.Data.prototype = {
init:function(opts){
var self = this;
self.modified = true;
var db = self.db = openDatabase("buddy","1.0","LocalDatabase",200000);
db.transaction(function(tx){
tx.executeSql("CREATE TABLE IF NOT EXISTS listing ( name TEXT UNIQUE, url TEXT UNIQUE)",[],function(tx,rs){
$.each(window.rr,function(index,item){
var i = "INSERT INTO listing (name,url)VALUES('"+item.name+"','"+item.url+"')";
tx.executeSql(i,[],null,null);
});
},function(tx,error){
});
});
self._load()
return this;
},
add:function(item){
var self = this;
self.modified = true;
self.db.transaction(function(tx){
tx.executeSql("INSERT INTO listing (name,url)VALUES(?,?)",[item.name,item.url],function(tx,rs){
//console.log('success',tx,rs)
},function(tx,error){
//console.log('error',error)
})
});
self._load()
},
remove:function(item){
var self = this;
self.modified = true;
self.db.transaction(function(tx){
tx.executeSql("DELETE FROM listing where name='"+item.name+"'",[],function(tx,rs){
//console.log('success',tx,rs)
},function(tx,error){
//console.log('error',tx,error);
});
});
self._load()
},
_load:function(callback){
var self = this;
if(!self.modified)
return;
self.data = new Array();
self.db.transaction(function(tx){
tx.executeSql('SELECT name,url FROM listing',[],function(tx,rs){
console.log(callback)
for(var i = 0; i<rs.rows.length;i++)
{
callback(rs.rows.item(i).name,rs.rows.item(i).url)
// var row = rs.rows.item(i)
// var n = new Object()
// n['name'] = row['name'];
// n['url'] = row['url'];
}
},function(tx,error){
//console.log('error',tx,error)
})
})
self.modified = false
},
all:function(cb){
this._load(cb)
},
toString:function(){
return 'main.Database'
}
}
})(window.main.classes);
And the code to update the list.
this.database.all(function(name,url){
console.log('name','url')
console.log(name,url)
var data = []
$.each(data,function(index,item){
try{
var node = $('<div > '+item.name + '</div>');
self.content.append(node);
node.unbind();
node.bind('click',function(evt){
var t = $(evt.target).attr('href');
chrome.tabs.create({
"url":t
},function(evt){
self._tab_index = evt.index
});
});
}catch(e){
console.log(e)
}
})
});
From looking at your code above, I notice you are executing "self._load()" at the end of each function in your API. The HTML5 SQL Database is asynchronous, you can never guarantee the result. In this case, I would assume the result will always be 0 or random because it will be a race condition.
I have done something similar in my fb-exporter extension, feel free to see how I have done it https://github.com/mohamedmansour/fb-exporter/blob/master/js/database.js
To solve a problem like this, did you check the Web Inspector and see if any errors occurs in the background page. I assume this is all in a background page eh? Try to see if any error occurs, if not, I believe your encountering a race condition. Just move the load within the callback and it should properly call the load.
Regarding your first question with the unlimited storage manifest attribute, you don't need it for this case, that shouldn't be the issue. The limit of web databases is 5MB (last I recall, it might have changed), if your using a lot of data manipulation, then you use that attribute.
Just make sure you can guarantee the this.database.all is running after the database has been initialized.