I'm trying to switch between divs at an interval, but also be able to stop it in order to include the ability to switch on command with an arrow button on the screen. (Like a slideshow of divs with an arrow to switch immediately.)
Therefore, I cannot use .delay(), as it cannot be stopped, so I'm trying to use .setTimeout, but I'm failing miserably. Can someone tell me what I'm doing wrong?
var divs = $('div[id^="Frame"]').hide(),
i = 0;
(function cycle() {
divs.eq(i).fadeIn(1000)
.setTimeout(function(){divs.eq(i).fadeOut(1000, cycle);},2000);
i = ++i % divs.length; // increment i,
// and reset to 0 when it equals divs.length
})();
I'm not sure what you are trying to achieve, but here is some code which will fadein/fadeout the divs and you have a chance to stop the process:
var divs = $('div[id^="Frame"]').hide(),
i = 0,
currentDiv = null,
interval = null;
var stopFading = function() {
clearTimeout(interval);
}
var showDiv = function() {
if(currentDiv) {
currentDiv.fadeOut(1000, function() {
currentDiv = null;
showDiv();
});
} else {
currentDiv = divs.eq(i);
currentDiv.fadeIn(1000, function() {
interval = setTimeout(showDiv, 2000);
});
i += 1;
if(i > divs.length) i = 0;
}
}
showDiv();
LIVE DEMO
JS:
var H = $('#FrameHolder'),
D = $('#Frame > div'),
B = $('#Button'),
n = D.length,
f = 400, // fade time
p = 2500,// pause
c = 0, // counter
i; // interval
function loop(){
i = setInterval(function(){B.click();},p);
}loop();
H.hover(function(e){
var mEnt = e.type.match('t');
B.stop().fadeTo(f,!!mEnt);
return mEnt?clearInterval(i):loop();
});
B.click(function(){
D.stop().fadeOut(f).eq(++c%n).fadeIn(f);
});
HTML:
<div id="FrameHolder">
<div id="Frame">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
</div>
<div id="Button"></div>
</div>
CSS:
#FrameHolder{
position:relative;
margin:0 auto;
width:400px;
height:300px;
overflow:hidden;
}
#frame{
}
#Frame > div{
position:absolute;
top:0;
text-align:center;
line-height:276px;
width:400px;height:300px;
}
#Frame > div + div{
display:none; /* hide all but 1st */
}
#Button{
cursor:pointer;
position:absolute;
width:60px;
height:60px;
background:rgba(0,0,0,0.5);
border-radius:50%;
right:20px;
top:50%;
margin-top:-30px;
display:none;
}
Haven't taken a look to see if the rest of your code is working, but the immediate error is that setTimeout is not chainable. So the code should look like this...
EDIT -- SHOULD WORK
The other issue was that the increment of i needed to be done in the setTimeout otherwise, i would be incremented before the function ran
http://jsfiddle.net/RJe86/1/
var divs = $('div[id^="Frame"]').hide(),
i = 0;
(function cycle() {
divs.eq(i).fadeIn(1000,function(){
setTimeout(function(){
divs.eq(i).fadeOut(1000, cycle);
i = ++i % divs.length; // increment i,
// and reset to 0 when it equals divs.length
},2000);
});
})();
Related
I've been working with javascript for a few days now but I'm currently stuck on while looping/using switches this animation.
essentially the program will "level up" into a new colored image after moving 3 times, and start from the beginning. I have a gold level up so far, but I want to keep changing colors for the next level ups. I'm trying to add a new classlist to the animated image, a different one for every counter, but nothing seems to be working. this is how I have it:
$("#go").click(function() {
var dest = parseInt($("#block").css("margin-left").replace("px", "")) + 100;
if (dest < 400) {
$("#block").animate({
marginLeft: dest + "px"
}, 700);
} else {
$("#block").animate({
marginLeft: "10px"
}, 100);
//if counter = 1
document.getElementById('block').classList.add("gold")
//if counter = 2
//document.getElementById('block').classList.remove("gold")
//document.getElementById('block').classList.add("pink")
//... etc
//counter += 1
}
});
and here is the link to run the program (click the run text)
http://jsfiddle.net/mept9g1u/
Hope someone can help!
You need to initialise your counter variable to 0 outside of the click event listener, otherwise it's reset to 0 every time you click.
var counter = 0 // ⭐️ Declare counter here
$("#go").click(function() {
var dest = parseInt($("#block").css("margin-left").replace("px", "")) + 100;
if (dest < 400) {
$("#block").animate({ marginLeft: dest + "px" }, 700);
} else {
$("#block").animate({ marginLeft: "10px" }, 100);
counter++;
if (counter === 1) {
document.getElementById('block').classList.add("gold")
}
if (counter === 2) {
document.getElementById('block').classList.remove("gold")
document.getElementById('block').classList.add("pink")
}
// etc.
}
});
$(document).ready(function(){
function BoxAnimate(){
var count= 0;
while( count < 6){
$(".boxanimate").eq(count).stop(true, true).delay(1000*count).animate({
left:"400px"
});
count++;
}
}
BoxAnimate();
});
.boxanimate { background:Green;
margin-bottom:10px;
margin-left:30px;
height:150px;
width:150px;
font-family:Arial;
font-size:30px;
text-align:center;
color:#fff;
line-height:150px;
position:relative;
clear:both;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="ani-wrp">
<div class="boxanimate"> data1 </div>
<div class="boxanimate"> data2 </div>
<div class="boxanimate"> data3 </div>
<div class="boxanimate"> data4 </div>
<div class="boxanimate"> data5 </div>
</div>
I am trying to create a loop of an array that changes the background of a div only one single loop. The code is as follows;
var ImagesF = [];
ImagesF[0]="images/image1.png";
ImagesF[1]="images/image2.png";
ImagesF[2]="images/image3.png";
var i = 1;
var index = 0;
var iterations = 0;
var interval = setInterval(autoImgB(), 2000);
function autoImgB(arr1, id){
var url = 'url(' + arr1 [i] + ')';
if(index >= arr1.length) {
index = 0;
iterations++;
}
document.getElementById(id).style.backgroundImage = url;
if (iterations >= 2) {
clearInterval(interval);
} else {index++}
}
The code is being called like, onclick="autoImgB(ImagesF, 'DIV')"It seems to be trying to work and it does change the first image, however then it doesn't seem to be passing the arguments to the next iteration, what am I doing wrong?
-- UPDATE --
I have attempted to add the following code to pass the argument as originally passed during the function call autoImgB(ImagesF, 'DIV'), however I get an error that states, "arr1 is undefined".
var index = 0;
var iterations = 0;
var interval = setInterval(function() {
autoImgB(arr1, id);
}, 2000);
function autoImgB(arr1, id){
var url = 'url(' + arr1 [index] + ')';
if(index >= arr1.length) {
index = 0;
iterations++;
}
document.getElementById(id).style.backgroundImage = url;
if (iterations >= 2) {
clearInterval(interval);
} else {index++}
}
-- UPDATE 2 --
#Andy, requested that I post my nested DIV's for further help, the DIV structure within the contain are as depicted;
var ImagesF = [];
ImagesF[0]="image1.png";
ImagesF[1]="image2.png";
ImagesF[2]="image3.png";
var n = 0;
function autoImgB(arr1) {
var url = 'url(' + arr1 [n] + ')';
if (n < arr1.length) {
document.getElementById('DIV3').style.backgroundImage = url;
setTimeout(autoImgB, 2000, arr1, ++n);
console.log(url,n)
}
}
.DIV1{
position:absolute;
top: 0px;
left: 0px;
width:100%;
height:100%;
background-image:url('');
background-color: none;
display: none;
z-index: 2;
}
.DIV2{
position:absolute;
top: 0px;
left: 0px;
width:100%;
height:100%;
background-image:url('');
background-color: none;
display: none;
z-index: 1;
}
.DIV3{
position:absolute;
top: 40px;
left: 417px;
width:105px;
height:130px;
background-image:url('');
background-color: none;
display: block;
z-index: 2;
}
<div class="holder">
<div class="DIV1" id="DIV1"></div>
<div class="DIV2" id="DIV2"></div>
<div class="DIV3" id="DIV3"></div>
</div>
<button style="cursor:pointer" onclick="autoImgB(ImagesF)">Press</button>
What I would like for this to do is be able to call it by ID within the function, eg: autoImgB(ImagesF, 'DIV3').
OK. So the main issue is that you are calling the function immediately rather than passing a reference to the function to setInterval.
var interval = setInterval(autoImgB, 2000);
The other problem is that you aren't passing any arguments to the function. There are two ways to do that. The first is to pass them as additional arguments after the time:
var interval = setInterval(autoImgB, 2000, ImagesF, 0);
The second is to call the function itself within the setInterval callback:
var interval = setInterval(function () {
autoImgB(ImagesF, 0);
}, 2000);
The other issue is that it's not clear what your HTML looks like. You appear to be getting an element with a particular id but are passing in div as the argument. So either you have an element like <div id="div"></div> or something else is going on. You should probably take a closer look at that.
That said you can shorten your code considerably if you use setTimeout instead of setInterval, as you only need to do the minimum of checks, and there's no need to clear the timer at any point. Just check to see if the index is less than the array length and call the function again.
var div = document.querySelector('div');
function autoImgB(arr, i) {
if (i < arr.length) {
div.style.backgroundImage = 'url("' + arr[i] + '")';
setTimeout(autoImgB, 2000, arr, ++i);
}
}
autoImgB(ImagesF, 0);
Here's some working code with setTimeout.
setInterval expects a function as its first parameter
var interval = setInterval(function() {
autoImgB(ImagesF, 'DIV');
}, 2000);
The only thing which is wrong in the code you've created is that you pass the return value of the autoImgB function which is undefined into the setInterval function, but the setInterval function only accepts a function or a code string.
Documentation for setInterval
I've created a example based on your code to show you how it'll work.
I'm trying to write my own animations using JavaScript.
I wrote a function for fadeIn() as below, it changes the display property followed by a change in value of opacity. But it doesn't seem to be working.
What am I doing wrong?
function fadeIn(obj, defDisp) {
obj.style.opacity = 0;
obj.style.display = defDisp;
var opVal = 0;
while (opVal < 1) {
obj.style.opacity = opVal;
opVal += 0.1;
}
}
defDisp = Default value for display property
Without a timing interval, this will likely execute too fast for you to see it. The while loop, without a timeout feature, will execute in far less than a second, and you won't see it happen. It's like asking a computer to count to 10, it will do it in less than a millisecond.
Try using a setTimeout
http://www.w3schools.com/jsref/met_win_settimeout.asp
while(opVal < 1) {
setTimeout(function(){
obj.style.opacity = opVal;
opVal += 0.1;
}, 3000);
}
Alter the timer (3000 in this case) to something that makes your fade work for you. Every 1000 is a one second and your loop runs 10 times, so in this case it would be 30 seconds, likely too slow.
I would probably stick with a CSS transition however, as they tend to render better on all browsers.
var el = document.getElementById('fadein');
fadeIn(el);
function fadeIn(ele, defDisp) {
ele.style.opacity = 0;
ele.style.display = defDisp;
var opVal = 0;
var t = setInterval(function(){
if(opVal >= 1){
clearInterval(t);
}
ele.style.opacity = opVal;
opVal += 0.1;
}, 100);
}
#fadein{ background: #ccc; border:1px solid #ddd; padding: 10px }
<div id="fadein">Hello</div>
Use a function that calls itself after a delay.
function fadeIn(obj, defDisp) {
obj.style.opacity = 0;
obj.style.display = defDisp;
var last = +new Date(); // Keep track of the time to calculate the opacity
var fadeStep = function () {
obj.style.opacity = +obj.style.opacity + (new Date() - last) / 800;
last = +new Date();
if (+obj.style.opacity < 1) {
setTimeout(fadeStep, 16);
}
};
fadeStep();
}
var el = document.getElementById('box');
fadeIn(el, 'block');
#box{ padding: 1em; background: #009afd; color: #ffffff; display: none; }
<div id="box">Hello</div>
If you want the fade to be faster, replace 800 by anything lower and vice-versa.
Because html render and for loop use the same thread, so when you doing the for-loop,you can't see any changes until the function complete. You have to use a setTimeout or setInterval (or requestAnimationFrame which is introduced from html5) so you browser can have the control to change the properties on the page:
You can see a example from the snippet, although the second that use a setTimeout is faster than the first one, which use for loop, the first one will not change its color as browser not able to change color during for-loop.
And if you choose to use requestAnimationFrame like I do in the snippets, you can have a smooth animation while the time can also be controlled precisely.
function fadeIn() {
this.style.opacity = 0;
this.style.display = 'block';
var opVal = 0;
console.time("count");
while(opVal < 1) {
this.style.opacity = opVal;
opVal += 0.000001;
}
console.timeEnd("count");
}
// Accept target as the target to apply anim, time is total anim time in ms.
function fadeInAlt(target, time) {
var opacity = 0;
var last = window.performance.now();
console.time("count2");
target.style.opacity = opacity;
target.style.display = 'block';
var fadeInFunc = function(timeStamp) {
if (opacity < 1) {
// Define the change by passed time.
var timePassed = timeStamp - last;
opacity += timePassed / time;
target.style.opacity = opacity;
last = timeStamp;
requestAnimationFrame(fadeInFunc);
} else {
console.timeEnd("count2");
return;
}
};
requestAnimationFrame(fadeInFunc);
}
var div = document.getElementById('test');
div.onclick = fadeIn;
var div2 = document.getElementById('test2');
div2.onclick = function() {
fadeInAlt(this, 3000);
};
#test {
background-color: red;
width: 30px;
height:30px;
}
#test2 {
background-color: blue;
width: 30px;
height:30px;
}
<div id="test"></div>
<div id="test2"></div>
i wanted to create some fadeIn FadeOut effects. When pressed button the main id should be removed and hidden content should be appered and wise versa. (sorry for my poor english knowledge) Jsfiddle
<div class='button'>Click me</div>
<div id='main'></div>
<div class='hidden'></div>
css
#main {
width:80%;
height:300px;
background:#95a5a6;
float:right;
overflow:hidden;
position: relative;
}
.button {
width: 90px;
height:90px;
border-radius: 50%;
background:#e74c3c;
top:70px;
text-align:center;
line-height:90px;
position:absolute;
cursor: pointer;
color:#fff;
}
.hidden {
position:relative;
width:80%;
float:right;
height:250px;
background:#ddd;
margin: 0 auto;
display:none;
}
jquery
$('.button').on('click', function(){
var main = $('#main');
var hidden = $('.hidden');
if(main){
$(main).fadeOut();
$(hidden).fadeIn();
}else{
$(hidden).fadeOut();
$(main).fadeIn();
}
})
You need to call the fadeIn method in the fadeOut callback
http://jsfiddle.net/jgTh2/12/
$('.button').on('click', function () {
var main = $('#main');
var hidden = $('.hidden');
if (main.is(':visible')) {
main.fadeOut(function () {
hidden.fadeIn();
});
} else {
hidden.fadeOut(function () {
main.fadeIn();
});
}
});
var show = true;
$('.button').on('click', function(){
var main = $('#main');
var hidden = $('.hidden');
if(show){
$(main).fadeOut();
$(hidden).fadeIn();
show = false;
}else{
$(hidden).fadeOut();
$(main).fadeIn();
show = true;
}
})
in the css set .hidden to opacity:0 and remove display:none;
You have to use 1 more variable — flag.
Try this:
var flag = 0;
$('.button').on('click', function(){
var main = $('#main');
var hidden = $('.hidden');
if(flag == 0){
$(main).fadeOut('fast', function() {
$(hidden).fadeIn();
flag = 1;
});
}else{
$(hidden).fadeOut('fast', function() {
$(main).fadeIn();
flag = 0;
});
}
})
Fiddle
As #cgatian suggested, you can use boolean variable, instead of integer:
var flag = false;
$('.button').on('click', function(){
var main = $('#main');
var hidden = $('.hidden');
if(flag == false){
$(main).fadeOut('fast', function() {
$(hidden).fadeIn();
flag = true;
});
}else{
$(hidden).fadeOut('fast', function() {
$(main).fadeIn();
flag = false;
});
}
})
No need to maintain two fadeIn/fadeOut blocks
$('.button').on('click', function(){
var visible = $('#main');
var hidden = $('.hidden');
hidden = hidden.is(':visible') ? [visible, visible = hidden][0] :hidden;
visible.fadeOut(function()
{
hidden.fadeIn();
});
})
http://jsfiddle.net/eN6bg/
So, i want to make game for my child. Have low experience in JS.
Scenario:
Have for example 4 square divs with blank bg. After refresh (or win) i want to:
Generate random numbers into div (1...4). And show them in them.
Then let player delete those divs by clicking on them, but in sequence how divs are numbered.
*For example after refresh divs have those numbers 2 3 1 4. So, user has to have rights to delete first div numbered 1 (2 3 _ 4) and so on.* If he clicks on 2 it get error , div stays in place, and user can try again delete right one.
It game for learning numbers. I have the begining.
Index.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="css.css">
<script src="http://code.jquery.com/jquery-latest.min.js"
type="text/javascript"></script>
</head>
<body>
<div class="grid">
<div id="Uleft"></div>
<div id="Uright"></div>
<div id="Dleft"></div>
<div id="Dright"></div>
</div>
<script>
$(".grid").children( "div" ).on("click", function(){
$(this).css("visibility", "hidden");
});
</script>
</body>
</html>
css.css
.grid {
margin: 0 auto;
width: 430px;
}
#Uleft, #Uright, #Dleft, #Dright {
border: 1px solid black;
width: 200px;
height: 200px;
margin: 5px;
}
#Uright {
float: right;
background-color: red;
}
#Uleft {
float: left;
background-color: blue;
}
#Dleft {
float: left;
background-color: green;
}
#Dright {
float: right;
background-color: yellow;
}
So, i guess i have use jQuery as well, but i dont know how to make it dynamic and different after refresh of page. Please help :)
http://jsfiddle.net/bNa8Z/
There are a few things you have to do. First you have to create a random array which you use sort and Math.random() to do then, you need insert the text in the squares. Find the min of the visible squares and then remove/alert depending if its the min value.
// sort by random
var rnd = [1,2,3,4].sort(function() {
return .5 - Math.random();
});
// map over each div in the grid
$('.grid div').each(function(ii, div) {
$(div).text(rnd[ii]); // set the text to the ii'th rnd
});
function minVisible() {
var min = 1e10; // a big number
$('.grid div').each(function(ii, div) {
// if not visible ignore
if ($(div).css('visibility') === "hidden" ){
return;
}
// if new min, store
var curFloatValue = parseFloat($(div).text());
console.log(curFloatValue);
if (curFloatValue < min) {
min = curFloatValue;
}
});
return min;
}
$(".grid").children( "div" ).on("click", function(){
var clickedFloatValue = parseFloat($(this).text());
if (clickedFloatValue == minVisible()) {
$(this).css("visibility", "hidden");
} else {
alert("sorry little tike");
}
});
Updated jsfiddle http://jsfiddle.net/bNa8Z/2/
Roughly this is what it would look like:
var selected = {};
$('.grid div').each(function(idx){
var is_done = false;
do{
var rand = Math.floor((Math.random()*4)+1);
if( selected[rand] == undefined ){
$(this).html(rand);
selected[rand] = 1;
is_done = true;
}
}while(!is_done);
});
alert("Start the game");
var clicked = [];
$('.grid').on('click', 'div.block', function(){
var num = $(this).html();
if( num == clicked.length + 1 ){
//alert(num + " is correct!");
clicked.push(num);
$(this).addClass("hide");
}else{
alert("Failed!");
}
if( clicked.length == 4 ){
alert("You Won!");
}
});
HTML:
<div class="grid">
<div class="block" id="Uleft"></div>
<div class="block" id="Uright"></div>
<div class="block" id="Dleft"></div>
<div class="block" id="Dright"></div>
</div>
Added CSS:
#Uleft, #Uright, #Dleft, #Dright {
position:absolute;
...
}
#Uright {
left:220px;
top:0px;
background-color: red;
}
#Uleft {
left:0px;
top:0px;
background-color: blue;
}
#Dleft {
left:0px;
top:220px;
background-color: green;
}
#Dright {
left:220px;
top:220px;
background-color: yellow;
}
.hide {
display: none;
}
See the working version at
JSFiddle
You will need to re-"run" the fiddle per game.
please try it. I think that It will help you.
var generated_random_number_sequesce = function(){
var number_array = [];
var number_string = '';
var is_true = true;
while(is_true){
var ran_num = Math.round(1 + Math.random()*3);
if(number_string.indexOf(ran_num) == -1 && ran_num < 5){
number_array[number_array.length] = ran_num;
number_string = number_string + ran_num;
if(number_array.length == 4){is_true = false;}
}
}
return number_array;
}
var set_number_on_divs = function(){
var number_array = generated_random_number_sequesce();
$(".grid").children().each(function(index, element){
$(this).attr('data-div_number' , number_array[index]);
});
}
set_number_on_divs()
var clicked = 0;
$(".grid").children( "div" ).on("click", function(){
clicked += 1;
var current_div_number = $(this).attr('data-div_number');
if( parseInt(current_div_number) == clicked){
$(this).css("visibility", "hidden");
} else{
clicked -= 1;
alert('error');
}
});