I am trying to get a current score to add up every time an answer is correct, what is happening is that I have the questions in a pagination set up and when this answer is correct it give me the score but then when it goes to the next page it refresh the score and if I got that one right it just give me the score for that one again but it doesn't add up.
JS code:
$(function() {
$('#author').on('change', function(event) {
var opt = this.options[ this.selectedIndex ];
var correct = $(opt).text().match (arr2);
var score = 0;
if (correct){
alert('Good job ' + arr2,);
score += 2;
alert (score);
currentScore = score++;
alert(currentScore);
display(currentScore);
}
else {
alert ('nice try ' + arr2);
}
});
});
Here is another option - local storage.
Here is a reference W3School Web storage
It's not the most ideal solution, but it can meet your criteria.
let score = localStorage.getItem('score')
score++;
localStorage.setItem('score', score);
Your pages will be able to access the localStorage so you can get the value of score and re-set it.
Hopefully the reference can answer further questions, else leave a comment!
Con: It may not be supported by all browsers.
EDIT:
Here is an example with your code.
$(function() {
let currentScore = localStorage.getItem('score'); // get score
if (currentScore === null){ // if score doesnt exist yet
localStorage.setItem('score', 0); // set score
currentScore = 0; // make currentScore 0
}
$('#author').on('change', function(event) {
var opt = this.options[ this.selectedIndex ];
var correct = $(opt).text().match (arr2);
if (correct){
alert('Good job ' + arr2);
currentScore += 2; //increment current score by 2
alert (currentScore);
localStorage.setItem('score', currentScore); // set the item again with new value
alert(currentScore);
display(currentScore);
}
else {
alert ('nice try ' + arr2);
}
});
});
Edit 2:
let currentScore = localStorage.getItem('score'); // get score
currentScore = parseInt(currentScore);
it give me the score but then when it goes to the next page it refresh the score and if I got that one right it just give me the score for that one again but it doesn't add up.
I think your problem is there.
If I understand correctly, when the answer is good, the page refresh and passes to the next question. Your problem is that the score doesn't add up to the previous one.
The score variable is only stored in the current page, like a temporary one. Without saving the score on the server, via ajax or another method, and getting it on the next page, it will not add up. Indeed, score will have a value of 0 due to the refresh.
A simple schema :
score = 0 -> correct answer -> +50 point -> score = 50 -> next page -> score = 0
As you can see, because the javascript you wrote is not assuring the persistance of your information, the previously stored score is lost.
You need to send the score on the server and then get it back when the new page is loaded or to avoid changing page and make your quizz on one and only page, without refreshing.
Keep in mind that everytime you are refresing a page, the javascript is starting again and therefore everything done before is lost.
I hope this was helpful.
Ps: You should place your code in the $( document ).ready(); block just like this :
$( document ).ready(function() {
console.log( "ready!" );
});
It will make your code start when the html DOM (the structure of the html file) is loaded and ready to be manipulated. It can avoid a lot of errors.
Edit2 : What it will look like in your code :
$( document ).ready(function() {
$('#author').on('change', function(event) {
var opt = this.options[ this.selectedIndex ];
var correct = $(opt).text().match (arr2);
var score = 0;
if (correct){
alert('Good job ' + arr2,);
score += 2;
alert (score);
currentScore = score++;
alert(currentScore);
display(currentScore);
}
else {
alert ('nice try ' + arr2);
}
});
});
Or, to make this more readable and to avoird having a lot of things in the document.ready block (when you will have a lot of lines/functions) :
$( document ).ready( myNiceFunction() );
var myNiceFunction = function(){
$('#author').on('change', function(event) {
var opt = this.options[ this.selectedIndex ];
var correct = $(opt).text().match (arr2);
var score = 0;
if (correct){
alert('Good job ' + arr2,);
score += 2;
alert (score);
currentScore = score++;
alert(currentScore);
display(currentScore);
}
else {
alert ('nice try ' + arr2);
}
}
Ps2 : I know this is not the best website to explain it but I think it is simple enough to make you understand the principle of ajax without losing you into a bunch of technical stuff : here and here
Edit : Grammar and second post-scriptum.
Not sure how you're doing pagination but it should be ajaxed, instead of a full postback, so you don't lose the values on your page.
Related
I'm sure this question has been answered, before, but my searches are coming up empty.
I have a simple jQuery function (that slides in a box after the page has been scrolled down). It works fine.
However, how do I set cookies, or other method, to make it execute on the first page load and, then, on every 3rd page load of the session, after that?
A little snippet like this should work for you.
(function () {
// Get the countdown from localStorage
var countdown = Number(window.localStorage.getItem('countdown'));
// If countdown isn’t set it or if it has
// run a couple times it’ll be `0`
// Either way—we reset countdown and run the function
if (!countdown) {
countdown = 3;
// Run the function
}
// Update the countdown
window.localStorage.setItem('countdown', countdown - 1);
})();
These are both very instructive answers (my javascript skill is at the piece-it-together level). If it's helpful to someone, even though the question was for a javascript solution, I realized there might be a PHP solution, as well.
This worked, too:
<?php //Slide-in ad will show every x pages
$slide_ad_frequency=3;
session_start();
//increase the already-set counter by 1 or initiate the counter with a value of 1
if( isset( $_SESSION['counter'] ) )
{
$_SESSION['counter'] += 1;
}
else
{
$_SESSION['counter'] = 1;
}
//If counter equals the ad frequency setting
if($_SESSION['counter'] % $slide_ad_frequency == 0) : ?>
... Code to execute ...
<?php endif ?>
You can store the count of window loads on the sessionStorage so that data won't be lost on every reload. The data will be cleared when the tab is closed. If you want your data to not expire when the session ends, you should instead use localStorage; both have the same implementation.
window.onload = doSomething;
function doSomething() {
let count = sessionStorage.getItem('noOfPageLoads');
if( count ) { //if count is not null, increment it
count++;
sessionStorage.setItem('noOfPageLoads', count); //update the local storage
}
else { //if count is null, it's the first load, so put it in the local storage
count = 0;
sessionStorage.setItem('noOfPageLoads', count);
}
console.log('noOfPageLoads = '+ count)
if( count===0 || count===3 ) {
console.log('do something now');
//do what you want here
}
}
I will like to achieve something in a quiz system.
Right about now I have a quiz system that works perfectly well. It closes the quiz after 10:00 min is elapsed.
But what I want now is, for each of the question there should be a timer.
So Question 1 would have 10 secs, Question 2 would also have 10 secs down to Question 20.
So when you fail to answer any question within ten seconds, it automatically takes you to the next question.
Right about now, what happens is that you must click on the next question button before it takes you to the next question, which is what I want to change.
Below is the code that does the timer and submit after 10 min
<script>
//function that keeps the counter going
function timer(secs){
var ele = document.getElementById("countdown");
ele.innerHTML = "Your Time Starts Now";
var mins_rem = parseInt(secs/60);
var secs_rem = secs%60;
if(mins_rem<10 && secs_rem>=10)
ele.innerHTML = " "+"0"+mins_rem+":"+secs_rem;
else if(secs_rem<10 && mins_rem>=10)
ele.innerHTML = " "+mins_rem+":0"+secs_rem;
else if(secs_rem<10 && mins_rem<10)
ele.innerHTML = " "+"0"+mins_rem+":0"+secs_rem;
else
ele.innerHTML = " "+mins_rem+":"+secs_rem;
if(mins_rem=="00" && secs_rem < 1){
quiz_submit();
}
secs--;
//to animate the timer otherwise it'd just stay at the number entered
//calling timer() again after 1 sec
var time_again = setTimeout('timer('+secs+')',1000);
}
</script>
<script>
setTimeout(function() {
$("form").submit();
}, 600000);
</script>
Here is the code that does the onclick to next question
<script type="text/javascript">
$('.cont').addClass('hide');
count=$('.questions').length;
$('#question'+1).removeClass('hide');
$(document).on('click','.next',function(){
last= parseInt($(this).attr('id'));
nex = last+1;
$('#question'+last).addClass('hide');
$('#question'+nex).removeClass('hide');
});
$(document).on('click','.previous',function(){
last = parseInt($(this).attr('id'));
pre = last-1;
$('#question'+last).addClass('hide');
$('#question'+pre).removeClass('hide');
});
setTimeout(function() {
$("form").submit();
}, 120000);
</script>
Please note that I fetch my questions with Php Mysqli
Initialize a timeout into a variable at start. The callback should simulate a click on the next button. Use .click() to simulate. It will execute all click event listeners associated to the button.
You also have to reset the timer when button is clicked (manually or not).
EDIT: After discussing by comments, I guess that you have <button.next> tags for each question in your HTML, with a numeric ID. So I propose you to stock in a variable your current progression.
// Initializes
let currentQuestion = 1;
let question_timer = setTimeout(question_timeout_callback, 10000);
// Function which simulates the click.
function question_timeout_callback() {
// Simulates
$(document).find(`#${currentQuestion}`).click();
}
// your code...
// And in your click event listener:
$(document).on('click','.next', function () {
// Resets timer
clearTimeout(question_timer);
question_timer = setTimeout(question_timeout_callback, 10000);
// Update question tracking
currentQuestion++;
// your code...
});
// Do NOT forget to update .previous buttons with "currentQuestion--"
Now, do not forget to ask yourself how you will handle the possibility to come back to the previous question.
i would suggest different approach.
first, take the time-counting to the backend of your application (so user can't tamper with it).
when user begins quiz, save start time and user identifier into db.
implement timeout (2s interval?) to ask backend, how much time is left.
create simple script which loads remaining time from db (calculates how much time remains for current question) and returns it to the frontend.
php:
<?php
$user = (int) $_GET['user'];
$questionNumber = (int) $_GET['question'];
//connect to the db
//select eg. with PDO
$st = $db->prepare('SELECT start_time FROM quiz_completion WHERE user_id = :user');
$st->bindParam(':user', $user, PDO::PARAM_INT);
$startTimeRow = $sth->execute();
//calculate remaining time
$elapsed = time() - $startTimeRow['start_time'];
$borderTime = 10 * $questionNumber;
echo $borderTime - $elapsed;
exit(0);
with mocked GET & db: https://3v4l.org/MId0K
then in js just call this script with user identifier and question number. when less than zero is returned, move user to the next question.
js:
$.ajax('http://localhost/your_php_script.php?user='+user+'&question='+questionNumber).done(
function(response){
if (response < 0) {
//move to the next q.
} else {
//show remaining time?
}
});
with asking backend to get time, there is risk of waiting too long for an answer from php (when many users are completing the poll)
I'm writing a choose your own adventure program where If a specific option is chosen (example to wait) the user gets a random number between 1-10 to do push ups(the push-ups would be the user clicking on the prompt "ok" button however many times the random number is equal to) here's my code so far but I keep getting errors. I'm a complete noob so go easy on me.
var count = Math.floor((Math.random() * 10) + 1);
var setsOf10 = false;
function pushUps() {
alert("Nice! Lets see you crank out " + pushUps + "!");
}
if (setsOf10 == pushUp) {
alert("Nice! Lets see you crank out " + pushUp + "!");
setsOf10 = true;
}
for (var i=0; i<count; i++){
pushUps();
}
else {
alert("Really, thats it? Try again");
}
while ( setsOf10 == false);
}
After playing with this some more I can tell i'm close but still don't have it. and again, I'M NOT ASKING YOU TO SOLVE THIS FOR ME JUST NEED POINTERS AS TO WHAT IM DOING WRONG OR MISSING. Here's what I have, Its giving me my random number I just need it to allow me to click the "ok" button however many times the random number has assigned me.
var pushUpSets = Math.floor((Math.random() * 10) + 1);
function pushUps(){
alert(pushUpSets);
if (pushUpSets < 3){
var weak = "Thats it? Weak sauce!";
alert(weak);
}
else{
alert("Sweet lets get some reps in!");
}
for (i=0; i>3; i++){
pushUps(pushUpSets);
}
}
Here, the make a choice button is just dummy to allow us to go to do push ups. Each click decrements our count.
// This is important, we use this event to wait and let the HTML (DOM) load
// before we go ahead and code.
document.addEventListener('DOMContentLoaded', () => {
document.querySelector('#choice').addEventListener('click', makeChoice);
});
function makeChoice() {
// Call a method to set random pushups and setup the click event
setUpPushUp();
// Here we change the display style of the push up section so that it shows to the player.
document.querySelector('.activity').style.display = 'block';
}
// The pushups variable is declared at the document level
// This way our setUpPushUp and doPushUp functions have easy access.
let pushUps = 0;
function setUpPushUp() {
// Create a random number of pushups, in sets of 10.
// We add an extra 1 so we can call the doPushUp method to initialize.
pushUps = (Math.floor((Math.random() * 10)+1)*10)+1 ;
// Add a click event to the push up button and call our doPushUp method on each click.
document.querySelector('#push').addEventListener('click', doPushUp);
// This is just an init call, it will use the extra 1 we added and place test in our P tag.
doPushUp();
}
function doPushUp() {
// Get a reference to our output element, we will put text to player here.
let result = document.querySelector('p');
// They have clicked, so remove a push up.
pushUps--;
// See if the player has done all the required push ups (i.e. pushUps is 0 or less.)
if (pushUps > 0) {
result.innerText = `You need to crank out ${pushUps} pushUps`;
} else {
result.innerText = 'Nice work!';
}
}
.activity {
display: none;
}
<button id="choice">Make a choice !</button>
<div class="activity">
<p></p>
<button id="push">Push</button>
</div>
So far I have created a basic number guessing game,the number is currently set to 50 for testing purposes. I would like to know how to add a loop so the user can guess again. I would also like to see the previous guesses on the screen. So it would should something like:
Number Guessing Game!
Guess #1 : 49 was LOW
Guess #2 : 51 was HIGH
Guess #3 : 50 was CORRECT
For the loop i know i need to use something like "while( !guessed )" but not sure how to implement it at all, i'm pretty new to this, any help would be fantastic!
var canvas;
canvas = openGraphics();
var max;
max = 100;
var numberToGuess;
numberToGuess = 50; // will become Math.floor( Math.random() * max ) + 1; later //
canvas.setFont("comic sans ms", "15px", Font.Bold);
canvas.drawString("Number Guessing Game!");
var guess;
guess = prompt( "Please input your first guess" );
if(guess > numberToGuess){
var message1;
message1 = " was HIGH";
var messageanswer;
messageanswer = "Guess #1 : " + guess + message1;
canvas.drawString(messageanswer, 20,20);
}
if (guess < numberToGuess){
var message2;
message2 = " was LOW";
var messageanswer2;
messageanswer2 = "Guess #1 : " + guess + message2;
canvas.drawString(messageanswer2, 20,20);
}
if (guess == numberToGuess){
var message3;
message3 = " was CORRECT";
var messageanswer3;
messageanswer3 = "Guess #1 : " + guess + message3;
canvas.drawString(messageanswer3, 20,20);
}
canvas.paint();
You're correct, you need to use a type of while loop to continuously allow input until the number is guessed.
Remember, you'll want to use a dowhile loop, because you want the condition to be checked after the code runs, not before.
Something like this would work:
var guess;
var numberToGuess = 50;
do {
// check previous guess and alert low/high message
if ( guess ) {
if ( guess > numberToGuess ) {
alert( "Your guess was too high." );
}
else {
alert( "Your guess was too low." );
}
}
guess = prompt( "Please input your guess" );
} while ( guess != numberToGuess );
alert( "You guessed correctly!" );
Obviously you can add your own counter and message if you'd like, but this should get you on the right track.
I think the best way in context of this is to wrap your code like this
function guess()
{
if(guess > numberToGuess)
{ }
if (guess < numberToGuess)
{ }
if (guess == numberToGuess)
{
...
return;
}
else guess();
}
There is a problem with loops in JavaScript: The UI is dead while they run. So you need to start thinking in "events" and "event handlers".
The idea is that you update the UI or the DOM to display the current state of the game. Part of the UI is a text entry field where the user can enter the next guess. Next should be a button "Am I right?". These two elements replace the prompt.
You can now add an event / click handler to the button. In the handler, you read the input and check it. If it's wrong, you update the UI.
If it's correct, you hide the text field and the button. Instead you display some kind of "You won!" screen plus a button to restart the game.
Again, the code should end with that. The click handler for the win button should reset the UI to the original state.
I'm trying to work through an assignment to further my understanding of js but I'm running into some issues that are keeping me from final code. The code executes a short quiz- inputs from radio buttons are taken in and matched to an object containing answers, then outputting a final score.
code at http://jsfiddle.net/8ax9A/3/
issues I'm aware of now :
my $response variable doesn't seem to work.
var $response = $('[name=rad]:checked').val();
counter is listening for clicks through questions. After the last question, I want to report final score. I can't get counter to reach the end of questions + 1, and I cant get an accurate final score listener reported (var finalScore).
if ($response == parseInt(questions[counter].answer, 10)) {
finalScore++;
}
Those are just snippets so check out the fiddle for full code. I'd love some suggestions on how to understand where I'm going wrong.
Here is one way you could do it:
//Initialization
var counter=0;
var score=0;
loadQuestion();
$('#next').on('click',answer);
//functions
function answer(){
// if the user did not answer
if ($('input:radio:checked').length == 0){
alert('You have to answer!');
return;
}
var currentQ=questions[counter];
// if answer is correct
if($('[name=rad]:checked').val()==currentQ.answer){score++;}
counter++;
// if there are no questions left
if(counter >= questions.length) {displayResults(); return;}
loadQuestion();
}
function loadQuestion(){
// clear the radio buttons
$("input:checked").removeAttr("checked");
var currentQ=questions[counter];
// display the question
$('h1').text(currentQ.question);
$('#a1').text(currentQ.choices[0]);
$('#a2').text(currentQ.choices[1]);
$('#a3').text(currentQ.choices[2]);
}
function displayResults(){
$("h1").text("You've finished with a score of " + score + "!");
$('[name=rad], #a1, #a2, #a3, #next').remove();
}
JS Fiddle