How to save reference in Firebase? - javascript

I'm struggling with what seems to be a basic Javascript problem. I generate a unique key for Firebase but that unique key which I want to stay constant keeps changing every time the page refreshes.
uniqueKey = function(){
var key = firebase.database().ref().child('users').push().key;
return {
usersKey: key
};
}();
var addName = function(){
var userName = document.getElementById("name").value;
var userNamePath = firebase.database().ref('users/' + uniqueKey.usersKey + '/name');
userNamePath.set(userName);
window.location.href="age.html";
}
var addAge10 = function(){
var userAgePath = firebase.database().ref('users/' + uniqueKey.usersKey + '/age');
userAgePath.set(10);
window.location.href="blood_type.html";
}
My attempt to solve this issue was to use the revealing module pattern, but I think I'm misunderstanding something. Do I need to separate javascript files..? Please correct me if I'm using bad javascript practice.

Firebase doesn't support arrays natively, so push() is used to create a unique index that can kind-of-sort-of be used to create lists.
Every time uniqueKey is initialized, presumably every time you refresh the page, push() is called again generating another random index. Assuming the code you posted above is only ran once inside of a single javascript context, the two functions addName and addAge10 should write to the same user. My guess is that you're calling the code above multiple times at runtime, generating multiple unique keys.
// load script (unique key generated)
addName()
// load script again (different key generated)
addAge10() // set with different key

Related

Saving a for loop result in a variable or saving it in a Gsheet

This is definitely a pretty basic question, but I can't seem to find a solution by myself, nor the answer in the depths of the internet.
Java script skill: Newbie
I am getting Google Forms Item Id's so that I could then edit/delete etc. even after somebody edits outside of my script.
To get them Ids I am using a 'for loop', which comfortably gets them for me in a string. Unfortunately I don't know how to save that result in a variable - always getting a syntax error.
I am also not happy with saving the logger.log in my google sheet.
Any ideas?
This is my code:
function GetItems3(){
var formId = "your-id";
var Form = FormApp.openById(formId);
var ajtems = Form.getItems();
for(var i=0;i<items.length;i++)
{ajtems[i].getId().toString()
Logger.log(ajtems[i].getId().toString())
};
//That saves the logger log in my sheet (DMsheet is a global var)
var A = DMsheet.getRange(15, 6, ajtems.length, 1).setValue(A);}
Thanks in advanc3
There are several things wrong from your code.
1) There is no need to use the .toString() method because getId() already returns the id as a String.
2) You didn't define your ajtems var.
3) You can't declare a var like A and use it at the same line you are declaring it because it hasn't been set yet.
4) You didn't declare DMsheet, this variable should contain your sheet and you would get it using the Class Sheet.
5) You said in your post "Java skill: Newbie". Java and JavaScript are not the same.
This code will help you to solve your issue:
function GetItems3(){
var formId = "your-id";
var Form = FormApp.openById(formId);
var items = Form.getItems();
// Get a sheet from the Spreadsheet you are running your script
var dmSheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
// Create an empty array to save the Form's items
var myArray = [];
for(var i=0;i<items.length;i++){
Logger.log(items[i].getId());
// Sotre the title items in the array
myArray.push(items[i].getTitle());
};
// Set the values in your sheet
dmSheet.getRange(1, 1, 1, items.length).setValues([myArray]);
}
I really recommend you to take your time to read the Apps Script docs. It will help you a lot to improve your coding and clear your doubts on how to use Apps Script in the best way possible.

keeping localStorage objects that iterate whilst using clear() within the same function

I'm trying to clear all local storage when the user either completes the game loop or starts a new game, but also keep some values.
I can do this already with my sound values for volume:
// inside a conditional statement that fires when the user chooses to start a new game.
if (newGameBool === '1') {
var tst = myAu;
//myAu is the stored value that the user sets as sound using a range type input
localStorage.clear();
localStorage.setItem("Au", tst);//A newly cleared localStorage just got a new value, and it's the same as it was before.
UI.myLoad();//reload the function that uses LS to do things.
}
How do I do this for key's that have an iterating number attached to them?
Here is how I save them:
var i = +v + +1;
localStorage.setItem("v", i);
var vv = localStorage.getItem("v");
localStorage.setItem("LdrBrd_" + vv, JSON.stringify(LdrBrd));//saves all data with the iterating key name.
Calling them the way i did the sound function:
var gv = v + 1;//v calls the value from LS and adjusted for off-by-one error. gv is a local variable.
if (newGameBool === '1') {
var ldd, vg;
for (var ii = 0; ii < gv; ii++) {
var ld = localStorage.getItem("LdrBrd_" + ii);
if (ld != null) {
//these are the values that i want to pass beyond the clear point
ldd = JSON.parse(ld);//JSON string of data saved
vg = ii;//how many of them.
}
}
localStorage.clear();
for (var xx = 0; xx < vg; xx++) {
var nld = localStorage.getItem("LdrBrd_" + xx);
if (nld != null) {
localStorage.setItem("LdrBrd_" + ii, JSON.stringify(ldd));
}
}
localStorage.setItem("v", vg);
UI.myLoad();
}
I have been using console.log() in various spots to see what is going on. I comment-out the clear function just to see if the values were wrong and they don't save all all. I tried to make a fiddle, but the local storage wasn't working at all there. In visual studio, it works fine but the script to this file is almost 2000 lines long, so i tried to dress it up the best i knew how.
Thanks in advance for any help or guidance.
I was stuck on this for a few days, but i think i found something that will work, so i'll answer my own question in case there is value in posterity.
locatStorage.clear();
/* ^LS clear() function is above all new setItem codes, some variables are declared globally and some are declared at the top of the functional scope or as param^ */
var itemClass = document.querySelectorAll(".itemClass");//the strings are here
if (itemClass) {//make sure some exist
for (var p = 0; p < itemClass.length; p++) {//count them
mdd = JSON.parse(itemClass[p].innerText);//parse the data for saving
localStorage.setItem("v", v);//this is the LS item that saves the amount of items i have, it's declared at the top of the functions timeline.
localStorage.setItem("LdrBrd_" + p, JSON.stringify(mdd));//this setItem function will repeat and increment with 'p' and assign the right string back to the key name it had before.
}
}
The key is to keep the strings physically attached to an element, then call the class name. The i ran a loop counting them. 'mdd' will spit back each item i want. So then all that is left to do is re-set the item back to it's original status.
This has allowed me to create a way for my users to collect trophies and keep them even after clearing the localStorage when the he/she decides to start a new game.
I use CSS to hide the text from the string.
color:transparent;
In my gameLoop, i have a function that will read the saved strings and show them as cards just below the hidden strings.
Since you want to keep some values I recommend one of two things:
Don't call localStorage.clear() and instead only wipe out the values that you want using localStorage.removeItem('itemName'). Since you said the item names have a numeric component, maybe you can do this in a loop to reduce code.
Pull item(s) that you want saved first and restore them after calling clear(). This option is best if there are way more items that you want removed rather than saved (see below)
function mostlyClear() {
var saveMe = {};
saveMe['value1'] = localStorage.getItem('value1');
saveMe['anotherValue'] = localStorage.getItem('anotherValue');
localStorage.clear();
for(var prop in saveMe) {
if(!saveMe.hasOwnProperty(prop)) continue;
localStorage.setItem(prop, saveMe[prop]);
}
}

Accessing values in javascript

I am using a JS library for facetracking/emotion detection called CLMtracker.
http://auduno.github.io/clmtrackr/examples/clm_emotiondetection.html
Note: Seems to work best in chrome for those trying to use it.
Is the example I am using, I am wondering how I can access the values for each emotion. For instance, I want check every 10 seconds what the values are and print to console. From this I would also like to compare the values to find the highest and find the emotion that is attached to that. I think I am right in saying that the max() function will give me the highest out of an array?
What I have tried:
I have tried to get emotionData[0].emotion and emotionData[0].value which should print Angry and the value, but it only prints 0. I have also tried the same method with data which does not seem to return anything.
EDIT
emotionData gets me:
however it does not seem to show any update/change as I make my expression change
ec.meanPredict(ctrack.getCurrentParameters()) returns an object containing all the current scores for all emotions.
To get the current score of "Angry", for example, you would do :
ec.meanPredict(ctrack.getCurrentParameters())[0].value
So, in order to get the current most probable emotion, you could do this :
function getCurrentEmotion()
{
if(!ec.meanPredict(ctrack.getCurrentParameters())){setTimeout(getCurrentEmotion,1000);return;}
var currentData = ec.meanPredict(ctrack.getCurrentParameters());
var currentScores = [];
//Gather all scores in an array
for(var i=0;i<currentData.length;i++)
{
currentScores.push(currentData[i].value);
}
//Get the biggest score
var max = Math.max.apply(null,currentScores);
//Calculate its index
var indexOfScore = currentScores.indexOf(max);
//Get the associated emotion
var emotion = currentData[indexOfScore].emotion;
console.log(emotion);
//Set up a loop (did not add 'var', to allow stopping it from outside)
currentEmotionLoop = setTimeout(getCurrentEmotion,3000);
}
To stop the loop at any time, do this :
clearTimeout(currentEmotionLoop);
By the way, the ec variable is declared privately, so in order for this to work, either remove var where it is declared :
var ec = new emotionClassifier();
or write this code in the same file, under the same scope.

Accessing a Dynamically Named array in jQuery/javascript

I wish to name an array according to the table row containing the button that was clicked.
I get the table row thus:
var rowNum = $(this).parent().parent().index();
Now, I wish to name the array and access it.
var arrayName = 'arrTR' + rowNum;
window[arrayName] = new Array();
window[arrayName]["First"] = "Bob";
window[arrayName]["Last"] = "Roberts";
window[arrayName]["email"] = "me#there.com";
//The array should be accessible as arrTR__
alert(arrTR1["Last"]);
The alert does not work, so I am doing something wrong.
How should I refactor the code to allow me to update and access the array?
jsFiddle
What you're doing with the dynamically named variables is essentially creating an array of those variables (one for each rowNum), but giving each of those array elements its own individual named variable.
There is a much better way to do this. Instead of generating a series of dynamically named variables, make a single array or an object. Then add an element or property for each of the dynamically named variables you were going to generate.
Your test code could look like this:
var arrTR = [];
var rowNum = 1;
arrTR[rowNum] = {
First: 'Bob',
Last: 'Roberts',
email: 'me#there.com'
};
alert( arrTR[1].Last );
Alternatively, you can do something with $.data as mentioned in Johan's answer. But if you do use plain JavaScript code, use a single array as described here instead of multiple dynamically named variables.
There are several reasons to do it this way. It's cleaner and easier to understand the code, it may be faster when there are large numbers of entries, and you don't have to pollute the global namespace at all. You can define the var arrTR = []; in any scope that's visible to the other code that uses it.
Arrays and objects are made for keeping track of lists of things, so use them.
There is nothing wrong with your code, and the only place it has error is the alert since it is not defined on the first click button
see this fiddle with a little update
if(rowNum === 1)
alert(arrTR1["Last"]);
else if(rowNum === 2)
alert(arrTR2["Last"]);
fiddle
How about something like this?
$('.getinfo').click(function() {
var result = $('table tr:gt(0)').map(function(k, v){
return {
firstName: $(v).find('.fname').val(),
lastName: $(v).find('.lname').val(),
email: $(v).find('.email').val(),
}
}).get();
//update to show how you use the jQuery cache:
//1. set the value (using the body tag in this example):
$('body').data({ result: result });
//2. fetch it somewhere else:
var res = $('body').data('result');
});
Not sure how you want to handle the first row. I skip in in this case. You can access each row by result[index].
As you might have noticed, this saves all rows for each click. If you want to use the clicked row only, use the this pointer.
http://jsfiddle.net/nwW4h/4/

Javascript array index is a var

I'm working on a website with Jquery tabs dynamically generated. Each tab has an ID.
For the purpose of my script I need to know how many times the user has clicked in a tab.
To record the number of clicks I was thinking of doing an array like this:
var i = new Array(my_tab_id);
(...)
i[my_tab_id] = 0;
Where my_tab_id dynamically changes depending on the tab we're in. Sadly, it doesn't seem like the value of my_tab_id is translated into the array. I don't have i[5] = 0, i[6] = 0, etc. but rather i[my_tab_id], which doesn't help more than a simple var.
Any advice? Thanks!
In that case you shouldn't use an array, you should use an object, which you can treat like a hash.
var o = {};
var id = 'x';
o[id] = 1;
alert(o[id]);
This should allow you to store the click count onto each tab using the .data() function in jQuery each time a tab is clicked.
$('#example').bind('tabsselect', function(event, ui) {
var count = parseInt(ui.tab.data("clickCount"));
if (isNaN(count)) count = 0;
count++;
ui.tab.data("clickCount", count);
});
I think I understand your problem.
You are saying that the var i only has one element. This happens because the var i is newly instantiated every time you open a new tab. I'm guessing every tab is a new page or at least is a new context for var i.
If you want to keep an instance of an object (like an array) in between different pages, take a look at jStorage, it allows you to keep data locally on the browser and it makes it easier to maintain context between page loads.
If all tabs are on the same page then the solution is easier, you need to keep the array in a global variable for the page.
Are you sure my_tab_id is an integer when i[my_tab_id] = 0; is called?

Categories