I'm trying to make a small page that runs a survey. I'd like the survey to be repeatable within the page, but the user needs to enter a login name when they enter the page. I'm attempting to write code such that they fill out the login, and then the survey begins. I'm trying to have a JSON that feeds in 100+ random images, sending in a new one each time the user completes the survey application.
So, whats happening is every time the start function is called, the survey function runs. However, it only runs for around 1 second, rather than the continuous running I'd like to have. When I've played with the ordering of the page and added timers, I've managed to get it such that the survey runs a single time but does not reset itself upon completion. It also doesn't seem to be picking up variables from the other function - I wanted the "count" variable to increase as the survey is repeatedly completed. It also isn't picking up the username variable, which is created inside of the outside "start" function.
I think my problem here has to do with not understanding how functions and variables are supposed to be nested inside of each other, and with how asynchronicity works in Javascript. Can anyone point me in the right direction? Here's a JSfiddle for the problem, and a code snippit:
//button Login
function serv (){
Survey
.StylesManager
.applyTheme("modern");
window.survey = new Survey.Model(json);
survey
.onComplete
.add(function (result) {
count ++;
var PID = username;
var results = PID + "|||" + (keyname) + ":\n" + JSON.stringify(result.data, null, 3) + (count) ;
document
.querySelector('#surveyResult')
.textContent = results;
survey.clear();
survey.render();
});
$("#surveyElement").Survey({model: survey});
}
function start() {
var username = document.getElementById("user_PID").value;
alert("your PID is " + username);
modal.style.display = "none";
serv();
}
var knlist = {}
var count = 13
var knx = ("kn" + count)
var keyname = (knlist[knx])
var mapilink = "https://images.mapillary.com/" + (keyname) + "/thumb-1024.jpg";
var json = {}
var modal = document.getElementById('id01');
Related
Beginner learning from forums websites and youtube, bear with me pls.
(plus im dumb)
I'm making a stupid clicker game just to see if i can do it (clearly not).
I've got some buttons with onclick functions and multipliers setup whatever everything works fine.
Until Saving/Loading.
I followed a tutorial i found for the save function, to save/load your progress via localStorage/cookies, and it's saving the total "money" (score) upon refresh, but my "scorepersecond" and every upgrade via button doesn't save, even though i've included their cost and name values to tell which variables i want to save. I'm using VS Code with Live Server extension to test (firefox).
function loadGame() {
var savedGame = JSON.parse(localStorage.getItem("gameSave", "score", "scorepersecond", "cursors", "cursorcost", "lighters", "lightercost", "grinders", "grindercost", "devils", "devilcost", "trays", "traycost", "dealers", "dealercost"));
if (typeof savedGame.score !== "undefined") score = savedGame.score;
}
function saveGame() {
var gameSave = {
score: score,
scorepersecond: scorepersecond,
clickingPower: clickingPower,
cursors: cursors,
cursorcost: cursorcost,
lighters: lighters,
lightercost: lightercost,
grinders: grinders,
grindercost: grindercost,
devils: devils,
devilcost: devilcost,
trays: trays,
traycost: traycost,
dealers: dealers,
dealercost: dealercost,
};
localStorage.setItem("gameSave", JSON.stringify(gameSave));
document.getElementById("score").innerHTML = score;
document.getElementById("scorepersecond").innerHTML = scorepersecond;
document.getElementById("cursorcost").innerHTML = cursorcost;
document.getElementById("cursors").innerHTML = cursors;
document.getElementById("lightercost").innerHTML = lightercost;
document.getElementById("lighters").innerHTML = lighters;
document.getElementById("grindercost").innerHTML = grindercost;
document.getElementById("grinders").innerHTML = grinders;
document.getElementById("devilcost").innerHTML = devilcost;
document.getElementById("devils").innerHTML = devils;
document.getElementById("traycost").innerHTML = traycost;
document.getElementById("trays").innerHTML = trays;
document.getElementById("dealercost").innerHTML = dealercost;
document.getElementById("dealers").innerHTML = dealers;
}
window.onload = function() {
loadGame();
updatescorepersecond();
document.getElementById("score").innerHTML = score;
document.getElementById("cursorcost").innerHTML = cursorcost;
document.getElementById("cursors").innerHTML = cursors;
document.getElementById("lightercost").innerHTML = lightercost;
document.getElementById("lighters").innerHTML = lighters;
document.getElementById("grindercost").innerHTML = grindercost;
document.getElementById("grinders").innerHTML = grinders;
document.getElementById("devilcost").innerHTML = devilcost;
document.getElementById("devils").innerHTML = devils;
document.getElementById("traycost").innerHTML = traycost;
document.getElementById("trays").innerHTML = trays;
document.getElementById("dealercost").innerHTML = dealercost;
document.getElementById("dealers").innerHTML = dealers;
};
Thing's I've Tried.
function loadGame() {
var savedGame = JSON.parse(localStorage.getItem("gameSave"));
if (typeof savedGame.score !== "undefined") score = savedGame.score;
}
function loadGame() {
var savedGame = JSON.parse(localStorage.getItem("gameSave"));
if (typeof savedGame.score !== "undefined") score = savedGame.score;
if (typeof savedGame.scorepersecond!== "undefined") scorepersecond = savedGame.scorepersecond;
}
along with other variables i want to save, in the form of "(typeof " which have also failed.
Not sure if this bit literally means anything, but if i inspect element on the page and access local storage it updates accordingly every 30 seconds with proper values, but upon page refresh it poof's (except for total "money" (score) on top of the page).
Not sure what people need to see or if i shared enough, but if anyone could help without being a d-bag that'd be cool :) even if not to solve it but a general idea of where i f'd up besides the whole thing. thanks in advance and lmk if you need to see more of my poopy clicker game.
You can only get one value with getItem().
If you want to get the json object of all values, simply use localStorage.
A Storage object which can be used to access the current origin's local storage space.
var savedGame = localStorage;
Refernce:
getItem()
localStorage
I have created a timer with javascript which is started when the user begins a game, and stops when the game is completed. I would like to be able to record the users best time and save it using local storage. The code below shows my function which is fired on completion of the game, and works as far as displaying the user's best time on the page, however local storage is not retaining the variable, userBestTime, after the page is reloaded. Any help would be much appreciated.
function stop() {
clearInterval(timer);
timer = false;
$(stopwatchEl).addClass('endgame');
let timeTaken = stopwatchEl.textContent;
let timeInMs = ((Number(timeTaken.split(':')[0])*60000) +
(Number(timeTaken.split(':')[1])*1000) +
(Number(timeTaken.split(':')[2])));
let bestTime = 9999999;
if (timeInMs < bestTime) {
bestTime = timeTaken;
}
localStorage.setItem('bestTime', JSON.stringify(bestTime));
let jsonString = localStorage.getItem('bestTime');
let userBestTime = JSON.parse(jsonString);
$('.best-time').html('Best Time: ' + userBestTime);
console.log(userBestTime);
}
I am trying to create a leaderboard when someone completes my quiz. I can get the person to enter their name via a prompt with their score when they complete quiz. I just can get the data to stay. I think I need to store the data with storage? Or is it there a better way to do this?
I added my code to codepen since it's kind of long:
https://codepen.io/rob-connolly/pen/xyJgwx
Edit: fixed broken codepen link
// variables
var score = 0; //set score to 0
var total = 10; //total nmumber of questions
var point = 1; //points per correct answer
var highest = total * point;
//init
console.log('script js loaded')
function init() {
//set correct answers
sessionStorage.setItem('a1', "b");
sessionStorage.setItem('a2', "a");
sessionStorage.setItem('a3', "c");
sessionStorage.setItem('a4', "d");
sessionStorage.setItem('a5', "b");
sessionStorage.setItem('a6', "d");
sessionStorage.setItem('a7', "b");
sessionStorage.setItem('a8', "b");
sessionStorage.setItem('a9', "d");
sessionStorage.setItem('a10', "d");
}
//hide all questions to start
$(document).ready(function() {
$('.questionForm').hide();
//show question 1
$('#question1').show();
$('.questionForm #submit').click(function() {
//get data attribute
current = $(this).parents('form:first').data('question');
next = $(this).parents('form:first').data('question') + 1;
//hide all questions
$('.questionForm').hide();
//show next question in a cool way
$('#question' + next + '').fadeIn(400);
process('' + current + '');
return false;
});
});
//process answer function
function process(n) {
// get input value
var submitted = $('input[name=question' + n + ']:checked').val();
if (submitted == sessionStorage.getItem('a' + n + '')) {
score++;
}
if (n == total) {
$('#results').html('<h3>Your score is: ' + score + ' out of ' + highest + '!</h3> <button onclick="myScore()">Add Your Name To Scoreboard!</a>')
stop()
}
return false;
}
window.yourPoints = function() {
return n;
}
function myScore() {
var person = prompt("Please enter your name", "My First Name");
if (person != null) {
document.getElementById("myScore").innerHTML =
person + " " + score
}
}
var x;
var startstop = 0;
window.onload = function startStop() { /* Toggle StartStop */
startstop = startstop + 1;
if (startstop === 1) {
start();
document.getElementById("start").innerHTML = "Stop";
} else if (startstop === 2) {
document.getElementById("start").innerHTML = "Start";
startstop = 0;
stop();
}
}
function start() {
x = setInterval(timer, 10);
} /* Start */
function stop() {
clearInterval(x);
} /* Stop */
var milisec = 0;
var sec = 0; /* holds incrementing value */
var min = 0;
var hour = 0;
/* Contains and outputs returned value of function checkTime */
var miliSecOut = 0;
var secOut = 0;
var minOut = 0;
var hourOut = 0;
/* Output variable End */
function timer() {
/* Main Timer */
miliSecOut = checkTime(milisec);
secOut = checkTime(sec);
minOut = checkTime(min);
hourOut = checkTime(hour);
milisec = ++milisec;
if (milisec === 100) {
milisec = 0;
sec = ++sec;
}
if (sec == 60) {
min = ++min;
sec = 0;
}
if (min == 60) {
min = 0;
hour = ++hour;
}
document.getElementById("sec").innerHTML = secOut;
document.getElementById("min").innerHTML = minOut;
// document.getElementById("hour").innerHTML = hourOut;
}
/* Adds 0 when value is <10 */
function checkTime(i) {
if (i < 10) {
i = "0" + i;
}
return i;
}
function reset() {
/*Reset*/
milisec = 0;
sec = 0;
min = 0
hour = 0;
document.getElementById("milisec").innerHTML = "00";
document.getElementById("sec").innerHTML = "00";
document.getElementById("min").innerHTML = "00";
document.getElementById("hour").innerHTML = "00";
}
//adding an event listener
window.addEventListener('load', init, false);
]2]2
localStorage, as the name suggests is local - the data will only be accessible in the browser it's saved in. sessionStorage is also local. Generally anything that doesn't rely on a server will be local.
To store and display the data across multiple clients, you will need a server. What you need in this case is a simple back end that will provide two endpoints - one that will display the scoreboard (GET) and another that will save the data into the scoreboard (POST). There are many options you can use to create that, if you're familiar with node.js you could try express and sequelize with sqlite (if you need a database) or you could store the data in a text (CSV) file.
To retrieve the data from the web app you will need to use AJAX, if you want an easy way to make HTTP requests from JS try fetch - it's available in all modern browsers. Make sure to configure CORS properly on the server - this will cause some headaches in the beginning but a value of * for Access-Control-Allow-Origin is generally fine for projects like that.
The general flow would be like this:
After your web app is opened, the JS will fetch /scores (without any options).
Whenever there's a need to store a score you would fetch /scores/create with method: 'POST' and body: JSON.stringify(scoreObject).
Here's an example on how to get data from fetch:
async function getScores() {
try {
const res = await fetch('http://localhost:8080/scores');
const json = await res.json();
// json will contain your scores
} catch (e) {
// Something went wrong.
console.log(e); // Check console for more details.
}
}
It may sound extremely difficult at first but once you start working on this everything will start to make sense.
To reiterate:
Make a back end and host it somewhere. Make sure to configure CORS.
Use fetch to get your data to (and from) your page.
Keep on experimenting, that's the best way to learn.
You will need to host the site somewhere in order for multiple users to share application state. The "Local Storage" API's are out of the question, unfortunately.
Read up on web storage API's here: https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API
As soon as you have the need to persist data across multiple browsers and users you have now entered some fiery challenges. There's a thousand ways to solve this one. Some of the concerns to consider are:
Security: How will you be able to securely store each users' data and know which requests come from which user?
Storage: The data has to live somewhere outside of any individual users browser. Thus, you will need some sort of hosting.
What about when you need to update the quiz? What happens to old completed quizzes? Will they be schema-compatible? Data migration is... lovely.
I would suggest the following study:
Figure out a way to persist your web application data. This means you will need to either host or setup an account with a provider such as Amazon, Google or Microsoft Azure where you can host your data.
For simple testing you can use the AJAX API's (the fetch thing mentioned before), or it is worth spending some time studying up on modern frameworks such as Angular, React or Vue.
If you feel the momentum while grappling with AJAX or one of the web UI frameworks, then these links might help:
https://aws.amazon.com/serverless/build-a-web-app/
https://aws.amazon.com/websites/
https://firebase.google.com/docs/web/setup
https://azure.microsoft.com/en-us/services/app-service/web/
Ultimately there are a TON of options here... these are just a few approaches to solving the problem. You can setup your own VM, you can use a myriad of "serverless" options, you can create hosted "functions" with persistence... look around a bit.
The most important thing I would suggest learning is how data is stored in backend databases for web applications. Check out the free options for some of the major services. They almost all have an option for using their services for free as long as you don't exceed monthly thresholds. Even after those thresholds are met, it's really not that expensive to have a hosted web application with some sort of database back-end.
It may sound daunting but it might be worth considering grabbing a good book on building web applications. Something using .NET Core, Python or node.js makes a reasonable back-end for API code. It really comes down to whatever you're comfortable with.
Ask some specific questions on here once you latch on to something specific and I'm sure the community will be happy to help.
Good luck!
I am making a ticket generator using javascript. I am using firebase to give the users a code that has already been stored on the database. my database is layed out like this:
"qrcodes" : {
"23KU8877" : {
"email" : "person#email.com",
"ticketgenerated" : "true"
},
"288RX9U5" : {
"email" : "person2#email.com",
"ticketgenerated" : "true"
}
}
my script allows me to get the first code in the qrcodes list and then move it to another database where another website processes it. But I was wanting to find a way that will make a function take a new snapshot everytime it is run.
The functions that grab the data from firebase are here:
function generatehtml(){
ticketname = document.getElementById('name').value;
ticketemail = document.getElementById('email').value;
adultnumber = document.getElementById('adults').value;
childnumber = document.getElementById('child').value;
while (functionruncount < inputnumber){
grabfirebasecode();
}
}
function grabfirebasecode(){
ref.limitToFirst(1).once('value', function(snapshot) {
for(key in snapshot.val()){
genvar = snapshot.child(key + "/ticketgenerated" ).val();
var genvarpath = "test/" + key + "/ticketgenerated";
if (genvar === "false"){
snapshot.forEach(function(childSnapshot) {
ref.child(childSnapshot.key).remove();
});
ref2.child(key).set({
email: ticketemail,
ticketgenerated: "true",
});
createticket();
}
}
});
functionruncount ++;
}
so if the code above runs succesully and grabs the first child of the qrcode list (e.g "23KU8877"), it will stay the same no matter how many times the function loops.
I am not sure how to fix this. Any help would be appreciated.
Thanks,
Daniel Martinez
You're attaching a same listener multiple times in a tight loop. All those listeners start at pretty much the same time, and thus all see the same value from the database. To get a next code, you must be sure to only start reading the next code after you've deleted the previous one. A common way to do this is with a recursive function:
function generatehtml(){
ticketname = document.getElementById('name').value;
ticketemail = document.getElementById('email').value;
adultnumber = document.getElementById('adults').value;
childnumber = document.getElementById('child').value;
grabfirebasecode(inputnumber);
}
function grabfirebasecode(inputnumber){
if (inputnumber > 0) {
ref.limitToFirst(1).once('value', function(snapshot) {
for(key in snapshot.val()){
genvar = snapshot.child(key + "/ticketgenerated" ).val();
var genvarpath = "test/" + key + "/ticketgenerated";
if (genvar === "false"){
var promises = [];
snapshot.forEach(function(childSnapshot) {
promises.push(ref.child(childSnapshot.key).remove());
});
promises.push(
ref2.child(key).set({
email: ticketemail,
ticketgenerated: "true",
})
);
Promise.all(promises).then(function() {
grabfirebasecode(inputnumber-1);
});
createticket();
}
}
});
}
}
So this code builds an array of promises, one for each database operation that happen asynchronously. When all those operations completes, it calls itself again with one lover number.
If your createticket() also performs asynchronous operations, you might want to also include it in the promises array so that its work is completed before the next iteration starts.
I am developing my app, and one of the features will be messaging within the application. What I did, is I've developed 'send message' window, where user can send message to other user. The logic behind it is as following:
1. User A sends message to User B.
2. Firebase creates following nodes in 'Messaging':
"Messaging"->"User A"->"User B"->"Date & Time"->"UserA: Message"
"Messaging"->"User B"->"User A"->"Date & Time"->"UserA: Message"
Here is the code that I am using for sending messages:
sendMsg: function(receiver, content) {
var user = Auth.getUser();
var sender = user.facebook.id;
var receiverId = receiver;
var receiverRef = $firebase(XXX.firebase.child("Messaging").child(receiverId).child(sender).child(Date()));
var senderRef = $firebase(XXX.firebase.child("Messaging").child(sender).child(receiverId).child(Date()));
receiverRef.$set(sender,content);
senderRef.$set(sender,content);
},
(picture 1 in imgur album)
At the moment, I am trying to read the messages from the database, and sort them in according to date. What I've accomplished so far, is that I have stored the content of "Messaging/UserA/" in form of an Object. The object could be seen in the picture I've attached (picture 2).
http://imgur.com/a/3zQ0o
Code for data receiving:
getMsgs: function () {
var user = Auth.getUser();
var userId = user.facebook.id;
var messagesPath = new Firebase("https://xxx.firebaseio.com/Messaging/");
var Messages = messagesPath.child(userId);
Messages.on("value", function (snapshot) {
var messagesObj = snapshot.val();
return messagesObj;
}, function (errorObject) {
console.log("Error code: " + errorObject.code);
});
}
My question is: how can I read the object's messages? I would like to sort the according to the date, get the message and get the Id of user who has sent the message.
Thank you so much!
You seem to be falling for the asynchronous loading trap when you're reading the messages:
getMsgs: function () {
var user = Auth.getUser();
var userId = user.facebook.id;
var messagesPath = new Firebase("https://xxx.firebaseio.com/Messaging/");
var Messages = messagesPath.child(userId);
Messages.on("value", function (snapshot) {
var messagesObj = snapshot.val();
return messagesObj;
}, function (errorObject) {
console.log("Error code: " + errorObject.code);
});
}
That return statement that you have in the Messages.on("value" callback doesn't return that value to anyone.
It's often a bit easier to see what is going on, if we split the callback off into a separate function:
onMessagesChanged(snapshot) {
// when we get here, either the messages have initially loaded
// OR there has been a change in the messages
console.log('Inside on-value listener');
var messagesObj = snapshot.val();
return messagesObj;
},
getMsgs: function () {
var user = Auth.getUser();
var userId = user.facebook.id;
var messagesPath = new Firebase("https://xxx.firebaseio.com/Messaging/");
var Messages = messagesPath.child(userId);
console.log('Before adding on-value listener');
Messages.on("value", onMessagesChanged);
console.log('After adding on-value listener');
}
If you run the snippet like this, you will see that the console logs:
Before adding on-value listener
After adding on-value listener
Inside on-value listener
This is probably not what you expected and is caused by the fact that Firebase has to retrieve the messages from its servers, which could potentially take a long time. Instead of making the user wait, the browser continues executing the code and calls your so-called callback function whenever the data is available.
In the case of Firebase your function may actually be called many times, whenever a users changes or adds a message. So the output more likely will be:
Before adding on-value listener
After adding on-value listener
Inside on-value listener
Inside on-value listener
Inside on-value listener
...
Because the callback function is triggered asynchronously, you cannot return a value to the original function from it. The simplest way to work around this problem is to perform the update of your screens inside the callback. So say you want to log the messages, you'd do:
onMessagesChanged(snapshot) {
// when we get here, either the messages have initially loaded
// OR there has been a change in the messages
console.log('Inside on-value listener');
var i = 0;
snapshot.forEach(function(messageSnapshot) {
console.log((i++)+': '+messageSnapshot.val());
});
},
Note that this problem is the same no matter what API you use to access Firebase. But the different libraries handle it in different ways. For example: AngularFire shields you from a lot of these complexities, by notifying AngularJS of the data changes for you when it gets back.
Also see: Asynchronous access to an array in Firebase