How to loop each() 3 times in JQuery - javascript

I am making a HTML5 banner and need to loop through 3 overlapping banners.
The script I'm currently using looks like this:
var currentDelay; currentDelay = 0;
var pastItem; pastItem = "";
$( ".state" ).each(function() {
$(this).delay(currentDelay).fadeIn();
$(this).prev().delay(3000).fadeOut();
currentDelay += 3000;
});
It works, but only works once. .state is the wrapping class for each banner. They are positioned over the top of each other and should fade in and out of each other.
HTML:
<div class="state">
<img src="images/img-1.jpg" alt="Last minute ski holidays from £299pp" />
<div class="message"><p>Last minute<br />ski holidays from £299<span>pp</span></p></div>
</div>
<div class="state">
<img src="images/img-2.jpg" alt="Enjoy free skiing guide & coaching" />
<div class="message blue"><p>Enjoy free<br />skiing guide<br />& coaching</p></div>
</div>
<div class="state">
<img src="images/img-3.jpg" alt="Last minute ski holidays from £299pp" />
<div class="message grey"><p>Limited availability<br /><span class="sub-mes">Don't miss out</span></p></div>
<p class="call-to-action">Find out more</p>
</div>
Is there a way I can make it loop round 3 times then just stop on the last frame? The last banner needs to fade back to the first frame so it looks seamless.
Big thanks for some help on this :)
Cheers
Rob

Here is a method using setInterval.
I have commented the code so I will not bother explaining it.
JS:
$(document).ready(function() {
var currentDelay; currentDelay = 3000;
var pastItem; pastItem = "";
var i=0;
// interval
var cycle = setInterval(function() {
// Fade
$(".state:eq(" + i + ")").fadeOut();
// Increment
i++;
// Increase delay
currentDelay+=3000;
// Check if at last, change to suit wants
if(i == $(".state").length) {
/*
// Loop here
$(".state").delay(500).fadeIn();
i=0;
*/
// Stop interval
clearInterval(cycle); // Comment this line if looping
}
}, currentDelay);
})
Fiddle: https: https://jsfiddle.net/4bhv9w80/1/

You can do this with a self-referencing function that calls its self 3 times.
var sleepTimer = 0;
(function LoopyLoo(i) {
setTimeout(function() {
var currentDelay = 0
$(".state").fadeOut();
$(".state").each(function() {
$(this).delay(currentDelay).fadeIn();
currentDelay += 3000;
});
if (--i) {
LoopyLoo(i);
}// decrement i and call myLoop again if i > 0
}, sleepTimer)
sleepTimer = 9000;
})(3); //Times to call the function.
Small change to the css, added some lovely colour so you can see it in action.
.state-con {
position: relative;
}
.state {
display: none;
position: absolute;
top: 0;
left: 0;
}
.one {
z-index: 1;
background-color: red;
}
.two {
z-index: 2;
background-color: blue;
}
.three {
z-index: 3;
background-color: aqua;
}
See it all working with this JS fiddle.
https://jsfiddle.net/yojmu6ga/21/

Hope this works for you:
var currentDelay; currentDelay = 0;
$( ".state" ).each(function() {
var $currentElement =$(this);
window.setTimeout(function(){
$( ".state:visible" ).fadeOut();
$currentElement.fadeIn();
}, currentDelay);
currentDelay += 3000
});
window.setTimeout(function(){
$( ".state:visible" ).fadeOut();
$(".state:first").fadeIn();
}, currentDelay);
https://jsfiddle.net/2k6c1b18/

Related

Setting a div to an array so i can make things disappear / re-appear based on buttons

The title may not make the most sense.
Basically I want to store all of the ".mainContent" into X ..
Then when you'd click a button it would make x[0] display none, and bring in x[1].. if that makes sense... that way I could have the same wiping transition and it would just bring in my 4 different pages that I would have.
You can see my page here: I have the "home" and "learn more" pages hard coded, but I obviously don't want to have to do this for every section
http://mikecioffi-me.stackstaging.com/ (*this is not on mobile***) only desktop. mobile version is not ready.. haha
<script>
var dissapearingTime = 1800;
var nextSlideTime = 3000;
var originalNumber = 0;
var newNumber = 1;
var x = $(this).find('.mainContent');
$('.button').hover(
function () {
$('.arrowRight').toggleClass('active');
})
$('.button').click(
function () {
console.log(x);
$('.sidebar').toggleClass('anim-trans');
setTimeout(function () {
$(".hero").css("display", "none");
$(".blank").css("display", "block");
}, dissapearingTime);
setTimeout(function () {
$('.sidebar').toggleClass('anim-trans');
}, nextSlideTime);
})
function hello() {
$('.sidebar').toggleClass('anim-trans');
setTimeout(function () {
$(".blank").css("display", "none");
$(".hero").css("display", "block");
}, dissapearingTime);
setTimeout(function () {
$('.sidebar').toggleClass('anim-trans');
}, nextSlideTime);
}
</script>
i loved your animations :).
I don't know how you use that but you can do with this way. I hope it can help you.
myArray = $('.test');
$(myArray[0]).hide();
https://jsfiddle.net/7rod0vky/2/
one way would be to label each card / div / item with an id, and then you can hide display using a global namespace / json object / dictionary for your own page, that holds some extra info between scopes.
window.__ok = {'current': '', 'prev': null}
var x = $('.main > div');
['#c0', '#c1', '#c2'].map(function(c,i,a){
$(c).on('click', function(a){
window.__ok.prev = window.__ok.current;
window.__ok.current = i;
alert(`show ${c} id: ${i} prev: ${window.__ok.prev}`);
if ($(`#${window.__ok.current}`).css('display') == 'none'){
$(`#${window.__ok.current}`).css('display', 'block');
$(`#${window.__ok.prev}`).css('display', 'none');
}
})
})
.red {
background-color: red;
height: 30px;
display: none
}
.blue {
background-color: blue;
height: 30px;
display: none
}
.green {
background-color: green;
height: 30px;
display: none
}
span {
color: grey;
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main">
<div id="0" class="red">a</div>
<div id="1" class="blue">b</div>
<div id="2" class="green">c</div>
</div>
<span id="c0">show0</span><br>
<span id="c1">show1</span><br>
<span id="c2">show2</span><br>

Why won't my HTML Images fade

I'm trying to create a simple slideshow effect. I have 10 images, and I've created a basic HTML page with 2 buttons to go to the right or left image. On clicking the button, the images change.
Now, I'm trying to add a basic fade functionality to the changing image. But the fade effect isn't getting displayed. When I put alerts, I notice that the fade is taking place, but without the alerts it is too fast to be visible. Also, it is happening on the previous image, instead of the next one.
<html>
<head>
<style>
.main {
text-align: center;
}
.centered {
display: inline-block;
}
#image {
border: solid 2px;
width: 500px;
height: 500px;
}
#number {
font-size: 30px;
}
</style>
<script>
function goLeft() {
var image = document.getElementById("image");
var pos = document.getElementById("number");
if(Number(pos.innerHTML)==1) {
image.src = "Images\\10.jpg"
pos.innerHTML = 10;
} else {
image.src = "Images\\" + (Number(pos.innerHTML)-1).toString() + ".jpg"
pos.innerHTML = (Number(pos.innerHTML)-1).toString();
}
for (var i=0; i<25; i++) {
setTimeout(changeOpacity(image, i), 1000);
}
}
function changeOpacity(image, i) {
alert(parseFloat(i*4/100).toString());
image.style.opacity = (parseFloat(i*4/100).toString()).toString();
}
function goRight() {
var image = document.getElementById("image");
var pos = document.getElementById("number");
if(Number(pos.innerHTML)==10) {
image.src = "Images\\1.jpg"
pos.innerHTML = 1;
} else {
image.src = "Images\\" + (Number(pos.innerHTML)+1).toString() + ".jpg"
pos.innerHTML = (Number(pos.innerHTML)+1).toString();
}
for (var i=0; i<25; i++) {
setTimeout(changeOpacity(image, i), 1000);
}
}
</script>
</head>
<body>
<div class="main">
<div class="centered">
<img id="image" src="Images\1.jpg">
</div>
</div>
<div class="main">
<div class="centered">
<span id="number">1</span>
</div>
</div>
<div class="main">
<div class="centered">
<button onclick="goLeft()" style="margin-right:50px;">Go Left</button>
<button onclick="goRight()" style="margin-left:50px;">Go Right</button>
</div>
</div>
</body>
The problem is this block of code that is in your goLeft method, and goRight method:
for (var i=0; i<25; i++) {
setTimeout(changeOpacity(image, i), 1000);
}
You are creating 25 timers that, and each timer will execute approximately 1 second later.
Creating animations is best left to the CSS.
In your CSS add:
#image {
transition: opacity 0.5s ease;
}
And then in your JavaScript, simply: image.style.opacity = 1.0;
When the opacity changes, CSS will automatically transition the opacity length at the speed defined in the css, e.g 0.5s. Feel free to experiment.
I also added a jsfiddle here: http://jsfiddle.net/dya7L8wq/
You misunderstood setTimeout and the for loop.
Norman's answer provides a good solution with CSS, but he doesn't talk too much about why your code is not working. So I'd like to explain.
for (var i=0; i<25; i++) {
setTimeout(changeOpacity(image, i), 1000);
}
You assumption is:
invoke changeOpacity(image, 0) after 1 second
invoke changeOpacity(image, 1) 1 second after step 1
invoke changeOpacity(image, 2) 1 second after step 2
invoke changeOpacity(image, 3) 1 second after step 3
....
And the last step is invoking changeOpacity(image, 24) 1 second after previous step.
What actually happens is:
The loop is finished almost immediately!
In each iteration, setTimeout queues an asynchronous function invocation, and it's done! That says, it will return right away, rather than wait until changeOpacity returns.
And then, after about 1 second, changeOpacity fires 25 times almost at the same time, because you queued it 25 times in the for loop.
Another problem here is: in changeOpacity invocations, passed-in parameter i are not 1, 2, 3...., they all have the same value that causes for loop to exit (1 second ago) - 25, because JS doesn't have a block scope prior to ES6 (in ES6 we have keyword let for it).
In a pure JS solution, to ensure the time sequence we'd usually queue next invocation at the end of every step:
function changeOpacity() {
// do something here
// before the function returns, set up a future invocation
setTimeout(changeOpacity, 1000)
}
Here's an example to print a list of numbers from 1 to 5:
var go = document.getElementById('go')
var op = document.getElementById('output')
var i = 0
function printNum() {
var p = document.createElement('p')
p.innerHTML = ++i
op.appendChild(p)
// next step
if(i < 5) {
setTimeout(printNum, 500)
}
}
go.onclick = printNum
<button id="go">GO</button>
<div id="output"></div>
Why use pure JavaScript?
Use jQuery.
It has a pretty neat fadeTo() function and a useful fadeIn() function.
Might wanna use that ;)

Fade in boxes 1 after the other with jQuery

Im trying to make a 'blanket' of divs containing child divs 150px high and 150px wide.
I want each child div to fade in 1 after the other after after a millisecond or so, opacity changing from 0, to 1.
I cant seem to figure out how this works, or how id do it though?
http://jsfiddle.net/CCawh/
JS
$(function(){
var figure = [];
w = 1500;
h = 450;
for(i = 0, i < 30, i++){
$('div').append(figure[].clone()).fadeIn();
}
});
Here is a working solution.
The problems in your code
in for(i = 0, i < 30, i++), you should use ';', not ',' . Use developer tools in your browser to catch such typos
In your code $('div').append(figure[].clone()).fadeIn(); , The fadeIn applies to $('div') as append() returns the calling object itself. You must replace it with $('<figure></figure>').appendTo('div').fadeIn('slow'); and to fadeIn items one by one you could set a timeout with incrementing delays
Add display: none; style to the figure to keep it hidden initially
Here is the full code.
$(function(){
for(i = 0; i < 30; i++){
setTimeout(function(){$('<figure></figure>').appendTo('div').fadeIn('slow');}, i*200);
}
});
Here is a fiddle to see it working http://jsfiddle.net/CCawh/12/
Try using greensock TweenLite http://www.greensock.com/get-started-js/.
It has staggerTo/staggerFrom action that does exactly what you are asking. TweenLite in conjunction with jQuery makes animation very easy.
This would be a possible solution (DEMO).
Use an immediate function and call it again n times in the fadeIn callback.
$(function(){
var figure = $('figure');
var counter = 0;
(function nextFade() {
counter++;
figure.clone().appendTo('div').hide().fadeIn(500, function() {
if(counter < 30) nextFade();
});
})();
});
You can use the following implementation as an example. Using setTimeout() will do the trick.
I've updated your jsfiddle here: http://jsfiddle.net/CCawh/5/
HTML:
<div class="container">
<div class="box"></div>
</div>
CSS:
.box {
display: none;
float: left;
margin: 10px;
width: 150px;
height: 150px;
background-color: #000;
}
JS:
$(function() {
var box = $('.box');
var delay = 100;
for (i = 0; i < 30; i++) {
setTimeout(function() {
var new_box = box.clone();
$('.container').append(new_box);
new_box.fadeIn();
}, delay);
delay += 500; // Delay the next box by an extra 500ms
}
});
Note that in order for the element to actually fade in, it must be hidden in the first place, i.e. display: none; or .hide()
Here's perhaps a more robust solution without counters:
http://jsfiddle.net/CCawh/6/
for(var i = 0; i < 30; i++){
$('div').append($('<figure>figure</figure>'));
}
(function fade(figure, duration) {
if (figure)
figure.fadeIn(duration, function() { fade(figure.next(), duration); });
})($('figure').first(), 400);
By the way, clauses in for loops are separated using semicolons, not commas.

Chaining similar elements modification by time interval

I have a given list of p elements on my html code.
On page load, I try to queuing modifications of each <p> elements's content by a given interval of time (1sec).
Given the html:
<p>I want to change first!</p>
<p>I want too!</p>
<p>Me 3rd !</p>
<p>Hey, don't forget me!</p>
the CSS:
p { padding: 2px 5px 0px 10px; }
.p { color: #999; }
.green { color:green; border-bottom: 1px solid #888; background: #EEE; }
What should be the JS to since I want to chain up modification. Literally: the first p sentence to be CSS / HTML modified first, 1sec later the 2nd line should be replaced, 1sec later the 3rd line, 4sec later the 4th line, etc.
$("p").ready(function(){
setInterval(function () {
$('p').text('aaaahhhhh.... happy!')
}, 1000);
});
That's fail (fiddle).
What I am doing wrong ? should I use a for loop, each(), instead of selector + setInterval ? please forward keywords so I may dig in the relevant docs. Fiddle appreciate~
Try this
$(document).ready(function(){
var st=null;
var i=0;
st=setInterval(function () {
$('p').eq(i).text('aaaahhhhh.... happy!');
if(i==$('p').length-1)// one less because i initialised by 0.
clearTimeout(st);
i++
}, 1000);
});
Check live demo here http://jsfiddle.net/gT3Ue/14/
(function next($set, i) {
setTimeout(function () {
$set.eq(i).text('aaaahhhhh.... happy!');
if (i < $set.length - 1) {
next($set, i + 1);
}
}, 1000);
// /\
// ||------ the delay
}($('p'), 0));
// /\ /\
// || ||-- the starting index
// ||----- -- your set of elements
demo: http://jsbin.com/otevif/1/
function modifyTargetDeferred(target) {
target.first().text('ahhh... happy');
if (target.length > 1) {
setTimeout(function() {
modifyTargetDeferred(target.not(':first'));
}, 1000);
}
}
setTimeout(function() {
modifyTargetDeferred($('p'));
}, 1000);
Your interval is working use append instead of text to see the effect. Use document.ready not $("p").ready
Live Demo
$(document).ready(function(){
setInterval(function () {
$('p').append('aaaahhhhh.... happy!')
}, 1000);
});
Live Demo
i = 0;
$(document).ready(function () {
div1 = $('#div1');
parry = $("p");
setInterval(function () {
div1.append(parry.eq(i++).text() + '<br />')
if (i > 3) i = 0;
}, 400);
});

Create an endless loop in Jquery

The HTML structure is like this
<ul class="innerfade">
<li style="position: absolute; z-index: 4; display: none;">some Text</li>
<li style="position: absolute; z-index: 3; display: none;">bla bla bla</li>
<li style="position: absolute; z-index: 2; display: none;">bla bla</li>
<li style="position: absolute; z-index: 1; display: none;">some Text</li>
<ul>
I wanna change the css of each <li> from display:none to display:block to none again after an interval. And this goes on in an endless loop. Can someone tell me how to acheive this in jquery.
So far my Jquery look like this -
$('.innerfade li').each(function()
{
$(this).css('display', 'block');
$(this).fadeOut('slow');
});
I tested this on firebug console but it didn't work. And i didnt go ahead and add the setTimout function.
Anyway any Help will be greatly appreciated!
Edit: I have edited the code so i can explain better what i'm trying to acheive. Like you can see each li is one below the other. The li's contain pictures and some text in the same structure(which i have omitted from here to keep things simple). Hence i want only one li to display at a time and then fade out. N then the next li takes over n so on and so forth in an endless loop. And i want each li to stay alive for roughly 5 mins
DEMO
var el = $('.innerfade li'),
i = 0;
$(el[0]).show();
(function loop() {
el.delay(1000).fadeOut(300).eq(++i%el.length).fadeIn(500, loop);
}());
Edit:
This code was written way too late at night by a tired programmer (myself), and should not be used due to browser hosing. Please see jQuery draws to a halt on Chrome and mac OS for production-quality code!
Do not use the below code.
Use two mutually-dependent functions:
var $lis = $('ul.innerfade > li');
function fadeThemOut()
{
$lis.fadeOut('slow', fadeThemIn);
}
function fadeThemIn()
{
$lis.fadeIn('slow', fadeThemOut);
}
// kick it off
fadeThemOut();
Demo: http://jsfiddle.net/mattball/nWWSa/
You can write this more concisely using .fadeToggle():
var $lis = $('ul.innerfade > li');
function toggleThem()
{
$lis.fadeToggle('slow', toggleThem);
}
// kick it off
toggleThem();
Demo: http://jsfiddle.net/mattball/XdAEG/
Try this
setInterval(function(){
$(".innerfade li").fadeToggle();
}, 1000);
Edit: Based on your clarification of what you are trying to achieve:
(function () {
var i = 0;
var delay = 1000 * 60 * 5; // 5 minutes
var items = $(".innerfade li");
var len = items.length;
setInterval(function () {
items.fadeOut().eq(++i % len).fadeIn();
}, delay);
})();
The above gives you a cross-fade effect. If you want to completely fade out before fading in the next element, you want this:
(function () {
var i = 0;
var delay = 1000 * 60 * 5; // 5 minutes
var items = $(".innerfade li");
items.eq(0).show();
var len = items.length;
setInterval(function () {
items.filter(":visible").fadeOut(function() {
items.eq(++i % len).fadeIn();
});
}, delay);
})();
http://jsfiddle.net/gilly3/CDHJY/
jQuery uses CSS-Selectors. What you are doing is trying to get all li-tags inside an innerfade-tag, which obviously doesn't exist.
You need to select it using its class, just like in CSS:
$(".innerface li")...
Although not fit with your Endless Loopm but this is a Loop where you stop at the Endpoint
var el = $('.innerfade li'), i = 0; $(el[0]).fadeIn();<BR> (function loop() { if(i+1<4){ el.delay(1000).fadeOut(300).eq(++i%el.length).fadeIn(500, loop);<BR>} else el.delay(1500).fadeOut(1000); <BR>} ());
try this:
$(function() {
$('.innerfade li').each(function() {
blink($(this))
});
});
function blink(li) {
li.fadeOut('slow', function() {
li.fadeIn('slow', blink(li));
});
}
Check out this fiddle.

Categories