I've found a few other questions pertaining to this, but the answers didn't work for me, so I'm checking to see if there's anything newer or something that will work. Essentially, I'm updating divs in a .each in jQuery, but I want them to update a couple seconds apart. Here's what I've tried:
function randomColor() {
$('div').each(function(i) {
setTimeout(function() {
var colors = ['blue', 'green'];
var n = Math.floor(Math.random() * colors.length);
var color = colors[n];
$(this).addClass(color);
}, 500 + (i * 500));
});
}
I've also tried using a separate function:
function randomColor() {
$('div').each(function(i) {
var time = 500;
setTimeout(function() {
applyColor($(this));
}, time);
time += 500;
});
}
function applyColor(div) {
var colors = ['blue', 'green'];
var n = Math.floor(Math.random() * colors.length);
var color = colors[n];
$(div).addClass(color);
}
Both of these return no errors, but the divs don't get updated. If I run this code without the setTimeout, it works perfectly. I've also tried using delay in this fashion:
$('div').delay(1000).each(function() {
...
});
And that delayed by 1 second, but then updated everything at once after that second. If I move the delay down near the addClass line, it stops working altogether again. Can anyone point out this (hopefully simple) mistake?
You're creating an anonymous function and inside that function this has a different meaning (i.e., the window object).
One solution is to cache this:
var $this = $(this);
setTimeout(function() {
var colors = ['blue', 'green'];
var n = Math.floor(Math.random() * colors.length);
var color = colors[n];
$this.addClass(color);
}, 500 + (i * 500));
I think what you want to do is:
function randomColor() {
var colors = ['blue', 'green'];
var n = Math.floor(Math.random() * colors.length);
var color = colors[n];
$('div').each(function() {
$(this).delay(1000).addClass(color);
});
});
When fuction is run, it would randomly pick a Class name ('blue' or 'green'). It would then update the DIV after waiting 1 second. Then move to the next in the Each loop.
Here's an example using setTimeout and an increment'er to loop over the divs, rather than the jQuery each method.
JSFiddle
(function randomColorDiv(ii) {
var colors = ['blue', 'green']
var n = Math.floor(Math.random() * colors.length)
var color = colors[n]
$($('div')[ii]).addClass(color)
if ( ii < $('div').length ) {
setTimeout(function() {
randomColorDiv(++ii)
}, 1000)
}
}(0))
Related
I am working on a random quote/color generator. I want it to avoid repeating previous color (in a simple/easy/understandable way as I'm a complete beginner in JS/jQuery).
Here is my code, I don't know what is wrong with it.
var colors = ["#8ee5ee", "#ee82ee", "#469649", "#ff4444", "#ffa500", "#dddddd", "#efc3c8", "#d2d449", "#f91589","#906161","#875d39","#ffdab9","#d1e529","#3a718b"];
var color = Math.floor(Math.random() * colors.length);
var lastcolor = 0;
while(color === lastcolor){
color = Math.floor(Math.random() * colors.length) + 1;
}
$("body").animate({backgroundColor: colors[color]}, 1000);
$("#new-quote").animate({backgroundColor: colors[color]}, 1000);
$("h6").fadeOut(1000);
$("p").fadeOut(1000);
});
});
Basically, when I click a button (#new-quote), the current background color changes to another random color and so on. But now and then the color doesn't change as the machine chose the same number/color as the current one. I'm trying to avoid that!
I guess there's some sort of loop around the code you provided. Then you shouldn't reset the color, but to assign it to the previous one.
var colors = ["#8ee5ee", "#ee82ee", "#469649", "#ff4444", "#ffa500", "#dddddd", "#efc3c8", "#d2d449", "#f91589","#906161","#875d39","#ffdab9","#d1e529","#3a718b"];
var color = Math.floor(Math.random() * colors.length);
while(color === lastcolor){
color = Math.floor(Math.random() * colors.length) + 1;
}
lastcolor = color;
And of course you should define your lastcolor at the beginning of the script. Place
var lastcolor = 0;
after <script> tag opens.
You could use simply a new random value, because if you add one, you might get undefined if the random value is the index of the last element.
while (color === lastcolor){
color = Math.floor(Math.random() * colors.length); // + 1;
// without ^^^^^^^
}
A better style would be one assignment with a do ... while loop.
var colors = ["#8ee5ee", "#ee82ee", "#469649", "#ff4444", "#ffa500", "#dddddd", "#efc3c8", "#d2d449", "#f91589", "#906161", "#875d39", "#ffdab9", "#d1e529", "#3a718b"],
color,
lastcolor = 0;
do {
color = Math.floor(Math.random() * colors.length);
} while(color === lastcolor);
lastcolor = color;
Simpler method: Use splice() method to remove the current element from your colors array so that every time you run the code, the previously occurring element wont occur again.
var color = Math.floor(Math.random() * colors.length);
//from index = color, delete that element using splice(index, # of elements to delete)
colors.splice(color, 1);
//now colors array will not contain the colors[color] element
for (var i = 0; i < colors.length; i++) {
console.log(colors[i]);
}
How can I run this every few second , without blocking the rest of the pagefrom loading.
function Create() {
var SomeArray = [];
for ( var i=0; i<=1 ; i ++) {
SomeArray[i] = (Math.random() * 10) + 1;
//alert(arr[0]);
}
return SomeArray;
}
var x = Create();
alert(x[0] + x[1]);
I was trying this var timer = setInterval(Create, 5000); it prevent loading rest of the page.
i want to get new values every few seconds
A basic example would be:
var counter = 0;
var timerRef;
var increment = function() {
counter += 1;
console.log(counter);
timerRef = setTimeout(increment, 1000);
}
setTimeout(increment, 1000);
// clearTimeout(timerRef);
Please avoid document.write refer the screencast for further details.
setInterval() can be configured to repeatedly call any function you designate at whatever time interval you request. But, you can't retrieve a return value from that function. Instead, you need to process the results from within the callback that you pass to setInterval() or call some other function and pass the results you generate inside the callback. This is how asynchronous functions work in JavaScript. I've provided several examples below of your options:
If you just want to generate two random decimal values between 1 and 10 (inclusive) every 5 seconds, you can do that like this:
var interval = setInterval(function() {
var rand1 = (Math.random() * 10) + 1;
var rand2 = (Math.random() * 10) + 1;
// now insert code here to do something with the two random numbers
}, 5000);
If you wanted the random values to be integers (which is more common), then you would do this:
var interval = setInterval(function() {
var rand1 = Math.floor(Math.random() * 10) + 1;
var rand2 = Math.floor(Math.random() * 10) + 1;
// now insert code here to do something with the two random numbers
}, 5000);
If you want to call a function and pass it those two random numbers, you can do this:
function processRandoms(r1, r2) {
// code here to do something with the two random numbers
}
var interval = setInterval(function() {
var rand1 = Math.floor(Math.random() * 10) + 1;
var rand2 = Math.floor(Math.random() * 10) + 1;
processRandoms(rand1, rand2);
}, 5000);
You can then stop the recurring interval at any time with this:
clearInterval(interval);
The behaviour I want is this: The background color changes to say, gold, and remains that color for say X length of time. Then, background color changes to say, red, and remains that color for say Y length of time. The background color then changes back to gold and remains that color for X length of time. Then the background color changes back to red and stays that way for Y length of time. This whole kit and caboodle executes in a loop-style fashion for Z number of times and then ends.
I've tried putting setInterval'd functions into a for loop (in order to count the number of times we make the change) but have found that all of the functions that have been set to setInterval themselves all start running the interval timers at the same time (not in sequence).
I hope this is clear. Here is a JSFiddle of my efforts: http://jsfiddle.net/6WE6s/3/ I've managed to get the background color to change in a even pattern, but I want the pattern described above and I'm confused as to what to do next.
Thanks in advance for the help! :)
var colors = [
['gold', 2000], // X = 2000 miliseconds
['red', 1000] // Y = 1000
],
repeat = 3, // Z = 3,
index = 0, // current position in colors array
changeColor = function( ) {
// if index == colors.length then mod = 0
var mod = index % colors.length;
if(!index || mod || --repeat ) {
index = mod;
var data = colors[ index++ ]; // data = [ currentColor, currentColorTimeout ]
document.body.style.background = data[0];
setTimeout( changeColor, data[1] ); // and so on
}
//if index >0 && index == last
//then decrement `repeat` and check if is == 0
//nothing to do :)
};
changeColor(); // run
This is a simple example. You can make function with arguments(colors,repeats) and its body as above.
Note:
setInterval isn't suitable for this purpose because in setInterval you pass timeout once
If repeat initially is 0 will be an infinite number of repetitions
Don't use setInterval(). With setTimeout() you can do something like this:
function changeColors(colors, repeats) {
var i = 0;
if (typeof repeats === "undefined")
repeats = 1;
function doNext() {
if (i >= colors.length){
if (--repeats > 0)
i = 0;
else
return;
}
$('body').css('background-color', colors[i].color);
setTimeout(doNext, colors[i++].delay);
}
doNext();
}
changeColors([{color : "gold", delay : 2000},
{color : "red", delay : 4000}],
3);
You can add as many colours as you like, each with their own delay, by adding more elements to the array you pass to changeColors(). The function will go through the colours in turn, and do the whole sequence the number of times specified in the repeats parameter.
Demo: http://jsfiddle.net/nnnnnn/6WE6s/10/
Here's my effort - no jQuery required:
function colorCycle(el, count, cols) {
var i = 0,
n = cols.length;
// allow this to work on any element given its ID
el = (typeof el === "string") ? document.getElementById(el) : el;
if (n === 0) {
return; // no colours?
} else if (n === 1) {
count = 1; // don't trigger any timers if there's only one colour
}
// all of the hard work is done here
(function repeat() {
var interval = cols[i][1];
el.style.backgroundColor = cols[i][0];
// only do the whole cycle "count" times - 0 = forever
if (++i === n) {
if (count && !--count) {
return;
}
i = 0;
}
setTimeout(repeat, interval); // call myself
})(); // IIFE starts the cycle straight away
};
colorCycle(document.body, 5, [
['red', 1000],
['gold', 500]]);
See http://jsfiddle.net/alnitak/42PeT/
Abstain from using setInterval. Reference here.
EDIT: I've missed the different delay in calls.
var colors = ["#FF0000", "#00FF00", "#0000FF"];
var times = [1000, 2000, 3000];
var backgroundColor = "";
var counter = 0;
var changeBackground = function () {
// if we ran out of colors — do nothing: this simply goes out
// of the function, without continually calling setTimeout.
if (counter >= colors.length)
return;
// you fetch your new color here and increase the counter
// The counter keeps count of how many animations you've done.
backgroundColor = colors[counter];
// increase the counter to point to the next index of colors
// array you'll use in a subsequent call
counter++;
// do your magic voodoo change background animation here.
// I'm just doing a console.log() to be sure this works.
// Your question was framework agnostic, the answer should be too.
console.log(backgroundColor);
// setInterval to repeat
window.setTimeout(changeBackground, times[counter]);
}
window.setTimeout(changeBackground, times[counter]);
try this
var colors = [];
colors.push({color:"gold", time:4000}); //4000 X length of time
colors.push({color:"red", time:2000}); //2000 Y length of time
var numberofTimes = 50; //50 Z number of times
var $body;
var times = 0; // counter for tracking
var currentColor = {}; //currentColor info can be used to get the current
$(function(){
$body = $('body');
changeBG();
});
function changeBG()
{
currentColor = colors[times % colors.length];
$body.css('background-color',currentColor.color);
times++;
if(times<numberofTimes)
setTimeout(changeBG, currentColor.time);
}
check this quick DEMO
A basic example iterating an array of color and time arrays with setTimeout.
(function() {
var i = 0,
colorsTimes = [['gold', 'red', 'gold', 'red', 'gold'],
[2000, 4000, 2000, 4000, 2000]];
function switchColors() {
setTimeout(function() {
$('body').css('background-color', colorsTimes[0][i]);
if (++i < colorsTimes[0].length) switchColors();
}, colorsTimes[1][i]);
}
switchColors();
}());
Fiddle
Using setTimeout:
var doCount = (function() {
var count = 0;
var interval;
var limit = 5; // default
return function(num) {
limit = num || limit;
if (count < limit) {
count++;
console.log('running number ' + count);
interval = setTimeout(arguments.callee, 1000);
} else {
interval && clearTimeout(interval);
}
}
}())
Using setInterval:
var doCount = (function() {
var count = 0;
var interval;
var limit = 5; // default
return function(num) {
limit = num || limit;
if (interval) {
if (++count >= limit) {
interval && clearInterval(interval);
}
console.log('running number ' + count);
} else {
interval = setInterval(arguments.callee, 1000);
}
}
}())
The advantage of setTimeout is that you can adjust the time between runs to make it more regular, setInterval just tries to run as regularly as it can.
I'm building an animated scene with HTML, CSS, and Javascript. Currently I have 2 functions for each fish that I want to animate. The first to send it across the screen and the second to reset its position once its off the screen.
Here is what the 2 functions look like...
function fish1Swim1() {
var ranNum = Math.round(Math.random() * 2.5);
var speed = 6000 * ranNum;
var screenW = screenWidth+350;
$('#fish1').animate({
left: -screenW,
}, speed, function () {
fish1Swim2();
});
}
function fish1Swim2() {
var ranNum = Math.round(Math.random() * 7);
var top = ranNum * 100;
var screenW = screenWidth+350;
$('#fish1').css("left", screenW);
$('#fish1').css("top", top);
fish1Swim1();
}
I'm using very similar functions for all the other fish in the scene as well, but I'd like to create 2 arrays at the beginning of the script, one for the IDs and one for speed like so...
var fish=["#fish1","#fish2","#oldBoot"];
var speeds=["6000","7000","5000"];
Then have the function I wrote early run but replacing the fish and speed with the items from the arrays.
How can I do this?
How's this? This provides a generalalised function for all animation/CSS movement. Where animation is concerned, the speed is read from an array, as you wanted.
The function expects two arguments - the first, the ID of the element (minus #); the second, the phase (like in your original code - you had a phase 1 function for fish 1, and a phase 2 function for fish 1).
To make the function work for the other animatory elements, just extend the switch statements.
//element data and corresponding anim speeds
var speeds = {fish1: 6000, fish2: 7000, oldBoot: 5000};
//main animation/movement func
function do_action(id, phase) {
var el, jq_method, method_data, after;
//work out what it is we're doing, and to what, and set some details accordingly
switch (id) {
case 'fish1':
el = $('#fish1');
switch (phase) {
case 1:
jq_method = 'animate';
method_data = [
{left: -screenWidth+350},
Math.round(Math.random() * 2.5) * speeds[id],
function() { do_action('fish1', 2); }
];
break;
case 2:
jq_method = 'css';
method_data = [
{top: Math.round(Math.random() * 700), left: screenWidth+350}
];
after = function() { do_action('fish1', 1); };
break;
}
break;
break;
}
//do actions
el[jq_method].apply(el, method_data);
if (after) after();
}
//and off we go
do_action('fish1', 1);
I'm still struggling with my simple javascript game. Here is my previous question: Simple javascript game, hide / show random square
Some square show and hide randomely for a few seconds and you have to click on them. I use RaphaelJS to draw the square and a few of JQuery ($.each() function)
I can't make the hide/show with the setInterval working for each square. The function made by Mishelle looks good but I get a "This is not a function" error.. I've test different stuff but it's not as obvious as I thought :/
window.onload = function() {
var paper = new Raphael(document.getElementById('canvas_container'), 500, 500);
// random function to for the x and y axis of the square
function random(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var rectanglemain = paper.rect(0, 0, 500, 500).attr({fill: "white",});
var win_click = 0; // set the var to count the click on the square
var recs = [];
for(var i = 0; i < 50; i++) {
var x = random(1,450);
var y = random(1,450);
var rec = paper.rect(x, y, 50, 50).attr({fill: 'blue'});
recs.push(rec); // add the square in an array
recs[i].click(function () {
//counting the clicks
win_click = win_click + 1;
})
function hideSquare() {recs[i].hide();}
hideSquare();
}
rectanglemain.click(function () {
alert('you click on ' + win_click + ' squares');
});
/* here is a function made by Mishelle on my previous question, unfortunately I can't make it work (this is not a function error).
function showBriefly (timeFromNow, duration) {
window.setTimeout(this.rec.show, timeFromNow);
window.setTimeout(this.rec.hide, timeFromNow + duration);
}
recs[2].showBriefly(1000, 3000); to test the function
*/
}
Thanks for the help :)
try
window.setTimeout(function(){this.rec.show();}, timeFromNow )
Just came across your problem, just in case you read this and you want to know what was the problem. this is undefined within the callback, thus you need to store which rectangle you were referring to in a variable (I've called it square), see my code:
showBriefly: function(timeFromNow, duration) {
square = this.box;
setTimeout(function(){square.show();}, timeFromNow )
setTimeout(function(){square.hide();}, timeFromNow + duration )
}
Cheers