I can't get the timer to display - javascript

I cannot get the timer countdown to display at all.
I've tried console logging but idk. I'm a noob.
var game = {
correct: 0,
incorrect: 0,
countdown: 90,
countdown: function () {
game.countdown--;
$("#counter-number").html(game.countdown);
if (game.countdown === 0) {
alert("Out of Time!");
game.done();
console.log(countdown)
}
},
// Can't get counter to stay on screen
start: function () {
timer = setInterval(game.countdown, 1000);
$('#insidecontainer').prepend('<h2>Time Remaining: <span id="counter-number">90</span> Seconds</h2>');
$("#start").remove();
console.log(timer)
for (var i = 0; i < questions.length; i++) {
panel.append('<h2>' + questions[i].question + '</h2>');
for (var j = 0; j < questions[i].choices.length; j++) {
panel.append('<input type="radio" name ="question' + '-' + i + '"value="' + questions[i].choices[j] + '">' + questions[i].choices[j]);
}
}
panel.append("<button id='done'>Done!</button>");
},
The timer comes up as 90 but then disappears after 1 second. I want the timer to display it's counting down until it gets to zero.

The questions is missing a lot of code but there are various ways to implement timer with JS and JS libraries.
Following your approach maybe something like this would be sufficient?
var game = {
correct: 0,
incorrect: 0,
countdownseconds: 90,
intervalId: null,
countdown: function () {
game.countdownseconds--;
if (game.countdownseconds === 0)
clearInterval(game.intervalId);
$("#counter-number").html(game.countdownseconds);
},
start: function () {
$('#insidecontainer').prepend('<h2>Time Remaining: <span id="counter-number">90</span> Seconds</h2>');
game.intervalId = setInterval(game.countdown, 1000);
}
}
game.start();
As jimmy5312 pointed out there was collision with the identifier countdown so I used countdownseconds to hold the seconds.
Using this approach, most of your logic would go to countdown function, but I think you should still be able to to extract another function to handle the business logic for the questions and call it right after $("#counter-number").html(game.countdownseconds);

Related

Starting timer when clicking first card of memory game

Ok I am trying to wrap up a project and the only thing holding me back is it that they call for the timer to start on clicking a match game. The timer starts when the HTML file loads which is not what the project wants and I have tried some methods but ends up freezing the game. I want the timer to be able to start when clicking a card.
var open = [];
var matched = 0;
var moveCounter = 0;
var numStars = 3;
var timer = {
seconds: 0,
minutes: 0,
clearTime: -1
};
//Start timer
var startTimer = function () {
if (timer.seconds === 59) {
timer.minutes++;
timer.seconds = 0;
} else {
timer.seconds++;
};
// Ensure that single digit seconds are preceded with a 0
var formattedSec = "0";
if (timer.seconds < 10) {
formattedSec += timer.seconds
} else {
formattedSec = String(timer.seconds);
}
var time = String(timer.minutes) + ":" + formattedSec;
$(".timer").text(time);
};
This is the code for clicking on a card. I have tried to include a startTimer code into this but doesn't work.
var onClick = function() {
if (isValid( $(this) )) {
if (open.length === 0) {
openCard( $(this) );
} else if (open.length === 1) {
openCard( $(this) );
moveCounter++;
updateMoveCounter();
if (checkMatch()) {
setTimeout(setMatch, 300);
} else {
setTimeout(resetOpen, 700);
}
}
}
};
And this class code I use for my HTML file
<span class="timer">0:00</span>
Try this: https://codepen.io/anon/pen/boWQbe
All you needed to do was remove resetTimer() call from the function that happens on page load and then just do a check in the onClick (of card) to see if the timer has started yet. timer.seconds == 0 && timer.minutes == 0.

Javascript/jQuery bug in my Trivia Game

I am creating a basic Trivia Game for a Web Dev class. We are to use HTML/CSS/JS/jQuery to create it. The new element that we are to work with in this assignment are the setTimeout() & setInterval() methods.
After clicking the start button, the game will ask a question and offer 4 possible answers. The user either clicks an answer or the timer runs out. The results are displayed and then then the next questions auto-loads. Once all of the questions in the questions array are asked, the game displays the overall results and then refreshes screen.
The bug that I discovered is that if I let the timer run all the way down until the "zero" is just displayed on the screen and then quickly click on an answer, it causes the game to react as if the conditions of an answer being clicked and the time running out had occurred simultaneously. Then the next question loads too many answers and the timer is decrementing at an increased rate. I'm not sure if there is some sort of time lag in the timer reaching zero somewhere that allows the answer clicks to transmit through and this creates a new timerID that doesn't get cleared which causes the time decrementing on the next question to increase in rate.
I've created a Fiddle for this: https://jsfiddle.net/brianpatrickhummel/0a2hg782/
var correctAnswers = 0;
var incorrectAnswers = 0;
var unansweredQuestions = 0;
var timeRemaining = 16;
var intervalID;
var indexQandA = 0; //index to load a different question each round without the game reset or screen refresh
var answered = false; //variable to stop the timer if user has clicked an answer
var correct;
var triviaGame = [
{question:"HOW MANY COLORS ARE THERE ON A RUBIK'S CUBE ?", answer:["5", "6", "7", "4"], correct: "1", image:("assets/images/rubik.png")},
{question:"WHAT IS THE SPEED OF LIGHT ?", answer:["8,600 MILES per SECOND","86,000 MILES per SECOND","186,000 MILES per SECOND","886,000 MILES per SECOND"], correct:"2", image:("assets//images/lightspeed.jpg")},
{question:"APPROXIMATELY HOW LONG DOES IT TAKE FOR SUNLIGHT TO REACH THE EARTH ?", answer:["45 SECONDS", "10 HOURS", "2 HOURS 15 MINUTES", "8 MINUTES"], correct:"3", image:("assets//images/sunlight.jpg")},
{question:"WHAT ELEMENT'S CHEMICAL SYMBOL IS Pb ?", answer:["POTASSIUM","STRONTIUM","LEAD","PALLADIUM"], correct:"2", image:("assets//images/periodictable.png")},
{question:"HOW FAST CAN BEES FLY ?", answer:["35 MPH", "15 MPH", "48 MPH", "8 MPH"], correct:"1", image: ("assets/images/bee.png")},
{question:"WHAT IS THE MOST ABUNDANT ELEMENT IN THE UNIVERSE ?", answer:["HYDROGEN", "OXYGEN", "HELIUM", "CARBON"], correct:"0", image:("assets//images/universe.png")},
{question:"THE AIR THAT WE BREATHE IS COMPRISED MOSTLY OF WHAT ELEMENT ?", answer:["CARBON", "ARGON", "OXYGEN", "NITROGEN"], correct:"3", image:("assets//images/breathe.jpg")},
{question:"WHAT IS THE DIAMETER OF THE EARTH ?", answer:["140,000 MILES", "2,500,000 MILES", "8,000 MILES", "25,000,000 MILES"], correct:"2", image:("assets//images/earth.png")}
];
// ------------- FUNCTION DECLARATIONS ----------------------------
function startGame() {
console.log("game has begun");
$('.start-button').remove();
correctAnswers = 0;
incorrectAnswers = 0;
unansweredQuestions = 0;
loadQandA ();
}
function loadQandA() {
// console.log(correctAnswers);
// console.log(incorrectAnswers);
// console.log(unansweredQuestions);
// console.log(indexQandA);
answered = false; // will allow timeRemaining to be pushed back to <h5> after round reset....else statement in function timer()
timeRemaining = 16;
intervalID = setInterval(timer, 1000);
if (answered === false){
timer();
}
correct = triviaGame[indexQandA].correct;
var question = triviaGame[indexQandA].question;
$('.question').html(question);
for (var i = 0; i < 4; i++) {
var answer = triviaGame[indexQandA].answer[i];
$('.answers').append('<h4 class= answersAll id=' + i + '>' + answer + '</h4>');
}
$( "h4" ).click(function() {
var id = $(this).attr('id');
// alert(id);
if (id === correct) {
answered = true; // stops the timer
// alert("correct answer");
$('.question').text("THE ANSWER IS: " + triviaGame[indexQandA].answer[correct]);
correctAnswer ();
}
else {
answered = true; //stops the timer
// alert("incorrect answer");
$('.question').text("YOU CHOSE: " + triviaGame[indexQandA].answer[id] + ".....HOWEVER THE ANSWER IS: " + triviaGame[indexQandA].answer[correct]);
incorrectAnswer();
}
});
}
function timer() {
if (timeRemaining === 0) {
answered = true;
clearInterval(intervalID);
$('.question').text("THE CORRECT ANSWER IS: " + triviaGame[indexQandA].answer[correct]);
unAnswered();
}
else if (answered === true) {
clearInterval(intervalID);
}
else {
timeRemaining--;
$('.timeRemaining').text('YOU HAVE ' + timeRemaining + ' SECONDS TO CHOOSE').removeClass('animated pulse infinite');
}
}
function correctAnswer() {
correctAnswers++;
$('.timeRemaining').text("YOU HAVE ANSWERED CORRECTLY!").css({'color':'#3D414F'}).addClass('animated pulse infinite');
resetRound();
}
function incorrectAnswer() {
incorrectAnswers++;
$('.timeRemaining').text("YOU HAVE ANSWERED INCORRECTLY!").css({'color':'#3D414F'}).addClass('animated pulse infinite');
resetRound();
}
function unAnswered() {
unansweredQuestions++;
$('.timeRemaining').text("YOU FAILED TO CHOOSE AN ANSWER").css({'color':'#3D414F'}).addClass('animated pulse infinite');
resetRound();
}
function resetRound() {
$('.answersAll').remove();
$('.answers').append('<img class=answerImage src="' + triviaGame[indexQandA].image + ' ">'); // adds answer image
indexQandA++; // increments index which will load next question when loadQandA() is called again
if (indexQandA < triviaGame.length) {
setTimeout(function(){ loadQandA(); $('.answerImage').remove();}, 5000); // removes answer image from previous round
}
else {
setTimeout(function(){
$('.question').remove();
$('.timeRemaining').remove();
$('.answerImage').remove();
$('.answers').append('<h4 class= answersAll end>CORRECT ANSWERS: ' + correctAnswers + '</h4>');
$('.answers').append('<h4 class= answersAll end>INCORRECT ANSWERS: ' + incorrectAnswers + '</h4>');
$('.answers').append('<h4 class= answersAll end>UNANSWERED QUESTIONS: ' + unansweredQuestions + '</h4>');
setTimeout(function(){ location.reload(); }, 7000);
}, 5000);
}
}
// ----------------------- MAIN PROCESS ---------------------
$('.startButton').on("click", function() {
$('.startButton').removeClass('infinite').addClass('animated fadeOutDown'); //manages the Animate.css applied to Start Button
startGame();
});
Each time you establish a timer with either setTimeout or setInterval, you need to set a variable to the returned timer id. That variable needs to have a high enough scope so that you can access it from any place where the timer must be interacted with.
Then, anywhere you need to interrupt the timer, you can clear it. In your case, when an answer is clicked, you need to stop the countdown timer.
Here's a scaled down example:
window.addEventListener("DOMContentLoaded", function(){
var clock = document.getElementById("clock");
var btnStart = document.getElementById("btnStart");
var btnStop = document.getElementById("btnStop");
// Declare this where you can get at it
var timer1 = null;
function start(){
clock.textContent = new Date().toLocaleTimeString();
timer1 = setTimeout(start, 900);
}
function stop(){
// Cancel the timer
clearTimeout(timer1);
}
btnStart.addEventListener("click", start);
btnStop.addEventListener("click", stop);
start();
});
<div id="clock"></div>
<button id="btnStop">Stop the Clock</button>
<button id="btnStart">Start the Clock</button>

SetInterval running even after i clear it

Im having a little trouble fixing a problem i have with setInterval.
I have a function that runs when i click an element on my website that sets var pass = 1;
if you look in color1(); there is a set Interval that clears itself when pass > 0; so if pass = 1; then it should clear itself, it does, but only after running the interval one more time.
so it - runs setInterval, clears setInterval, then runs the rest of the code in setInterval. What i need, is for setInterval to clear without running the code again.
Thanks in advance
function color1() {
var pass = 1;
var counter = 2;
var animationSpeed = 800;
var $colorContent = '.color-container-1 .color-content-container'
var colorInterval = setInterval(function() {
if (pass > 0) {
clearInterval(colorInterval);
}
$($colorContent).fadeOut(0);
$(($colorContent + '-' + counter)).fadeIn(animationSpeed);
++counter
if (counter === $($colorContent).length + 1) {
counter = 1;
}
}, 3000);
}
It should be like below, you should return the function. Here you have cleared the interval but you haven't stopped the execution
var colorInterval = setInterval(function() {
if (pass > 0) {
clearInterval(colorInterval);
return; //stop here so that it doesn't continue to execute below code
}
$($colorContent).fadeOut(0);
$(($colorContent + '-' + counter)).fadeIn(animationSpeed);
++counter
if (counter === $($colorContent).length + 1) {
counter = 1;
}
}, 3000);

jQuery addClass to multiple elements shows an unexpected delay

I'm making a flipping counter which is supposed to change color when reaching the target number (1000 in the example). But the thing is the different parts of the counter doesn't change color at the same time, we can clearly see a delay between the tiles that make up the counter...
I'm using a simple jQuery addClass to trigger the color change:
$("#rhcounter .count").addClass("red");
Any ideas what could be causing that ?
Here is the fiddle: http://jsfiddle.net/ka6ke28m/6/
Thanks for your help !
First issue:
There was a huge amount of wasted processing going on. jQuery selectors have an overhead so reduce them to a minimum and complex selectors more-so. I have reduced that considerably.
Second issue:
There is a nasty visual glitch on some browsers that looked like this:
Which you can eliminate by using background-color: instead of background: (which tries to completely re-render the area instead of just fill the background colour).
Third issue:
The color blue left behind was down to slow repainting of the screen. The above two fixes had a huge impact and I also tried adding specific CSS animations that worked only with the red class. This can probably be improved now you know the causes of the slow painting (e.g. have blue and red CSS animation?):
http://jsfiddle.net/TrueBlueAussie/ka6ke28m/10/
$(function () {
var total = 1000,
current = 950,
timeout = 150,
inc = 7,
prevTiles = ["0", "0", "0", "0"],
interval = setInterval(function () {
increase()
}, timeout),
increase = function () {
current += inc;
if (current >= total) {
clearInterval(interval);
current = total;
}
if (current === total) {
$("#rhcounter .count").addClass("red");
}
// instant timer to delay css
setTimeout(function () {
var tiles = [false, false, false, false],
currStr = (current + "").split("").reverse().join("");
for (var i = 0; i < currStr.length; i++) {
if (currStr[i] !== prevTiles[i]) {
tiles[i] = true;
prevTiles[i] = currStr[i];
}
}
tiles.forEach(function (tile, index) {
if (!tile) {
return;
}
// Get the current tile
var $tile = $("#rhcounter div.tile" + index);
$tile.children('span.curr').each(function () {
$(this).text($tile.text());
});
$tile.removeClass("flip");
setTimeout(function () {
$tile.addClass("flip");
}, 5);
var top = $tile.find("span.count.next.top"),
bottom = $tile.find("span.count.next.bottom"),
delay = (index === 0 ? timeout : 250);
setTimeout(function () {
top.text(prevTiles[index]);
}, delay / 2);
setTimeout(function () {
bottom.text(prevTiles[index]);
}, delay / 2);
});
}, 1);
};
});
that was happening because you were changing color before changing text. i just shifted if condition and i think that is what you wanted DEMO
$(window).load(function() {
var total = 1000, current = 950, timeout = 150, inc = 7,
prevTiles = ["0","0","0","0"],
interval = setInterval(function(){increase()}, timeout),
increase = function () {
current += inc;
if (current >= total) {
clearInterval(interval);
current = total;
}
var tiles = [false, false, false, false],
currStr = (current+"").split("").reverse().join("");
for (var i = 0; i < currStr.length; i++) {
if (currStr[i] !== prevTiles[i]) {
tiles[i] = true;
prevTiles[i] = currStr[i];
}
}
tiles.forEach(function (tile, index) {
if (!tile) { return; }
$("#rhcounter > div[class~='tile"+index+"'] > span[class~='curr']").each(function() {
$(this).text($("#rhcounter > div[class~='tile"+index+"'] > span.count.next.top").text());
});
$("#rhcounter > div[class~='tile"+index+"']").removeClass("flip");
setTimeout(function(){$("#rhcounter > div[class~='tile"+index+"']").addClass("flip");}, 5);
var top = $("#rhcounter > div[class~='tile"+index+"'] > span.count.next.top"),
bottom = $("#rhcounter > div[class~='tile"+index+"'] > span.count.next.bottom"),
delay = (index === 0 ? timeout : 250);
setTimeout(function(){ top.text(prevTiles[index]); }, delay/2);
setTimeout(function(){ bottom.text(prevTiles[index]); }, delay/2);
});
if (current === total) {
$("#rhcounter .count").addClass("red");
}};
});

setInterval doesnt tigger inner script on first time run

Maybe I'm not properly understanding setInterval but I have made a kind of slideshow script, as below:
var i = 0;
setInterval(function() {
$('.slide').fadeOut('slow').delay(200);
$('.slide:eq(' + i + ')').fadeIn('slow').delay(2000);
i++;
if(i == 5){
i = 0;
}
}, 4000);
This works, except for the first run - no slides will display for the first 4 seconds.
See Fiddle here: http://jsfiddle.net/vpa89snf/6/
Is there anyway I can trigger whats inside the setInterval function when it runs the first time round?
Use setTimeOut instead of setInterval for better performance, inspect the sample below:
Here is working jsFiddle.
var i = -1;
var totalSlide = $('.slide').length-1;
var slideTimer = 0;
function nextFrame() {
i == totalSlide ? i = -1 : i;
i++;
$('.slide').fadeOut(200);
$('.slide').eq(i).fadeIn(200);
slideTimer = setTimeout(nextFrame,4000);
}
$('#holder').addClass('isAni');
nextFrame();
// play / pause animation
$('#holder').click(function() {
if ( $(this).hasClass('isAni') ) {
$(this).removeClass('isAni');
clearTimeout(slideTimer);
}else{
$(this).addClass('isAni');
nextFrame();
}
});
You need to run the function and not wait for the 4 first seconds:
var i = 0;
function doSomething() {
$('.slide').fadeOut('slow').delay(200);
$('.slide:eq(' + i + ')').fadeIn('slow').delay(2000);
i = (i + 1) % 5;
}
$document.ready(function () {
setInterval(doSomething, 4000);
doSomething(); // run it!
});
JSFIDDLE.
This is how setInterval is executed. It runs your function after x milliseconds set as 2nd parameter.
What you have to do in order to show the first slide is to have the 1rst slide fadein like below:
var i = 0;
$('.slide:eq(' + i + ')').fadeIn('slow').delay(2000);
i++;
setInterval(function() {
...
}, 4000);

Categories