Javascript OOP issue with variable scope - javascript

I'm using an alert() for testing, but I can't get my object to alert the right value of my variables after they have been changed inside of my for loop. I want to store the values in an object using a constructor but only the empty values I set at the beginning are being stored.
//declare the variables I'm going to use inside of my database query and for loop.
$(function(){
var uID = JSON.parse(localStorage.getItem( 'uID' ));
var hood = ' ';
var gender = ' ';
var birthday = ' ';
var zip = ' ';
Parse.initialize("ivHLAO7z9ml1bBglUN*******yCgKM2x","gNeGt04lU7xce*****BsIBSCVj");
$("#mainDiv").on('click', '.interested', function(){
//on click, use "uID" variable to query the parse database to get birthday, gender, neighborhood, and zip
var query = new Parse.Query(Parse.User);
query.equalTo("uID",uID);
query.find({
success: function(results) {
for(i = 0; i < results.length; i++){
//this is where the variable values declared at the beginning are supposed to be changed to the results of the query
hood = results[i].get("neighborhood");
gender = results[i].get("gender");
birthday = results[i].get("birthday");
zip = results[i].get("zipCode");
}
}//closes success
})//closes find
//my object constructor
function interested(neighborhood,sex, bDay, zipCode) {
this.hood = neighborhood;
this.gender = sex;
this.birthday = bDay;
this.zip = zipCode;
}
var intrstd = new interested(hood, gender, birthday,zip);
alert(intrstd.hood);
alert(intrstd.gender);
alert(intrstd.birthday);
alert(intrstd.zip);
});//closes on

If you query is asynchronous, then object is constructed before those variables change. Move your alert into correct scope:
//declare the variables I'm going to use inside of my database query and for loop.
$(function () {
var uID = JSON.parse(localStorage.getItem('uID'));
var hood = ' ';
var gender = ' ';
var birthday = ' ';
var zip = ' ';
Parse.initialize("ivHLAO7z9ml1bBglUN*******yCgKM2x", "gNeGt04lU7xce*****BsIBSCVj");
$("#mainDiv").on('click', '.interested', function () {
//on click, use "uID" variable to query the parse database to get birthday, gender, neighborhood, and zip
var query = new Parse.Query(Parse.User);
query.equalTo("uID", uID);
//my object constructor
function interested(neighborhood, sex, bDay, zipCode) {
this.hood = neighborhood;
this.gender = sex;
this.birthday = bDay;
this.zip = zipCode;
}
query.find({
success: function (results) {
for (i = 0; i < results.length; i++) {
//this is where the variable values declared at the beginning are supposed to be changed to the results of the query
hood = results[i].get("neighborhood");
gender = results[i].get("gender");
birthday = results[i].get("birthday");
zip = results[i].get("zipCode");
}
var intrstd = new interested(hood, gender, birthday, zip);
alert(intrstd.hood);
alert(intrstd.gender);
alert(intrstd.birthday);
alert(intrstd.zip);
} //closes success
}) //closes find
}); //closes on
});

Related

Can't get value of array

Still can't understand my mistake with this code.
All what I want it - via prompt get all list of users (name / surname)
function UserList() {
let users = [];
while (true) {
let response = prompt('Please, enter your name surname?');
if (response == null) {
alert('cancel');
break;
}
users.push(response.split(' '));
}
return users;
}
function User() {
this.name = userList[0];
this.surname = userList[1];
this.regDate = new Date;
for (i = 0; i < userList.length; ++i) {
console.log('Name: ' + this.name + ' Surname: ' + this.surname + '. Date of registration : ' + this.regDate)
}
}
let userList = new UserList();
let user = new User();
And I faced with a misunderstanding why I cant get first word of prompt despite I put users.push (response.split(' ')).
userList [0] - shows first index of array instead first word.
And second I want to get all list of users in console.log but instead it I get the same string depending on length of array
userList[0] in the function User will return an array: ['name', 'surname'].
To get the first name for example, you need to use this.name = userList[i][0]
function UserList() {
let users = [];
while (true) {
let response = prompt('Please, enter your name surname?');
if (response == null) {
alert('cancel');
break;
}
users.push(response.split(' '));
}
return users;
}
function User() {
for (var i = 0; i < userList.length; ++i) {
this.name = userList[i][0];
this.surname = userList[i][1];
this.regDate = new Date;
console.log('Name: ' + this.name + ' Surname: ' + this.surname + '. Date of registration : ' + this.regDate)
}
}
let userList = new UserList();
let user = new User();
You are pushing an array in an other array, so your index is not correct (array looks like this: [["firstname", "lastname"]]). You could spread the items when pushing using the spread operator (...), you could also flatten the array using flat().
Also when creating a date, use new Date().
function UserList() {
let users = [];
while (true) {
let response = prompt('Please, enter your name surname?');
if (response == null) {
alert('cancel');
break;
}
users.push(...response.split(' ')); // flatten
}
return users;
}
function User() {
this.name = userList[0];
this.surname = userList[1];
this.regDate = new Date(); // ()
console.log('Name: ' + this.name + ' Surname: ' +
this.surname + '. Date of registration : ' + this.regDate)
}
let userList = new UserList();
let user = new User();
Using flat()
return users.flat();
Edit
I actually understood the question wrong (thought you only wanted 1 user), the other answer should be correct and makes more sense.
UserList shouldn't be a constructor. It should just be a function that returns an array of names.
You shouldn't be iterating over the list of users within User. You should then be iterating over the array creating one new User on each iteration which should be generated from a constructor. You can just pass in each name from the array and build an new object.
function getNames() {
const users = [];
while (true) {
const response = prompt('Please, enter your first and last names');
if (response == null) break;
users.push(response.split(' '));
}
return users;
}
// Pass in a user name from the array as an argument
// It's array so we can destructure the first and last name
// immediately
function User([first, last]) {
this.first = first;
this.last = last;
this.regDate = new Date();
this.message = `Name: ${this.first}. Surname: ${this.last}. Date of registration: ${this.regDate}.`;
}
// Iterate over the array generated by `getUsers`
// and for each name create a new user.
for (let name of getNames()) {
console.log(new User(name));
}
Additional documentation
Destructuring assignment

Firebase .orderByChild().on runs more and more times every time it is called

I'm creating a guest list program that stores the guest list in Firebase RTDB and when I check people in and out my function runs several times more than it is supposed to. I've sent alerts to the console so I know how many times it has run. I have separate functions for both check in and check out operations so it may be that I am calling my db too many times?
//-------------------- Check In and Check In Helper Functions -------------------------
//Helper Function to Grab current List index
function printArray() {
var ref = database.ref('guestList')
ref.on('value', readData, errData);
}
function readData(data){
guestList=[];
var scores = data.val();
var keys = Object.keys(scores)
for (var i=0; i < keys.length; i++){
var k = keys[i]
var name = scores[k].name;
var inside = scores[k].Inside;
var timeIn = scores[k].TimeIn;
var timeOut = scores[k].TimeOut;
guestList[i] = {
name: name,
Inside: inside,
TimeIn: timeIn,
TimeOut: timeOut,
}
}
checkIn(guestList);
}
function errData(err){
console.log('Error!');
console.log(err);
}
//Helper Function to set text box to selected name
function checkInn(name){
console.log(name)
document.getElementById('checkIn').value = name;
}
//Check in
function checkIn(list) {
//Grabs current guest to be added or deleted from form text box
var name = document.getElementById('checkIn').value;
//Checks to see if user is in list of guests and isn't in the list of guest in the party
var guestsRef = firebase.database().ref("guestList/");
guestsRef.orderByChild("name").on("child_added", function(data) {
if (name == data.val().name) {
objIndex = list.findIndex((obj => obj.name == name));
guestsRef = firebase.database().ref("guestList/" + objIndex)
guestsRef.update({
Inside: "Yes",
TimeIn: getTime(),
})
guestsRef.off();
document.getElementById('checkIn').value = "";
alerts(name, true)
}
})
}
//------------------------- Check Out ------------------------------------------------------------
//Helper Function to Grab current List index
function printArrayy() {
var ref = database.ref('guestList')
ref.on('value', readOutData, errData);
}
function readOutData(data){
guestList=[];
var scores = data.val();
var keys = Object.keys(scores)
for (var i=0; i < keys.length; i++){
var k = keys[i]
var name = scores[k].name;
var inside = scores[k].Inside;
var timeIn = scores[k].TimeIn;
var timeOut = scores[k].TimeOut;
guestList[i] = {
name: name,
Inside: inside,
TimeIn: timeIn,
TimeOut: timeOut,
}
}
checkOut(guestList);
}
//Helper Function to set text box to selected name
function checkOutt(name){
console.log(name);
document.getElementById('checkOut').value = name;
}
//Check Out
function checkOut(list) {
//Grabs current guest to be added or deleted from form text box
var name = document.getElementById('checkOut').value;
//Checks to see if user is in list of guests and isn't in the list of guest in the party
var guestsRef = firebase.database().ref("guestList/");
guestsRef.orderByChild("name").on("child_added", function(data) {
if (name == data.val().name) {
objIndex = list.findIndex((obj => obj.name == name));
guestsRef = firebase.database().ref("guestList/" + objIndex)
guestsRef.update({
Inside: "No",
TimeOut: getTime(),
})
document.getElementById('checkOut').value = "";
guestsRef.off();
alerts(name, false)
}
})
}
//Placeholder to alert user when a succesful check in or check out function runs
function alerts(name, Boolean){
if(Boolean){
console.log(name + " has been checked in!")
}
else{
console.log(name + " has been checked out!")
}
}
Here is the screenshot of my output. Thanks in advance!
Edit: Forgot to mention and apologize for my excessive use of helper functions! My HTML form calls printArrayy() and printArray first for each function!
have you tried once instep on, i mean:
ref.once('value', readOutData, errData); }

Accessing an object not working with a variable

This seems simple but I'm banging against a wall. My code gets weights, accesses an object array to get a value then calculates a result using that value * weight. But accessing the object doesn't work with a variable.
function calc(){
var gender;
if(document.getElementById("male").checked){
gender = "mensList";
} else if (document.getElementById("female").checked){
gender = "womensList";
} else {
alert("Please select a gender");
return false;
}
var kg = parseInt(document.getElementById("bwKg").value);
var grams = parseFloat(document.getElementById("bwGrams").value);
var bw = parseFloat(kg + grams);
var lifted = parseFloat(document.getElementById("liftWeight").value);
var theValue = womensList[bw]; // This works
var theValue = mensList[bw]; // This also works
var theValue = gender[bw]; // This doesn't work
var theValue = gender + "[\"" + bw + "\"]" // Nor this
var result = theValue * lifted;
document.getElementById("result").textContent = result;
}
var womensList = {
40.0: "1.4936",
40.1: "1.4915",
40.2: "1.4894",
40.3: "1.4872",
40.4: "1.4851",
// ......... etc
150.7: "0.7691",
150.8: "0.7691",
150.9: "0.7691"
};
var mensList = {
40.0: "1.3354",
40.1: "1.3311",
40.2: "1.3268",
40.3: "1.3225",
40.9: "1.2975",
// ......... etc
205.7: "0.5318",
205.8: "0.5318",
205.9: "0.5318"
};
In your code you are setting a gender to string not variable.
if(document.getElementById("male").checked){
gender = "mensList";
} else if (document.getElementById("female").checked){
gender = "womensList";
}
Should be
if(document.getElementById("male").checked){
gender = mensList;
} else if (document.getElementById("female").checked){
gender = womensList;
}
Here is your problem :
if(document.getElementById("male").checked){
gender = "mensList"; //gender now contains a string only..
} else if
Since gender contains a mere string, this will not work:
var theValue = gender[bw]; // This doesn't work
What you should be doing instead is :
if(document.getElementById("male").checked){
gender = mensList; //now gender contains an array provided mensList is defined beforehand ..
}

Cordova Sqlite plugin inserts entries with null values

I'm implementing the Cordova Sqlite plugin in a Ionic project, so far I've been able to create a database and table and make queries following the functions available through the ngCordova implementation.
I noticed there's a insertCollection function available, which I tried to test, I passed an array to it and even though the inserts are made, the entries are made with null.
This my example table definition:
CREATE TABLE IF NOT EXISTS people (id integer primary key, firstname text, lastname text)
I filled an array like this:
for(var i = 0; i < 250000; i++){
var index = i + 1;
firstname = firstname + ' ' + index;
var entry = {
'firstname' : firstname,
'lastname' : lastname
};
$scope.insertArray.push(entry);
}
And then made the insert like this:
$cordovaSQLite.insertCollection($rootScope.db, $scope.insertQuery, $scope.insertArray).then(function(res) {
console.log(res);
}, function (err) {
console.error(err);
});
Where insertQuery is the following:
INSERT INTO people (firstname, lastname) VALUES (?,?)
I made a select like this:
$scope.select = function() {
$scope.results = [];
var query = "SELECT firstname, lastname FROM people";
$cordovaSQLite.execute($rootScope.db, query).then(function(res) {
if(res.rows.length > 0) {
console.log('select was successful ' + res.rows.length + ' entries');
for(var i = 0; i < $scope.maxItemsToShow; i++){
$scope.results.push(res.rows.item(i));
}
} else {
console.log("No results found");
}
}, function (err) {
console.error(err);
});
}
I try to display the results on a ion-list but the values in firstname and lastname are null for all the items.
What is causing this problem?
The function insertCollection expects an array of arrays, not an array of records. The inner array must contain the values to insert in the order that the question marks (as place holders for the values) appear in the sql statement.
So you need to write:
for(var i = 0; i < 250000; i++){
var index = i + 1;
firstname = firstname + ' ' + index;
var entry = [firstname, lastname];
$scope.insertArray.push(entry);
}

Parse.com Cloud Code, trying to filter query, but query still contains all objects

I'm trying to add unique objects to my parse database, that is, the name property must be different for each object. I try to query for all objects with a given name like so
var query = new Parse.Query(Food);
query.exists("name", name);
query.count({
success: function(number) {....}
However, query.count is always the total number of objects (90) stored on the database, even though there should be 0 or 1 objects with a given name stored.
EDIT:
Following one of the answers, I modified the code to this. However, I still see duplicates in the database.
var query = new Parse.Query(Food);
query.equalTo("name", name);
query.first({
success: function(results) {...}
Below is the entire (edited) function
Parse.Cloud.define("recordFavorite", function(request, response) {
var foodList = request.params.foodList; //string array of food names
var foodListCorrected = new Array();
var Food = Parse.Object.extend("Food");
// Wrap your logic in a function
function process_food(i) {
// Are we done?
if (i == foodList.length) {
//console.log("count is " + foodListCorrected.length);
Parse.Object.saveAll(foodListCorrected, {
success: function(foodListCorrected) {},
error: function(foodListCorrected) {}
});
return;
}
var name = foodList[i];
//console.log("before name is " + name);
var query = new Parse.Query(Food);
query.equalTo("name", name);
query.first({
success: function(results) {
if(!results){
console.log("new");
var food = new Food();
food.set("name", name);
foodListCorrected.push(food);
// console.log(foodListCorrected.length);
} else {
//don't create new food
console.log("exists");
}
process_food(i+1)
},
error: function(error) {
console.log("error");
}
});
}
// Go! Call the function with the first food.
process_food(0);
});
EDIT:
I've tried an alternate approach to this problem using promises, but the line
return Parse.Object.saveAll(foodListCorrected);
does not seem to be executing. I've verified that foodListCorrected is a non-empty array. Below is the entire code for the function.
Parse.Cloud.define("recordFavorite", function(request, response) {
var foodList = request.params.foodList; //string array of food names
var foodListCorrected = new Array();
var Food = Parse.Object.extend("Food");
var query = new Parse.Query(Food);
query.find().then(function(foods) {
for (i = 0; i < foodList.length; i++) {
var j;
for (j = 0; j < foods.length; j++){
if (foodList[i] == foods[j])
break;
}
if (j==foods.length)
foodListCorrected.push(foodList[i]);
}
console.log(foodListCorrected.length);
return Parse.Object.saveAll(foodListCorrected);
}).then(function() {
// Everything is done!
})
});
Try this:
Parse.Cloud.define("recordFavorite", function(request, response) {
var foodList = request.params.foodList; //string array of food names
var saveThese = [];
var FoodClass = Parse.Object.extend("Food");
for(var i = 0; i < foodList.length; ++i){
var food = new FoodClass();
food.set("name", foodList[i]);
saveThese.push(food);
}
Parse.Object.saveAll(saveThese, {
success: function(list){
response.success();
},
error: function(error){
response.error("Failure on saving food");
}
});
});
//If a food already exists in the database, then don't save it
Parse.Cloud.beforeSave("Food", function(request, response){
var query = new Parse.Query("Food");
query.equalTo("name", request.object.get("name"));
query.count({
success: function(count){
if(count > 0)
response.error("Food already exists");
else
response.success();
},
error: function(error){
response.error(error);
}
});
});
The "exists" condition takes in one argument, the name of a key and sees if it exists for a row. So it will return every row where your "name" column has a value, any value. What you're looking for is something like this:
var query = new Parse.Query(Food);
query.equalTo("name", name);
query.first(...)

Categories