console.log gives undefined on a variable - javascript

I have a timer function (it calculates how many words were read in given time but my code doesn't work).
It says:
"Uncaught ReferenceError: startTime is not defined"
on line:
"testTime = (stopTime - startTime)/1000 + testTime;"
HTML
<button class="btn" id="start">Start Reading</button>
<div id="page1" style="display: block;"><p class="title">
Text goes here
</div>
<button class="btn" id="stop">Finished!</button>
<span id="wordValue"></span>
<span id="timeValue"></span>
JAVASCRIPT
function runTest(){
testRunning = false;
restart = false;
var testTime = 0;
jQuery('#start').click(function(){
startTime = new Date().getTime();
testRunning = true;
});
jQuery('#stop').click(function(){
stopTime = new Date().getTime();
testTime = (stopTime - startTime)/1000 + testTime;
testRunning = false;
// set wpm = calculated words per minute
wpm = Math.round(wordCount('#page1') / (testTime / 60));
// set difference = calculated difference between words per minute and national average (250)
difference = Math.round(100*((wpm/250)-1));
if (difference < 0) {
difference = difference*-1 + '% slower';
} else {
difference = difference+'% faster';
}
});

I think startTime is not defined because it's a local variable to jQuery('#start').click. Try define startTime upper
var testRunning = false;
var restart = false;
var testTime = 0;
var startTime = 0; // here

Ran this on jsfiddle and it worked fine:
https://jsfiddle.net/d3eqmbv5/
Just had to remove:
function runTest(){
And I made a fake wordCount function for testing purposes.

There is a missing parenthesis first if you look at this jsfiddle and tape F12, so what can be the next step ? to shutt the function right after or at the end of the complete block of code ?
function runTest(){
testRunning = false;
restart = false;
var testTime = 0;
https://jsfiddle.net/qugp3fot/

Related

My JS timer clock is not stopping when clicked twice on start button [duplicate]

This question already has an answer here:
JavaScript countdown timer with on key press to reset the timer
(1 answer)
Closed 11 months ago.
I have a simple HTML stopwatch logic where I can start and stop the clock with the button click. By clicking on the start button, one can start the timer (shows current time) and update every second. One can stop it by clicking stop button. But if one clicks on start button twice, there is nothing I can do to stop the timer. Below is my code:
var hour = document.getElementById("hoursOut");
var minute = document.getElementById("minsOut");
var second = document.getElementById("secsOut");
var btnStart = document.getElementById("btnStart");
var btnStop = document.getElementById("btnStop");
var waitTimer;
function displayTime() {
var currentTime = new Date();
var currentHour = currentTime.getHours();
var currentMinute = currentTime.getMinutes();
var currentSeconds = currentTime.getSeconds();
hour.innerHTML = twoDigit(currentHour) + ":";
minute.innerHTML = twoDigit(currentMinute) + ":";
second.innerHTML = twoDigit(currentSeconds);
}
function twoDigit(digit) {
if (digit < 10) {
digit = "0" + digit;
}
return digit;
}
function startClock() {
waitTimer = setInterval(displayTime, 1000);
}
function stopClock() {
clearInterval(waitTimer);
}
btnStart.onclick = startClock;
btnStop.onclick = stopClock;
<h1>JavaScript Clock</h1>
<div id="calendarBox">
<!-- OUTPUT TIME VALUES -->
<p class="timeDisplay">
<span id="hoursOut">00:</span>
<span id="minsOut">00:</span>
<span id="secsOut">00</span>
</p>
<!-- BUTTON SET -->
<input id="btnStart" type="button" value="START" />
<input id="btnStop" type="button" value="STOP" />
</div>
I have checked some answers in stackoverflow but most solutions uses a for-loop from 0 to 1000 until it finds the interval id and stop all of them using loop. I am confident there should be an elegant solution than that.
// some stackoverflow suggested answer
for (var i = 1; i < 99999; i++)
window.clearInterval(i);
A possible solution is to prevent the problem before it happens. You can place a check on the running timer (Is there a way to check if a var is using setInterval()?).
In this case you could just have a global timer variable var timer = false the with add a check to the start function. Then the stop function will set the timer variable back to false.
function startClock() {
if(!timer){
timer = true
waitTimer = setInterval(displayTime, 1000);
}
else return
}
function stopClock() {
clearInterval(waitTimer);
timer = false
}
when you double click you start a new setInterval(). So you now have two set intervals running. Only problem is you can't access the first one cause you named the second one the same name. Check if waitTimer exists and if it does stop it. see code:
UPDATE: actually you don't even need an if statement. just call stopClock() before you set waitTimer -- code snippet adjusted
var hour = document.getElementById("hoursOut");
var minute = document.getElementById("minsOut");
var second = document.getElementById("secsOut");
var btnStart = document.getElementById("btnStart");
var btnStop = document.getElementById("btnStop");
var waitTimer;
function displayTime() {
var currentTime = new Date();
var currentHour = currentTime.getHours();
var currentMinute = currentTime.getMinutes();
var currentSeconds = currentTime.getSeconds();
hour.innerHTML = twoDigit(currentHour) + ":";
minute.innerHTML = twoDigit(currentMinute) + ":";
second.innerHTML = twoDigit(currentSeconds);
}
function twoDigit(digit) {
if (digit < 10) {
digit = "0" + digit;
}
return digit;
}
function startClock() {
stopClock();
waitTimer = setInterval(displayTime, 1000);
}
function stopClock() {
clearInterval(waitTimer);
}
btnStart.onclick = startClock;
btnStop.onclick = stopClock;
<h1>JavaScript Clock</h1>
<div id="calendarBox">
<!-- OUTPUT TIME VALUES -->
<p class="timeDisplay">
<span id="hoursOut">00:</span>
<span id="minsOut">00:</span>
<span id="secsOut">00</span>
</p>
<!-- BUTTON SET -->
<input id="btnStart" type="button" value="START" />
<input id="btnStop" type="button" value="STOP" />
</div>

Chrome Extension: calculate in miliseconds and click button after specific seconds

Well i am practising on Chrome Extension , i'm newbie on this.
Here is my code.
popup.html
<!doctype html>
<html>
<head>
<title>Laser Script</title>
<script type="text/javascript" src="popup.js"></script>
<style type="text/css">
h1 { font-size: 22px; }
.powered {
font-size: 14px;
margin-top: 8px;
}
</style>
</head>
<body>
<h1>Scheduled Click</h1>
<div id="contentWrapper">
<input type="text" id="duration" placeholder="Duration">
<input type="text" id="attack_date" placeholder="Day/Month/Year">
<input type="text" id="attack_time" placeholder="00:00:00">
<button id="schedule">Start Attack</button>
</div>
<div class="powered">Courtesy of <img src="justpark_logo.png" width="170px"></div>
</body>
</html>
popup.js
function initialise () {
// here im calculating the remind time in (mileseconds) that the button have to be pressed
var attack_timeInput = document.getElementById("attack_time");
var attack_timeParts = attack_timeInput.value.split(":");
var hours = parseInt(attack_timeParts[0],10);
var minutes = parseInt(attack_timeParts[1],10);
var seconds = parseInt(attack_timeParts[2],10);
var mileseconds = parseInt(attack_timeParts[3],10);
var attack_DateInput = document.getElementById("attack_date");
var attack_DateInputParts = attack_DateInput.value.split("/");
var day = parseInt(attack_DateInputParts[0],10);
var month = parseInt(attack_DateInputParts[1],10);
var year = parseInt(attack_DateInputParts[2],10);
var durationInput = document.getElementById("duration");
var durationParts = durationInput.value.split(":");
var hours2 = parseInt(durationParts[0],10)*3600000;
var minutes2 = parseInt(durationParts[1],10)*60000;
var seconds2 = parseInt(durationParts[2],10)*1000;
var duration_mile = hours2+minutes2+seconds2;
var now = new Date();
var new_now = now.getTime();
var full_attack_date = new Date(year, month-1, day, hours, minutes, seconds, mileseconds);
var new_full_attack_date = full_attack_date.getTime();
var delayInputValue = new_full_attack_date - new_now - duration_mile;
function scheduleClick () {
document.getElementById("contentWrapper").innerHTML = 'The attack will start in ' + delayInputValue + 'miliseconds';
var codeString = 'var button = document.getElementById("troop_confirm_go"); setTimeout( function() { button.click(); },' + delayInputValue + ' )';
console.log(codeString);
chrome.tabs.executeScript({ code: 'console.log(document.getElementById("The attack will start ' + delayInputValue + ' miliseconds"))' });
chrome.tabs.executeScript({ code: codeString});
};
scheduleButton = document.getElementById("schedule");
scheduleButton.addEventListener('click', scheduleClick, true);
};
document.addEventListener('DOMContentLoaded', initialise, false);
So i have 3 inputs. I calculate the remind time until the button will be clicked. (it works)
But in this part
document.getElementById("contentWrapper").innerHTML = 'The attack will start in ' + delayInputValue + 'miliseconds';
it diplays
The attack will start in NaN miliseconds.
and the button is pressed instantly.
I ckeched also this code:
var p = 1 ; //it's outside the function as the var delayInputValue
document.getElementById("contentWrapper").innerHTML = 'The attack will start in ' + delayInputValue + 'seconds';
and it displays :
The attack will start in 1 miliseconds.
So here is my question, why it can't read and work with the var delayInputValue but i can the var p?
Can i fix it somehow ?
Got it - the initialise() function is called when your DOM content is finished loading. At that point, the user has not entered information into the text fields, so they show as null or undefined. When the code starts running with this data it produces data as NaN since the calculations don't work.
In order for the code to run properly, you need to place the code dealing with data from those fields inside the scheduleClick() function, like so:
function initialise () {
function scheduleClick () {
var attack_timeInput = document.getElementById("attack_time");
var attack_timeParts = attack_timeInput.value.split(":");
var hours = parseInt(attack_timeParts[0],10);
var minutes = parseInt(attack_timeParts[1],10);
var seconds = parseInt(attack_timeParts[2],10);
//var mileseconds = parseInt(attack_timeParts[3],10);
var attack_DateInput = document.getElementById("attack_date");
var attack_DateInputParts = attack_DateInput.value.split("/");
var day = parseInt(attack_DateInputParts[0],10);
var month = parseInt(attack_DateInputParts[1],10);
var year = parseInt(attack_DateInputParts[2],10);
var durationInput = document.getElementById("duration");
var durationParts = durationInput.value.split(":");
var hours2 = parseInt(durationParts[0],10)*3600000;
var minutes2 = parseInt(durationParts[1],10)*60000;
var seconds2 = parseInt(durationParts[2],10)*1000;
var duration_mile = hours2+minutes2+seconds2;
var now = new Date();
var new_now = now.getTime();
var full_attack_date = new Date(year, month-1, day, hours, minutes, seconds);
var new_full_attack_date = full_attack_date.getTime();
var delayInputValue = new_full_attack_date - new_now - duration_mile;
document.getElementsByTagName("div")[0].innerHTML = 'The attack will start in ' + delayInputValue + 'miliseconds';
};
scheduleButton = document.getElementById("schedule");
scheduleButton.addEventListener('click', scheduleClick, true);
};
document.addEventListener('DOMContentLoaded', initialise, false);
Note that I also removed the miliseconds variable as the inputs I was using included hours, minutes and seconds only. You should also add some code to sanitise inputs to make sure they are in the format you want before calling the function.
Hope that helps

clearInterval is not stopping time consistenly

I'm creating a simple game of boggle that limits the user to 30 seconds. After that time, the game ends and the results are displayed. The problem is SOMETIMES everything works fine and the "timer" html shows Times Up. Other times, the countdown starts counting backward. My interval id variable is global and initially set to null. I'm not sure what's going on.
function words(x)
{
switch (x)
{
case 1:
var word = new Array("balte","table","hat","tab","belt","lab","eat","tea","ate","tale","bale","let","bet","teal","late","beat");
break;
case 2:
var word = new Array("atwre","water","wet","wear","tear","war","ret","rate","eat","ate","tea","awe","raw","rat","wart","art","tar");
break;
case 3:
var word = new Array("dclaen","can","cane","and","clan","lane","lean","lend","land","den","dean","dance","lance","clean","deal","ale","dale","candle","clad");
break;
case 4:
var word = new Array("aepinlar","air","airplane","plane","plan","lane","lean","pane","ear","near","nap","nape","lair","pen","pan","ape","leap","ale","peal","nap","rap","par", "pare", "pale", "are", "rail", "ail", "pail", "nail", "air", "pair", "ran", "pin", "pine", "line", "nip", "rip", "ripe", "lip", "earn", "learn", "ire");
break;
case 5:
var word = new Array("redykboa","keyboard","key","board","bored","bore","bark","dark","dork","oar","boar","ark","dare","bare","are","red","rod","road","bode","rode","ode","bread", "read", "bead", "bred", "break", "drey", "day", "boy", "broke", "rake", "bake", "ear", "dear", "bear", "dye", "dyer", "doer", "oak", "boa", "doe", "okay","dab", "bade", "ade", "drake", "bard", "yard", "year", "beak", "beard", "bad", "bed", "bay");
break;
case 6:
var word = new Array("evtsaedri","advertise","side","eat","sad","sat","rat","rate","vet","advise","read","rest","vest","serve","served","aside","east","tread","dear","deer","tear","trade","starve","steer","stare","veer","seat","seed","tree","drives","strive");
break;
case 7:
var word = new Array("rcseanbh","branches","bra","she","ran","bran","car","cab","race","ranch","share","bench","bar","char","can","crane","ban","hear","hare");
break;
case 8:
var word = new Array("vradntseue","adventures","vent","dent","stun","dust","rust","vase","sure","ensure","star","vend","dare","tar","starve","trade","sad","eat veer","tear","seat","seed","sand","tree","rest");
break;
case 9:
var word = new Array("wokcnalgede","acknowledge","and","land","wand","wage","ledge","led","lead","lend","leg","gown","know","now","no","lean","wean","week","wed","lack","leak","deal","deck","knew","kneel");
break;
case 10:
var word = new Array("muprith","triumph","hit","hurt","pit","trim","rum","rump","tip","thump","put","rim","him","hum","hip","rut");
break;
}
return word;
}
<html>
<head>
<title>Greg's Gambits | Greg's Game of Boggle</title>
<link href="greg.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="gregBoggle2.js"></script>
<script>
compWords = new Array(); notAword = new Array();
playWords = new Array();
var play = ""; /*var today;*/ var count = 30;
var score = 0; var interval = null;
var quit = false;
function start()
{
/*var start = new Date();
today = start.getTime();*/
timeIt();
boggle();
}
function displayLetters()
{
var num = Math.floor(Math.random()*10) +1;
compWords = words(num);
yourWord = compWords[0];
document.getElementById("letters").innerHTML = yourWord;
}
function timeIt()
{
interval = window.setInterval("countdown()",1000);
}
function countdown()
{
count--;
if (count == 0)
{
window.clearInterval(interval);
interval = null;
document.getElementById("timer").innerHTML = "Time's Up";
var btn =document.getElementById("start");
btn.disabled = true;
quit = true;
checkWin();
return;
}
document.getElementById("timer").innerHTML = count;
}
function boggle()
{
play = document.getElementById("words").value;
if (!quit)
{
playWords.push(play);
displayEntries();
document.getElementById("words").value = "";
document.getElementById("words").focus();
}
else
{
document.getElementById("words").value = "";
document.getElementById("words").focus();
checkWin();
}
}
function displayEntries()
{
document.getElementById("entries").innerHTML = playWords.toString();
}
/*function toMinutesAndSeconds(millis)
{
var minutes = Math.floor(millis/60000);
var seconds = ((millis%60000)/1000).toFixed(0);
return minutes + ":" + ((seconds < 10 ? '0' : "")+ seconds);
}*/
function checkWin()
{
// check winning score and list bad words
var complgth = compWords.length;
var playlgth = (playWords.length);
var flag; var timePlayed;
/*var endTime = new Date().getTime();
var diff = endTime - today;
timePlayed = toMinutesAndSeconds(diff);*/
for (var i = 0; i < playlgth; i++)
{
flag = 0;
for (var k = 0; k < complgth; k++)
{
if (playWords[i] == compWords[k])
{
score= score + 1;
flag = 1;
}
}
if (flag == 0)
notAword.push(playWords[i]);
}
document.getElementById("result").innerHTML = ("Your score is " +
score + ". The following entries " + "are not valid words: <br />" +
notAword.toString());
/*document.getElementById("timer").innerHTML = ("Your time: " + timePlayed);*/
}
</script>
</head>
<body>
<div id="container">
<img src="images/superhero.jpg" width="120" height="120" class="floatleft" />
<h1 align="center"><em>Greg's Game of Boggle</em></h1>
<div style = "clear:both;"></div>
<div id = "nav">
<p>Home
About
Play a Game
Sign In
Contact Us</p>
</div>
<div id="content">
<p>The object of the game is to create as many words as
you can. Please click the Display letters button and your letters will
be shown below. You have 10 possible letter combinations and 30 seconds. When you are ready to begin, enter the word then click the Submit Word button. The timer will start after first entered word.</p>
<p><input type="button" value="Display letters" onclick="displayLetters();" /><br/>
<input type="text" id="words">
<input type="button" id="start" value="Submit Word" onclick="start();" />
</p>
<h2><br /><br />Letters you can use:<br /><div id="letters"> </div><br /></h2>
<h2>Your words so far: <br /><div id="entries"> </div><br /></h2>
<h2>Results:<br /><div id="result"> </div></h2>
<h2>Timer: <br /><div id="timer"> </div></h2>
</div>
<div id="footer">Copyright © 2013 Greg's Gambits<br />
foulksy#gmail.com
</div>
</div>
</body>
</html>
Every time you submit a word, you call your start() function which calls timeIt(). Your solution works if you only submit one word, but if you submit multiple, you'll run into the issue where you see a negative timer.
I believe you have to clear the previous setInterval before creating a new one and storing it on your interval variable:
function timeIt()
{
window.clearInterval(interval);
interval = window.setInterval(countdown, 1000);
}
You should replace this line
interval = window.setInterval("countdown()",1000);
with the following
interval = window.setInterval(countdown, 1000);
You need to pass a function as the first parameter which can be called by the timer. You pass a string, which can't be called.
More information here.
Not sure if this is why it's failing, but setInterval takes a function as its first argument, not a string. It should be setInterval(countdown, 1000) not setInterval("countdown()", 1000).

Personal Best Scorekeeper / Timer

I'm making a timer that records the longest time (personal best) when clicking 'ok' on the pass button. I can't seem to figure out how to get the counter back to 0 and I'm sure there's a way to do it with only 2 buttons (start + pass). I want the timer to start again when I press start, at the moment it just runs each case once and returns the highest value. The timer currently logs the second after the number shown on screen which I do not understand.
Thanks in advance for your help, much appreciated!
var c = 0;
var d = 0;
var pb;
function myCounter() {
document.getElementById("demo").innerHTML = c++;
}
function restartCount() {
document.getElementById("demo").innerHTML = d++;
}
function userPass() {
if (confirm("Are you sure?")) {
console.log(c,d);
clearInterval(myCounter);
clearInterval(restartCount);
document.getElementById("personalBest").innerHTML = Math.max(c,d);
} else {
document.getElementById("good").innerHTML = "Keep it up!";
}
}
<h1>Best Time = <span id="personalBest"></span></h1>
<p id="good"></p>
<p id="demo"></p>
<button onClick="myCounter = setInterval(myCounter, 1000)">Start counter!</button>
<button onclick="userPass()">Pass</button>
<button onclick="restartCount = setInterval(restartCount, 1000)">Restart</button>
Regarding your second question "The timer currently logs the second after the number shown on screen which I do not understand."
This is linked to where you put the ++ in this line
document.getElementById("demo").innerHTML = c++;
c++ means get the value of c then increment it. I believe you want to increment first (because 1 second has elapse) then assign and use.
In this case you should use ++c instead.
document.getElementById("demo").innerHTML = ++c;
There were a few mistakes
timer variable name and function variable name were same, they need to be different. Also, it is cleaner to invoke a simple method rather than starting timer from the onclick.
No need for second start button, ensure that you clear c and timer before starting new timer.
var c = 0;
var d = 0;
var myCounter;
function myCounter1() {
c = 0; //set c to 0;
clearInterval(myCounter);
myCounter = setInterval(() => {
document.getElementById("demo").innerHTML = c++;
}, 1000);
}
function userPass() {
if (confirm("Are you sure?")) {
d = Math.max(c,d);
clearInterval(myCounter);
document.getElementById("personalBest").innerHTML = d;
} else {
document.getElementById("good").innerHTML = "Keep it up!";
}
}
<h1>Best Time = <span id="personalBest"></span></h1>
<p id="good"></p>
<p id="demo"></p>
<button onClick="myCounter1()">Start counter!</button>
<button onclick="userPass()">Pass</button>

Javascript highscore counter not updating

I'm trying to make a game that measures your reaction time, but my fastest score tracker is very buggy. It works during the first reaction test but after that stops working. Thanks in advance to anyone that can help.
<!DOCTPYE html>
<html>
<head>
<script>
window.onload = alert("Press START to start the game. As soon as the screen turns red click the stop button. Get the fastest time you can. Good luck");
var button = document.getElementById("reactionTester");
var start = document.getElementById("start");
var startTime;
var scoreContainer = document.getElementById("p");
var css = document.createElement("style");
css.type= "text/css";
var counter = 0;
var timer = null;
var highscore = document.getElementById("highscore");
var currentRecord = 0;
var highscoreCounter = 0;
function init(){
var startInterval/*in milliseconds*/ = Math.floor(Math.random()*10)*1000;
clearTimeout(timer);
timer = setTimeout(startTimer,1/*startInterval*/);
document.body.appendChild(css);
css.innerHTML = "html{background-color: blue;}";
}
function startTimer(){
startTime = Date.now();
css.innerHTML="null";
css.innerHTML = "html{background-color: red;}";
if(counter==1){
p1 = document.getElementsByTagName('p')[1];
p1.parentNode.removeChild(p1);
counter++;
}
}
function stopTimer(){
if(startTime){
var stopTime = Date.now();
var dif = stopTime - startTime;
alert("Your time is " + dif + " ms");
startTime = null;
css.innerHTML = null;
var p = document.createElement("p");
document.body.appendChild(p);
p.innerHTML = dif;
counter=1;
if (highscoreCounter != 0){
if(dif < currentRecord){
Phighscore2 = document.getElementsByTagName('p')[0];
Phighscore2.parentNode.removeChild(Phighscore2);
document.getElementById("highscore").appendChild(highscoreP);
currentRecord = dif;
highscoreP.innerHTML = currentRecord;
}
else{}
}
else{
var highscoreP = document.createElement("p");
document.getElementById("highscore").appendChild(highscoreP);
currentRecord = dif;
highscoreP.innerHTML = currentRecord;
highscoreCounter++;
}
}
else{
alert("don't trick me");
}
}
</script>
</head>
<body>
<div id="highscore">
</div>
<form id="form">
<div class="tableRow">
<input type="button" value="start" id="start" onclick="init()">
</div>
<div class="tableRow">
<input type="button" id="reactionTester" onclick="stopTimer()" value="stop">
</div>
<div id="p">
</div>
</form>
</body>
</html>
Your problem is caused by the fact that variable highscoreP is defined locally in function stopTimer. Local variables lose their value upon function return. Make it a global variable (and do not forget to remove its 'var' keyword inside the function).
I cannot resist making some additional remarks about your code:
Do not create the same DOM elements over and over again; it complicates your code and stresses out the browser's memory manager. Define all elements statically and refer to them by ID as you already did with the containers (highscore, p).
Do not build a style element dynamically, this is really bad practice. Instead, define CSS classes statically, then assign the classes dynamically by setting attribute className.
Even though you are doing a pretty good job programming in plain javascript, you may want to consider using jQuery.

Categories

Resources