How can I slow down this js with setTimeout? - javascript

I want to slowly rotate the letters in a string using 2 second pauses.
I'm trying to use setTimeout(function, delay) but it doesn't pause it runs the entire script in under a second. How can I do this?
My code is at https://jsfiddle.net/6un4xhuj/
<html>
<head>
<link type="text/css" href="style.css">
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<h1>JS</h1>
<h2 id='for'>For: String Rotations</h2>
<h3 id='result'>Result:</h3>
<h4></h4>
<span id="end_of_results"></span>
<script src="main.js"></script>
</body>
</html>
js:
'use strict';
function display(string) {
$("span#end_of_results").before( $( "<h4>" + string + "</h4>" ) );
}
var string="rotate me";
for (var i = 0; i <= string.length; i++) {
setTimeout(display(string), 2000);
string=string[0,string.length - 1] + string.slice(0,-1);
}
I get this output but all of it immediately, not step by step.

Get rid of the loop and just recurse the same function passing in the string each time. This code repeats without end so you might want to add a condition as per your requirements.
function thing(string) {
string = string[0, string.length - 1] + string.slice(0,-1);
$("h2#result").html( $( "<h3>" + string + "</h3>" ) );
setTimeout(thing, 2000, string);
}
thing(string);
DEMO

setTimeout takes a function in your argument. In your code setTimeout(display(string), 2000);, you pass the result of invoking the function display(string) into setTimeout. To make this more evident, assign it to a variable like this:
var result = display(string); // undefined
setTimeout(result, 2000); // Not right
You'll need to use something like bind, or just create a function that returns a function:
setTimeout(function () {
// Modify your string here
string=string[0,string.length - 1] + string.slice(0,-1);
display(string)
}, 2000);

setTimeout is async, which means the for loop is completing immediately. Also... you are calling display directly instead of passing the function reference. The same algorithm using callbacks would be like this:
jsfiddle: https://jsfiddle.net/w1x0csp9/
'use strict';
var i = 0;
var string="rotate me";
function display() {
if(i > string.length) {
return;
}
$("span#end_of_results").before( $( "<h4>" + string + "</h4>" ) );
string = string[0,string.length - 1] + string.slice(0,-1);
i++;
setTimeout(display, 2000);
}
display();

I've accepted andy's answer, also based on it, I create this version to only scroll once:
<h1>JS</h1>
<h2 id='for'>For: String Rotation</h2>
<h2 id='result'>Result:</h2>
'use strict';
function rotate(string) {
string = string[0, string.length - 1] + string.slice(0,-1);
$("h2#result").html( $( "<h3>" + string + "</h3>" ) ).animate(100);
rotations+=1
if (rotations > string.length) {
return;
}
setTimeout(rotate, 50, string);
}
var string="rotate this string ";
var rotations=0
rotate(string);
fiddle at https://jsfiddle.net/xb865yw6/3/

You are beginning the 2 second wait immediately for all instances of setTimeout. The simplest way to fix your code is to increase the wait each time you go through your loop:
change this:
setTimeout(display(string), 2000);
to this:
setTimeout(display(string), (i+1)*2000);
Alternatively you could make a single HTML element update on a 2 second interval using setInterval() like this:
<div class="rotating-text"> rotate me</div>
<script>
setInterval(function(){
$('.rotating-text').each(function(){
var string = $(this).text();
string = string[0,string.length - 1] + string.slice(0,-1);
$(this).text(string);
});
}, 2000);
</script>
This example applies to everything with a class rotating-text
http://codepen.io/t3hpwninat0r/pen/eZVYqw

You can use .queue() , .delay()
"use strict";
var elem = $("h2#result");
var string = "rotate this string";
elem.append("<br>" + string)
.queue("_fx", $.map(Array(string.length), function(value) {
return function(next) {
string = string[0,string.length - 1] + string.slice(0,-1);
$(this).delay(2000).queue(function() {
$(this).append("<br>" + string).dequeue();
next()
})
}
})).dequeue("_fx")
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<h1>JS</h1>
<h2 id='for'>For: String Rotation</h2>
<h2 id='result'>Result:</h2>

Related

How do I insert Javascript into a web page

Need help putting this javascript into this HTML code ( i'm new to coding )
<img id="coin"/><br/>
<button id="toss">Toss</button><br/>
<div id="count"></div>
HTML ^
var current = 3;
var elem = document.getElementById('toss');
var intervalId = setInterval( function(){
if( current > 0 ){
elem.innerHTML = "<h1>" + current + "</h1>";
} else {
if( Math.random() > .5 ){
elem.innerHTML = '<img src="http://csgowild.com/assets/images/terrorist.png">';
} else {
elem.innerHTML = '<img src="http://vignette1.wikia.nocookie.net/cswikia/images/4/4c/Csgo_CT_icon_alt.png/revision/latest?cb=20151222191721">';
}
clearInterval( intervalId );
}
current--;
}, 1000 ); // 1000 ms = 1s
Javascript ^
Edit: to make it work on the click of the button not the following changes:
I added an `onclick' event to your button, and I wrapped the intervalId function in another function. setInterval, the way you had it, fired immediately, now it is associated with the press of the button.
Here you go, just put it in a script tag like so, all in your HTML file:
working Fiddle
<img id="coin"/><br/>
<button id="toss" onclick=intervalId();>Toss</button><br/>
<div id="count"></div>
<script>
var current = 3;
var elem = document.getElementById('toss');
var intervalId = function() {setInterval( function(){
if( current > 0 ){
elem.innerHTML = "<h1>" + current + "</h1>";
} else {
if( Math.random() > .5 ){
elem.innerHTML = '<img src="http://csgowild.com/assets/images/terrorist.png">';
} else {
elem.innerHTML = '<img src="http://vignette1.wikia.nocookie.net/cswikia/images/4/4c/Csgo_CT_icon_alt.png/revision/latest?cb=20151222191721">';
}
clearInterval( intervalId );
}
current--;
}, 1000 ); // 1000 ms = 1s
}
</script>
I think you can take it from here
Welcome to coding, and welcome to StackOverflow!
There are two ways to include Javascript (or CSS eg.)
1: Embed it directly into your HTML file
<script>
// Your code here
</script>
This is recommended for small code snippets. If you need much Javascript, possibility number two would make more sense.
2: Include as own file
You can also save your Javascript code as - for example - "script.js" and add
the followig to your HTML file:
<script src="/path/to/script.js"></script>
Remember to use the correct path.

Simple JavaScript image rotator

I have a simple image rotator on a website consisting of 4 images that have to appear for a few seconds before showing the next one. It seems to work on its first cycle but then when it gets back to the first image it doesn't show that one but works again from the second image and so on always missing that image on every cycle.
The function is called using onLoad EH in the body. In the body there is an img with my first image inside it. I'm a noob so please be gentle if I've missed anything out.
Here's what I have...
<body onLoad="sunSlideShow()">
<img src="IMAGES/slider1.gif" alt="slide-show" id="mySlider" width="900">
<body>
var quotes = new Array ("slider2.gif", "slider3.gif" ,"slider4.gif", "slider1.gif");
var i = 0
function sunSlideShow()
{
document.getElementById("mySlider").src = ( "IMAGES/" + quotes[i] );
if (i<4)
{
i++;
}
else
i = 1;
setTimeout("sunSlideShow()", 3000);
}
sunSlideShow()
Change it to this:
else
i = 0;
setTimeout("sunSlideShow()", 3000);
Further to my other answer (which was wrong!)... Try this:
http://jsfiddle.net/pq6Gm/13/
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
setInterval(sunSlideShow,3000);
});
var quotes = [
"http://static.guim.co.uk/sys-images/Guardian/Pix/pictures/2007/07/11/sun128.jpg",
"http://icons.iconarchive.com/icons/robinweatherall/seasonal/128/sun-icon.png",
"http://www.astronomytoday.com/images/sun3.gif",
"http://mariusbancila.ro/blog/wp-content/uploads/2011/08/sun.png"
];
var i = 0;
function sunSlideShow() {
document.getElementById("mySlider").src = quotes[i];
if (i < (quotes.length-1))
{
i++;
}
else
{
i = 0;
}
}
</script>
<body>
<img src="http://mariusbancila.ro/blog/wp-content/uploads/2011/08/sun.png" id="mySlider"/>
</body>
==================================================================
EDIT: This is wrong... please find my other answer on this page.
==================================================================
To start with, I wouldn't use ... you're better off starting the script with jquery once the page is loaded.
Add this to your head section:
<script type="text/javascript">
$(function () {
sunSlideShow();
}
</script>
That will fire the sunSlideShow function once the page is loaded.
Then, you're starting your slideshow with var i = 0... but when you've got to the fourth image, you're setting it to 1?
I would be tempted to use a while loop to achieve what you want.
Something like this:
<script type="text/javascript">
$(function () {
sunSlideShow();
}
var quotes = new Array ("slider2.gif", "slider3.gif" ,"slider4.gif", "slider1.gif");
var i = 0;
function sunSlideShow(){
while (i<4)
{
document.getElementById("mySlider").src = ( "IMAGES/" + quotes[i] );
if (i<4)
{
i++;
}
else
{
i = 0;
}
sleep(3000);
}
}
function sleep(miliseconds){
var currentTime = new Date().getTime();
while (currentTime + miliseconds >= new Date().getTime()){}
}
</script>
This script hasn't been tested... but it should start the sunSlideShow function once the page has loaded and then change the image every 3 seconds.
I too searched the web trying to find a general solution to the problem of rotating an image about its center. I came up with my own solution which works perfectly. The basic concept is simple: rotate the entire context by the desired angle (here called 'tilt'); calculate the image's coordinates in the NEW coordinate system; draw the image; lastly, rotate the context back to its original position. Here's the code:
var xp = rocketX * Math.cos(tilt) - rocketY * Math.sin(tilt);
var yp = rocketX * Math.sin(tilt) + rocketY * Math.cos(tilt);
var a = rocketX - xp;
var c = Math.sqrt(a*a + (rocketY-yp)*(rocketY-yp));
var beta = Math.acos(a/c);
var ap = c * Math.cos(tilt + beta);
var bp = c * Math.sin(tilt + beta);
var newX = rocketX + ap;
var newY = rocketY - bp;
context.rotate(tilt);
context.drawImage(littleRocketImage, newX-9, newY-40);
context.rotate(-tilt);
In the penultimate line, the constants '9' and '40' are half the size of the image; this insures that the rotated image is placed such that its center coincides with the center of the original image.
One warning: I use this only for first quadrant rotations; you'll have to put in the standard tests for the other quadrants that change the signs of the components.
Update: 2021
You can use the light-weight library Ad-rotator.js to setup simple Ad-rotation like this -
<script src="https://cdn.jsdelivr.net/npm/ad-rotator"></script>
<script>
const instance = rotator(
document.getElementById('myelement'), // a DOM element
[ // array of ads
{ url: 'https://site1.com', img: 'https://example/picture1.jpg' },
{ url: 'https://site2.com', img: 'https://example/picture1/picture2.jpg'},
// ...
]
);
</script>
<body onLoad="instance.start()">
<div id="myelement"></div>
<body>
Reference Tutorial

Write sequence of random numbers in javascript to paragraph

Really a newbie question but I can't seem to find the answer. I need to have this html file show a bunch of random numbers, separated by 1 second intervals. For some reason (maybe obvious) it is only showing me the last one unless I have 1 alert after each random number generated. How can I correct this?
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var randomnumber
var message
function placePossibleWinner()
{
randomnumber=Math.floor(Math.random()*11);
message="Teste ";
message=message.concat(randomnumber.toString());
document.getElementById("WINNER").innerHTML=message;
//alert(".")
}
</script>
</head>
<body>
<script type="text/javascript">
function runDraw()
{
var i=1
alert("start")
while (i<20)
{
setTimeout("placePossibleWinner()",1000)
i++
}
}
</script>
<h1>H Draw</h1>
<p id="WINNER">Draw</p>
<p></p>
<button onclick="runDraw()">Get me winner!</button>
</body>
</html>
Thanks in advance for any answers/comments.
The problem is all your setTimeouts are being triggered at the same time. Adding alerts pauses the JavaScript execution, so you see each number. Without that, after 1 second, all 19 setTimeouts run (one after another) and you just see one number (the screen is updated so fast, you just see one).
Try using setInterval instead.
function runDraw() {
var i = 1;
var interval = setInterval(function(){
if(i < 20){
placePossibleWinner();
i++;
}
else{
clearInterval(interval);
}
}, 1000);
}​
This will run the function once every second, until i is 20, then it will clear the interval.
I believe you want setInterval instead. using setTimeout in a loop will just queue up 20 calls immediately and they will all fire at once 1 second later. Also, you are setting the innerHTML of the p which will overwrite any previous text.
function placePossibleWinner() {
// add a var here, implicit global
var randomnumber=Math.floor(Math.random()*11);
// add a var here, implicit global
message="Teste " + randomnumber + '\n'; // new line
document.getElementById("WINNER").innerHTML += message; // concat, don't assign
}
function runDraw() {
var counter = 1;
var intervalID = setInterval(function () {
if (counter < 20) {
placePossibleWinner();
counter++;
} else {
clearInterval(intervalID);
}
}, 1000);
}
You are resetting your message in your functions and you are calling placePossibleWinner() the wrong way... you want to use setInterval. Below is a modification of your html/javascript
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var randomnumber;
var message = "Teste ";
var timesCalled = 0;
var funtionPointer;
function placePossibleWinner()
{
timesCalled++;
randomnumber=Math.floor(Math.random()*11);
message=message.concat(randomnumber.toString());
document.getElementById("WINNER").innerHTML=message;
if (timesCalled > 20)
{
clearInterval(functionPointer);
}
}
</script>
</head>
<body>
<script type="text/javascript">
function runDraw()
{
var i=1
alert("start")
functionPointer = setInterval(placePossibleWinner,1000)
}
</script>
<h1>H Draw</h1>
<p id="WINNER">Draw</p>
<p></p>
<button onclick="runDraw()">Get me winner!</button>
</body>
</html>
To start with,
setTimeout("placePossibleWinner()",1000)
should be
setTimeout(placePossibleWinner,1000)
The parameter to setTimeput should be a reference to a function. See JavaScript,setTimeout

How can I optimize this recursive function which calls setTimeout()

The following function is using 100% of a CPU core on my computer. Is there a way I could rewrite it to be non-recursive? Would that fix it or is it because my CPU sucks? Are others seeing the same performance problems on their computer?
Code:
<html>
<head>
<script type="text/javascript" src="jquery-1.7.1.js"></script>
<script type="text/javascript">
function timeMsg(n,max,delay)
{
writeToLog(n + "th: &#" + n,n);
var temp = n + 1;
if(n < max){
var t=setTimeout("timeMsg(" + temp + "," + max + "," + delay + ")",delay);
}
}
function writeToLog(text,n){
$("#log").html($("#log").html() + text + "<br/>");
//autoscrolling: doesn't work...'
}
</script>
</head>
<body>
<form>
<input type="button" value="Display alert box in 3 seconds" onClick="timeMsg(0,100000,100)" />
</form>
<div id="log"></div>
</body>
Instead of repeatedly calling setTimeout with slightly-different values, you could setup a global variable to track the current iteration, and use one call to setInterval() instead. setInterval is like setTimeout, except it will keep running indefinitely - you don't have to call it over and over again. That might help, a bit.
That should not be using 100% CPU. (But the actual performance is dependent on the size of your document.) However, one obvious improvement is to get rid of the implicit eval in setTimeout:
function timeMsg(n, max, delay) {
writeToLog(n + "th: &#" + n, n);
var temp = n + 1;
if(n < max) {
var t = setTimeout(function() {
timeMsg(temp, max, delay);
}, delay);
}
}
You should also use append in place of the double-html (anti-)pattern you're currently employing:
function writeToLog(text,n){
$("#log").append(text + "<br/>");
}
There's no need to search for #log twice (reading its html both times).
Use setInterval() to start and clearInterval() when you reach your max.
Demo: http://jsfiddle.net/ThinkingStiff/PwASf/
Script:
var timer;
function startMsg( n, max, delay ) {
timer = window.setInterval( function() {
timeMsg( n++, max );
}, delay );;
};
function timeMsg( temp, max ) {
writeToLog(temp + "th: &#" + temp, temp);
if( temp == max ){
window.clearInterval( timer );
}
}
function writeToLog(text,n){
$(' #log' ).append( text + '<br/>' );
}
startMsg( 1, 10, 1000 );
HTML:
<div id="log"></div>
No, even as written, it doesn't use 100% CPU for me.
First thing you should do is change your writeToLog function. It is must faster to append an HTML block than to 1) read the existing HTML, 2) add the text+BR, 3) write the whole thing back in.
function writeToLog(text,n){
$("#log").append(text + "<br/>");
//autoscrolling: doesn't work...'
}
Other than that, if you want to not block other JS from running, then you need to use the setTimeout/setInterval method of implementing this loop. Otherwise a regular for loop is faster.

Javascript recursion on mouseOver not working?

The following code is supposed to gently vary the color of a tab, which i pass into the function. However, the gradient only increases every new time that i enter the tab, instead of increasing the one time i put the mouse over...
<script type = "text/javascript">
hex=255;
function fadetext(element){
if(hex>0) {
hex-=11;
element.style.backgroundColor="rgb("+hex+","+hex+","+hex+")";
setTimeout("fadetext(element)",50);
}
else
hex=255;
}
</script>
<div id="tabs">
<ul>
<li>Personal details</li>
</ul>
</div>
For the timeout, element is undefined when using it as text. You should use an anoymous function:
var elem=element;//I find that this is needed in some browsers
setTimeout(function(){fadetext(elem);},50);
For what it's worth, you are missing a closing bracket } at the end of fadetext.
You're missing the curly brace to end the function:
<script type = "text/javascript">
hex=255;
function fadetext(element){
if(hex>0) {
hex-=11;
element.style.backgroundColor="rgb("+hex+","+hex+","+hex+")";
setTimeout("fadetext(element)",50);
}
else
hex=255;
}
} // You're missing this one here
</script>
Try replacing the setTimeout() call with:
setTimeout(function(){fadetext(element);},50);
A more robust approach, with smooth animation. Usage: fadeText("elementid", 1000);
Also, you can reuse this for any kind of animation. Just change the values between you interpolate, and the style setting part.
function interpolate( start, end, pos ) {
return start + ( pos * (end - start) );
}
function fadeText( dom, interval, delay ) {
interval = interval || 1000;
delay = delay || 10;
var start = Number(new Date());
if ( typeof dom === "string" ) {
dom = document.getElementById( dom );
}
function step() {
var now = Number(new Date()),
elapsed = now - start,
pos = elapsed / interval,
value = ~~interpolate( 255, 0, pos );
dom.style.backgroundColor =
"rgb("+value+","+value+","+value+")";
if ( elapsed < interval )
setTimeout( step, delay );
}
setTimeout( step, delay );
}

Categories