Javascript double timer - javascript

So i want to set a vanilla JavaScript to display a message screen text for 30-40 seconds then display a different text for 10 seconds. The first message should change in particular order (ie.. hello, world, i ,love java, script). And cycle through. I tried to put it in an a array with a timer but no luck can't get the timer to oscillate between the 30 and 10 seconds.
So ie... hello for 30 sec, then world for 10 sec, then i love for 30 sec and so on.
Currently I'm following this example but I'd rather not do the math there's got to be a cleaner better way.
https://www.w3schools.com/jsref/met_win_settimeout.asp
This what i am doing now. Abbreviated
function timedText() {
setTimeout(myTimeout1, 10000) setTimeout(myTimeout2, 30000) setTimeout(myTimeout3, 40000)
}
function myTimeout1() {
document.getElementById("tebatademo").innerHTML = "<h2 style='background-color: yellow; color: black; text-align: center;'>Mountin Climbers</h2>";
}
function myTimeout2() {
document.getElementById("tebatademo").innerHTML = "<h2 style='background-color: red; color: white; text-align: center;'>REST</h2>";
}
function myTimeout3() {
document.getElementById("tebatademo").innerHTML = "<h2 style='background-color: yellow; color: black; text-align: center;'>Inch Worms</h2>";
}

Why not just have two functions, one that sets the other and vice versa?
function one() {
window.alert('Messsage One')
setTimeout(two, 10*1000);
}
function two() {
window.alert('Message two');
setTimeout(one, 30*1000);
}
setTimeout(two, 30*1000);
Obviously, you could change the window.alert calls to whatever method you're actually using for displaying the text.
EDIT
Ok, to update based on your request. If you want an array of words to cycle, and varying times, I've done it this way. Given the HTML:
<div id='msgBox'></div>
You can setup an array and a function to display from that array like so:
var msgBox = document.getElementById('msgBox');
var messages = ['hello', 'world', 'i' ,'love', 'java', 'script']
function updateMessage() {
// take the first word out of the array and store it in the msg variable
var msg = messages.shift();
// set the div content to the word
msgBox.innerHTML = msg;
// pick a duration based on if the remaining array length is odd or even
var duration = messages.length % 2 ? 10 * 1000 : 30 * 1000
// queue up the next message update
setTimeout(updateMessage, duration)
}
setTimeout(updateMessage, 10*1000)
Obviously, you can tweak the duration bit however you want; I just did a modulo operation so that basically if the array length is even you wait 10 seconds if it's odd you wait 30 seconds.
Likewise if you want to update the inner content to include other information (e.g. like you had an h2 with various styles) you can either put that whole string in the array, or you can use something similar to my duration logic to select the correct wrapper.
Here's the fiddle

you can do something like below!
you can modify timeout interval as per your requirement
function myTimeout1() {
document.getElementById("tebatademo").innerHTML = "<h2 style='background-color: yellow; color: black; text-align: center;'>Mountin Climbers</h2>";
setTimeout(myTimeout2,3000);
}
function myTimeout2() {
document.getElementById("tebatademo").innerHTML = "<h2 style='background-color: red; color: white; text-align: center;'>REST</h2>";
setTimeout(myTimeout3,5000);
}
function myTimeout3() {
document.getElementById("tebatademo").innerHTML = "<h2 style='background-color: yellow; color: black; text-align: center;'>Inch Worms</h2>";
setTimeout(myTimeout1,2000);
}
myTimeout1();
<div id="tebatademo">
</div>

Best way to do it with OOP.
function Timer(fn, delay) {
this.startTimer = function(fn, delay) {
setTimeout(fn, delay);
}
return this;
}
function timedText() {
let timer1 = new Timer();
let timer2 = new Timer();
let timer3 = new Timer();
timer1.startTimer(myTimeout1, 1000);
timer2.startTimer(myTimeout2, 3000);
timer2.startTimer(myTimeout3, 4000);
}
function myTimeout1() {
document.getElementById("tebatademo").innerHTML = "<h2 style='background-color: yellow; color: black; text-align: center;'>Mountin Climbers</h2>";
}
function myTimeout2() {
document.getElementById("tebatademo").innerHTML = "<h2 style='background-color: red; color: white; text-align: center;'>REST</h2>";
}
function myTimeout3() {
document.getElementById("tebatademo").innerHTML = "<h2 style='background-color: yellow; color: black; text-align: center;'>Inch Worms</h2>";
}
timedText();
<div id="tebatademo"></div>
In case if you need to add other functionality of timer in future, you can easily add and remove it not needed anyone.
Hope this helps!

Related

Cancel a function if button is clicked [duplicate]

I am using setInterval(fname, 10000); to call a function every 10 seconds in JavaScript. Is it possible to stop calling it on some event?
I want the user to be able to stop the repeated refresh of data.
setInterval() returns an interval ID, which you can pass to clearInterval():
var refreshIntervalId = setInterval(fname, 10000);
/* later */
clearInterval(refreshIntervalId);
See the docs for setInterval() and clearInterval().
If you set the return value of setInterval to a variable, you can use clearInterval to stop it.
var myTimer = setInterval(...);
clearInterval(myTimer);
You can set a new variable and have it incremented by ++ (count up one) every time it runs, then I use a conditional statement to end it:
var intervalId = null;
var varCounter = 0;
var varName = function(){
if(varCounter <= 10) {
varCounter++;
/* your code goes here */
} else {
clearInterval(intervalId);
}
};
$(document).ready(function(){
intervalId = setInterval(varName, 10000);
});
I hope that it helps and it is right.
Already answered... But if you need a featured, re-usable timer that also supports multiple tasks on different intervals, you can use my TaskTimer (for Node and browser).
// Timer with 1000ms (1 second) base interval resolution.
const timer = new TaskTimer(1000);
// Add task(s) based on tick intervals.
timer.add({
id: 'job1', // unique id of the task
tickInterval: 5, // run every 5 ticks (5 x interval = 5000 ms)
totalRuns: 10, // run 10 times only. (omit for unlimited times)
callback(task) {
// code to be executed on each run
console.log(task.name + ' task has run ' + task.currentRuns + ' times.');
// stop the timer anytime you like
if (someCondition()) timer.stop();
// or simply remove this task if you have others
if (someCondition()) timer.remove(task.id);
}
});
// Start the timer
timer.start();
In your case, when users click for disturbing the data-refresh; you can also call timer.pause() then timer.resume() if they need to re-enable.
See more here.
In nodeJS you can you use the "this" special keyword within the setInterval function.
You can use this this keyword to clearInterval, and here is an example:
setInterval(
function clear() {
clearInterval(this)
return clear;
}()
, 1000)
When you print the value of this special keyword within the function you output a Timeout object Timeout {...}
The Trick
setInterval returns a number:
Solution
Take this number. Pass it to the function clearInterval and you're safe:
Code:
Always store the returned number of setInterval in a variable, so that you can stop the interval later on:
const intervalID = setInterval(f, 1000);
// Some code
clearInterval(intervalID);
(Think of this number as the ID of a setInterval. Even if you have called many setInterval, you can still stop anyone of them by using the proper ID.)
Why not use a simpler approach? Add a class!
Simply add a class that tells the interval not to do anything. For example: on hover.
var i = 0;
this.setInterval(function() {
if(!$('#counter').hasClass('pauseInterval')) { //only run if it hasn't got this class 'pauseInterval'
console.log('Counting...');
$('#counter').html(i++); //just for explaining and showing
} else {
console.log('Stopped counting');
}
}, 500);
/* In this example, I'm adding a class on mouseover and remove it again on mouseleave. You can of course do pretty much whatever you like */
$('#counter').hover(function() { //mouse enter
$(this).addClass('pauseInterval');
},function() { //mouse leave
$(this).removeClass('pauseInterval');
}
);
/* Other example */
$('#pauseInterval').click(function() {
$('#counter').toggleClass('pauseInterval');
});
body {
background-color: #eee;
font-family: Calibri, Arial, sans-serif;
}
#counter {
width: 50%;
background: #ddd;
border: 2px solid #009afd;
border-radius: 5px;
padding: 5px;
text-align: center;
transition: .3s;
margin: 0 auto;
}
#counter.pauseInterval {
border-color: red;
}
<!-- you'll need jQuery for this. If you really want a vanilla version, ask -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="counter"> </p>
<button id="pauseInterval">Pause</button></p>
I've been looking for this fast and easy approach for ages, so I'm posting several versions to introduce as many people to it as possible.

Deduct Timer Count Every Page Refresh (Vanilla Javascript)

I am absolutely a noob when it comes to Javascript so I hope someone can help me please. I made a very simple Vanilla JS + HTML code that counts the number of times that it reaches 10 seconds (10 seconds = 1 count). This code will also refresh the page onmouseleave and when I change tab using window.onblur. My problem is that every time the page refreshes, the counter will go back to zero. What I want is that for the counter to deduct just one (or a specific number of) count every page refresh instead of completely restarting the count to zero. Please help me with Vanilla Javascript only and no JQuery (because I am planning to use this code personally and offline). Thank you in advance.
For those who may wonder what's this code is for, I want to create this to encourage myself to stay away from my computer for a certain period everyday. Like, if I can stay away from my computer for 100 counts, then I can use my computer freely after. I am addicted to the internet and I want to make this as my own personal way of building self-control.
Here is my code:
<style>
label {
color: orange;
}
p {
border-radius: 0px;
color: black;
text-decoration: none;
font-family: Consolas !important;
font-size: 16px;
font-weight: normal;
outline: none;
line-height: 0.25 ;
}
</style>
<body onmouseleave="window.location.reload(true)">
<p>You have earned <label id="pointscounter">00</label> point/s.</p>
<script>
var PointsLabel = document.getElementById("pointscounter");
var totalCountPoints = 0;
setInterval(setTimePoints, 10000);
function setTimePoints() {
++totalCountPoints;
PointsLabel.innerHTML = pad(totalCountPoints);
}
function pad(val) {
var valString = val + "";
if (valString.length < 2) {
return "0" + valString;
} else {
return valString;
}
}
</script>
<script>
var blurred = false;
window.onblur = function() { blurred = true; };
window.onfocus = function() { blurred && (location.reload()); };
</script>
</body>
Storage
If you want the data to survive a reload, you need to save it somewhere. There are multiple options you can use. I used localStorage. You can learn more about it here: https://www.w3schools.com/jsref/prop_win_localstorage.asp. localStorage even survives closing the Browser Tab.
If you want to reset the data in a new session, you can use sessionStorage (just replace localStorage with sessionStorage): https://www.w3schools.com/jsref/prop_win_sessionstorage.asp.
What I did:
Save data on blur
If a blur-event occurs, the data is saved.
I also stopped the interval because there is no need for the interval anymore.
blurred variable
There is (currently?) no need for this variable.
The only usecase seems to be:
window.onfocus = function() {
blurred && location.reload();
};
To my knowledge you don't need this variable here.
Comming back
If the user already has points in localstorage, the current Points are calculated based on the points in localstorage. It currently deducts 1 point.
Using onmouseleave
I replaced the location.reload(true) on the body-tag with a function call. Everytime the mouse leaves, it calls this function. This function calls the onBlur function. The onBlur function is there, to ensure, that both window.onblur and onmouseleave do the same thing (save & stop). After the onBlur function is called, an EventListener is added to wait for mouseenter. When the mouse is seen again, we can reload the page with the onFocus function. It wouldn't reload the page as soon as the mouse left, because the timer would start (bc of reload), even if the mouse wasn't on the document.
Todo:
There is currently no check to see, if a the mouse in on the document after a reload. The timer will begin, even if the mouse isn't on the document.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<style>
label {
color: orange;
}
p {
border-radius: 0px;
color: black;
text-decoration: none;
font-family: Consolas !important;
font-size: 16px;
font-weight: normal;
outline: none;
line-height: 0.25;
}
</style>
</head>
<body onmouseleave="mouseLeft()">
<p>You have earned <label id="pointscounter">00</label> point/s.</p>
<script>
var PointsLabel = document.getElementById("pointscounter");
var totalCountPoints = 0;
// Calculate Points if user has already collected points
if (localStorage.getItem("points") !== null) {
// You can change, how many points to deduct
const pointsToDeduct = 1;
var tempPoints = localStorage.getItem("points");
totalCountPoints = tempPoints - pointsToDeduct;
// Reset to 0 if points now negative
if (totalCountPoints < 0) {
totalCountPoints = 0;
}
PointsLabel.innerHTML = pad(totalCountPoints);
}
// need to save, to stop/clear it later
var timePointsInterval = setInterval(setTimePoints, 10000);
function setTimePoints() {
++totalCountPoints;
PointsLabel.innerHTML = pad(totalCountPoints);
}
function pad(val) {
var valString = val + "";
if (valString.length < 2) {
return "0" + valString;
} else {
return valString;
}
}
function mouseLeft() {
onBlur();
document.addEventListener("mouseenter", onFocus);
}
function onBlur() {
// save Current Points:
localStorage.setItem("points", totalCountPoints);
//stop the timer
clearInterval(timePointsInterval);
}
function onFocus() {
location.reload();
}
// Blur Detection
var blurred = false;
window.onblur = function () {
// [-] blurred = true;
onBlur();
};
window.onfocus = function () {
// [-] blurred && location.reload();
onFocus();
};
</script>
</body>
</html>

Function not triggering even though it's called

I'm writing a website, and part of it requires some text to appear as if it's being typed. However, one of my functions to do this (typewriter2) isn't working, even though it's called.
I've tried moving around the code, and testing it separately. The code runs fine, however the typewriter2 function just won't start.
var x = document.getElementById("businesscard");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
var i = 0;
var txt1 = "cd Info && cat Business Card";
var speed = 75;
function typeWriter() {
if (i < txt1.length) {
document.getElementById("cmd1").innerHTML += txt1.charAt(i);
i++;
setTimeout(typeWriter, speed);
} else {
BusinessCard();
}
}
function BusinessCard() {
var x = document.getElementById("businesscard");
if (x.style.display === "none") {
x.style.display = "block";
typeWriter2();
} else {
x.style.display = "none";
}
}
var txt = "cat Websites";
function typeWriter2() {
if (i < txt.length) {
document.getElementById("cmd2").innerHTML += txt.charAt(i);
i++;
setTimeout(typeWriter2, speed);
}
}
/* unvisited link */
a:link {
color: white;
}
/* visited link */
a:visited {
color: white;
}
/* mouse over link */
a:hover {
color: blue;
}
/* selected link */
a:active {
color: blue;
}
body {
background-color: #300A24;
color: white;
font-family: 'Ubuntu Mono', monospace;
}
<body onload="typeWriter()">
<link href="https://fonts.googleapis.com/css?family=Ubuntu+Mono&display=swap" rel="stylesheet">
<p id="cmd1">[dmeskin#code-u.org ~]$ </p>
<div id="businesscard"><p>Daniel Notmylastname<br> Student at notmyschoool<br> Systems Administrator<br>
http://code-u.org<br>
1byte#gmail.com<br>
+1(917)-555-6761<br><p id="cmd2">[dmeskin#code-u.org Info]$ </p>
What's supposed to be happening is that typeWriter2() starts after businesscard is unhidden, but it doesn't.
Using global variables will hurt you. It makes the code unpredictable, especially if you use the same variable in more than one function.
Another thing: Don't query the DOM for the element every time you need the element: Querying the DOM is expensive and should be avoided if possible (in your code it dosen't matter, but since th fix is so easy, I would like you to learn doing the right thing from the start.) In your code it is the same element that it was 75 milliseconds ago.
Yet another thing: Don't repeat yourself. If you write the same piece of code over and over in the same program, or with just another variable, it is time to move that to a function. Then you have ONE place too look at when you are troubleshooting, and ONE place to apply a fix if needed.
The example below is NOT perfect by any means. A modern variant would probably use arrow-functions, but I decided against that in this example, since they can be hard to read if you aren't used to it.
Here is a little improved version that reuses the same function for the typewriter effect.
// A function that hides and show the Business card depending on the given variable.
function setBusinessCardVisible (visibility) {
const elem = document.getElementById("businesscard");
elem.style.display = visibility ? 'block' : 'none';
}
// A generig typewriter that takes an object and callback as arguments.
// The arg object has:
// elem : the element that text shold be appended to
// cmd : The text that should be added
// delay : the delay between characters
function typeWriter (arg, callback) {
let index = 0; // set the index for this typewriter to 0.
// Get the elment ONE time, and resuse that.
arg.elem.textContent = arg.prompt;
const length = arg.cmd.length;
// Using setInteval to start ONE timer that will be called
// until it is cleared with clearInterval
let timer = setInterval(
function () {
// Add the character
arg.elem.textContent += arg.cmd.charAt(index);
// increment index and see if we are finished
if (index++ >= length) {
clearInterval(timer); // stop the timer
if (callback) callback(); // call callback if specified
}
},
arg.delay
);
}
// call this function to start the effect
function startTyping () {
const
elem1 = document.getElementById('cmd1'),
elem2 = document.getElementById('cmd2'),
delay = 75, // Set the delay here and reuse it below
cmdprompt1 = "[dmeskin#code-u.org ~]$ ", // Part one: hide the card.
cmdprompt2 = "[dmeskin#code-u.org Info]$ ";
elem1.textContent = cmdprompt1;
elem2.textContent = cmdprompt2;
// Part one: hide the card.
setBusinessCardVisible(false); // Start the first typewriter
typeWriter({
elem: elem1,
prompt: cmdprompt1,
cmd: "cd Info && cat Business Card",
delay: delay
}, function () { // part two, show the card
setBusinessCardVisible(true); // Start the secord typewriter
setTimeout( function() {
typeWriter({
elem: elem2,
prompt: cmdprompt2,
cmd: "cat Websites",
delay: delay
}, function () {
setTimeout(function () {
setBusinessCardVisible(false);
elem1.textContent = cmdprompt1;
elem2.textContent = cmdprompt2;
setTimeout(startTyping, 2000); // Restart after 2 seconds
}, 2000);
})
}, 2000) // delay after showing card
});
}
a,
a:link,
a:visited,
a:hover,
a:active {
color: blue;
}
body {
background-color: #300A24;
color: white;
font-family: monospace;
}
<body onload="startTyping()">
<p id="cmd1">[dmeskin#code-u.org ~]$ </p>
<div id="businesscard">
<p>Daniel Notmylastname<br> Student at notmyschoool<br> Systems Administrator<br>
http://code-u.org<br>
1byte#gmail.com<br>
+1(917)-555-6761<br>
<p id="cmd2">[dmeskin#code-u.org Info]$ </p>
</div>
</body>
The issue was that i was not set to the correct value, and had to be renamed.

JS & HTML - place on html on which the JS script will appear

I'm quite new to JS.
I want to have my html page stay the same when JS text will be appearing in one exact place without starting from blank page.
I trigger JS function via button on HTML, function in HTML:
function match () {
setTimeout(function () {
player_hp -= monster_dmg
monster_hp -= player_dmg
if (player_hp<=0) {
document.write("\nPlayer dies!")
menu();
return;
}
if (monster_hp<=0) {
document.write("\nPlayer wins!")
menu();
return;
}
if (fight=1) {
document.write("\nPlayer hp:" + player_hp)
document.write("\nMonster hp:" + monster_hp)
document.write("\n");
match()
}
}, interval)
}
One easy way to handle this is to simply create a <div> or a <span> element that has an ID attribute like this:
<div id="status"> </div>
Now you can access this element by using the Javascript method
document.querySelector("#status") and then use the innerHTML function of that element to change the internal content. You can even place the document.querySelector function into a convenient function which I have named send_status()
Here's the whole thing
/* default values */
var player_hp = 300;
var monster_dmg = 30;
var monster_hp = 200;
var interval = 500;
var player_dmg = 50;
match();
/* heres a function that will replace your document.write() functions */
function send_status(message) {
document.querySelector("#status").innerHTML = message;
}
function match() {
setTimeout(function() {
player_hp -= monster_dmg
monster_hp -= player_dmg
if (player_hp <= 0) {
send_status("\nPlayer dies!") // replaced document.write with send_status
menu();
return;
}
if (monster_hp <= 0) {
send_status("\nPlayer wins!")
menu();
return;
}
if (fight = 1) {
send_status("\nPlayer hp:" + player_hp)
send_status("\nMonster hp:" + monster_hp)
send_status("\n");
match()
}
}, interval)
}
function menu() {}
#game {
width: 100%;
height: 100px;
border: 2px solid black;
}
#status {
width: 100%;
height: 50px;
background-color: grey;
}
<div id="game">Game Goes Here</div>
<!-- here is your status area -->
<div id="status"></div>
You should create a results div, in which will be shown the match result.
Just add <div id="match_results"></div> in your HTML code.
And replace all yours document.write() for
document.getElementById('match_results').innerHTML += "<br>Player wins!"
This command is appending content in the element with ID match_results.
You should use <br> instead of \n because it is the proper way to break line in HTML code.

I am having trouble making a javascript typewriter effect

Its supposed to type one letter at a time when you open the page, however, it is not showing up at all. I'm a newbie at this javascript stuff.
HTML
<div class="wrap">
<div class="test type" data-text="Hi, my name is John Doe"></div>
</div>
CSS
body {
font: 16px/20px sans-serif;
}
.wrap {
width: 500px;
margin: 30px auto;
text-align: center;
}
.test {
margin-top: 10px;
text-align: left;
}
JS
function typeWriter(text, n) {
if (n < (text.length)) {
$('.test').html(text.substring(0, n+1));
n++;
setTimeout(function() {
typeWriter(text, n)
}, 100);
}
}
$('.type').click(function(e) {
e.stopPropagation();
var text = $('.test').data('text');
typeWriter(text, 0);
});
Use this, I made it worked in less code.
Another thing i did is used some random time to give real world effect..
$(function(){
var txt = $(".type").data("text").split("");
txt.forEach(function(chr, i){
var rand = Math.floor(Math.random() * 100) + 1;
setTimeout(function(){
$(".type").append( chr );
},300*(i+1) + rand)
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test type" data-text="Hi, my name is John Doe"></div>
$(function(){
function typeWriter(text, n) {
if (n < (text.length)) {
$('.test').html(text.substring(0, n+1));
n++;
setTimeout(function() {
typeWriter(text, n)
}, 100);
}
}
$('.type').click(function(e) {
e.stopPropagation();
var text = $('.test').data('text');
typeWriter(text, 0);
});
});
body {
font: 16px/20px sans-serif;
}
.wrap {
width: 500px;
margin: 30px auto;
text-align: center;
}
.test {
margin-top: 10px;
text-align: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrap">
<div class="test type" data-text="Hi, my name is John Doe">Click me</div>
</div>
You needed to add something to click. (I added the text 'click me' in the div).
You may miss the CDN.
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>
Your codes are good.
Here's another example JavaScript code that types out a string one letter at a time, with a delay of 500 milliseconds between each letter:
const myString = "Hello, world!"; // The string to be typed out
let i = 0; // Index of the current letter to be typed out
function typeString() {
if (i < myString.length) { // Check if there are more letters to type out
document.getElementById("myText").innerHTML += myString.charAt(i); // Add the next letter to the text
i++; // Increment the index for the next letter
setTimeout(typeString, 500); // Call this function again in 2 seconds
}
}
typeString(); // Call the function to start typing out the string
<div id="myText"></div>
This code uses a recursive function called typeString() that checks if there are more letters to type out, adds the next letter to a specified HTML element using the innerHTML property, increments the index for the next letter, and then sets a delay of 2 seconds using the setTimeout() method before calling itself again to type out the next letter. The function is called initially to start typing out the string. Note that you should replace "myText" in the code with the ID of the HTML element where you want the string to be displayed.

Categories