Fade in Each Thumbnail? - javascript

all of my thumbnails have the class .thumb
I'm trying to fade in each at a time like I've seen on some websites but it doesnt seem to be working. My code is below
$('.thumb').eachDelay(function(){
$(this).fadeIn('1000');
}, 100);
What is wrong here?
Here is a fiddle: http://jsfiddle.net/NPWGu/
I've tried a ton of the solutions and havent had any luck yet so hopefully this will help make it easier to understand how I have my code setup

Try this:
$(".thumb").each(function(i) {
$(this).delay(500*i).fadeIn(1000);
});

I'm not aware of any jQuery method called eachDelay(). As it is not quite clear from your question which exact scenario you want, here are four different different options:
1) If you want to fade them all in at once, you would use this:
$('.thumb').fadeIn('1000');
2) If you want to fade them all in at the same time after delay, you can use this:
$('.thumb').delay(1000).fadeIn('1000'); 
3) If you want to fade them all in one after another, you can use this:
function sequentialFade(selector) {
var items$ = $(selector);
var index = 0;
function next() {
if (index < items$.length) {
items$.eq(index++).fadeIn('1000', next);
}
}
next();
}
sequentialFade('.thumb');
4) If you want to fade them all in one after another with a delay between the finish of one and the start of the next, you can use this:
function sequentialFade(selector, delayTime) {
var items$ = $(selector);
var index = 0;
function next() {
if (index < items$.length) {
items$.eq(index++).delay(delayTime).fadeIn(1000, next);
}
}
next();
}
sequentialFade('.thumb', 1000);
Working demonstration of this last option here: http://jsfiddle.net/jfriend00/zg8S4/

Serial animation code should look like (you can change the 1000ms below as needed):
var cur = -1;
var thumbs = $(".thumb");
function doIt() {
if(cur == -1) cur = 0;
else if(cur < thumbs.length-1) cur++;
else return;
$(thumbs[cur]).fadeIn(1000, doIt);
}
doIt();

Related

JQuery transition animation

This program randomly selects two employees from a json-object Employees array, winnerPos is already defined.
For better user experience I programmed these functions to change pictures one by one. The animation stops when the randomly selected person is shown on the screen.
The slideThrough function will be triggered when the start button is pressed.
function slideThrough() {
counter = 0;
start = true;
clearInterval(picInterval);
picInterval = setInterval(function () {
changePicture();
}, 500);
}
function changePicture() {
if (start) {
if (counter > winnerPos) {
setWinner();
start = false;
killInterval();
} else {
var employee = Employees[counter];
winnerPic.fadeOut(200, function () {
this.src = 'img/' + employee.image;
winnerName.html(employee.name);
$(this).fadeIn(300);
});
counter++;
}
}
}
The problem is the animation doesn't work smoothly. At first it works, but not perfect. The second time the transition happens in an irregular way, i.e. different speed and fadeIn/fadeOut differs from picture to picture.
Could anyone help me to fine-tune the transition?
I would avoid using setInterval() and add a function to the call to .fadeIn() that starts the animation of the next picture.
It would look like this:
function changePicture(pos) {
pos = pos || 0;
if (pos <= winnerPos) {
var employee = Employees[pos];
winnerPic.fadeOut(200, function() {
this.src = 'img/' + employee.image;
winnerName.html(employee.name);
$(this).fadeIn(300, function() {
changePicture(pos + 1);
});
});
} else {
setWinner();
}
}
To start the animation, you call changePicture() without any arguments, like this.
changePicture();
jsfiddle

Pausing Recursive Function Call

I have a function of which I'm supposed to pause on mouseenter and pause on mouseleave but the problem is that the function is recursive. You pass in a parent and index and it will recursively loop through each inner div displaying and hiding. The function looks like this:
var delay = 1000;
function cycle(variable, j){
var jmax = jQuery(variable + " div").length;
jQuery(variable + " div:eq(" + j + ")")
.css('display', 'block')
.animate({opacity: 1}, 600)
.animate({opacity: 1}, delay)
.animate({opacity: 0}, 800, function(){
if(j+1 === jmax){
j=0;
}else{
j++;
}
jQuery(this).css('display', 'none').animate({opacity: 0}, 10);
cycle(variable, j);
});
}
I've tried setting a timeout and clearing it but it doesn't seem to do anything (it seems to ignore the timeout entirely), I've tried using stop() and calling the function again on mouseout but that seemed to repeat the function call (I was seeing duplicates) and it stopped mid animation which didn't work. I tried adding in a default variable at one point (var pause = false || true;) but I also couldn't get it to work as expected (though I feel the solution relies on that variable). I'm open to all suggestions but there are some rules of engagement:
Rules: There can't be any major changes in how this function works as many things rely on it, it's something I do not have control over. Assume the function call looks like this jQuery('#divList', 0) and holds a bunch of div elements as children.
The timeout function is the last solution I tried which looks like:
jQuery('#divList').on('mouseenter', function(){
setTimeout(cycle, 100000);
})
.on('mouseleave', function(){
window.clearTimeout();
});
Perhaps something like this? I simplified the animation just to make the example simpler, but you should be able to adapt it to your needs.
First, we have a function that's responsible for animating a set of elements. Every function call returns a new function that allows to toggle the animation (transition between pause and resume).
function startCycleAnimation(els) {
var index = 0,
$els = $(els),
$animatedEl;
animate($nextEl());
return pauseCycleAnimation;
function animate($el, startOpacity) {
$el.css('opacity', startOpacity || 1)
.animate({ opacity: 0 }, 800, function () {
animate($nextEl());
});
}
function $nextEl() {
index = index % $els.length;
return $animatedEl = $els.slice(index++, index);
}
function pauseCycleAnimation() {
$animatedEl.stop(true);
return resumeCycleAnimation;
}
function resumeCycleAnimation() {
animate($animatedEl, $animatedEl.css('opacity'));
return pauseCycleAnimation;
}
}
Then we can kick-start everything with something like:
$(function () {
var $animationContainer = $('#animation-container'),
toggleAnimation = startCycleAnimation($animationContainer.children('div'));
$animationContainer.mouseenter(pauseOrResume).mouseleave(pauseOrResume);
function pauseOrResume() {
toggleAnimation = toggleAnimation();
}
});
Example HTML
<body>
<div id="animation-container">
<div>Div 1</div>
<div>Div 2</div>
<div>Div 3</div>
</div>
</body>
If you want something more generic, it seems there's a plugin that overrides animate and allows to pause/resume animations in a generic way.
You will need to put a flag that each cycle checks before it determines if it is going to run. Then you can just change that flag when the mouse events are triggered. If you need to pick up where you left off when you unpause, consider saving the last value of j
function cycle(variable, j){
if (window.paused) {
window.last_j = j;
return;
}
...
Then when you want to pause, just set window.paused = true . To resume, change it back to false and call cycle again:
cycle(variable, last_j);

jquery/javascript set multiple timeouts one after the other via loop to run independently of the other

I am trying to animate a handful of DIV's to scroll upwards but I want one to scroll up after a pause after the other after the other. And the best I can come up with at the moment is
$('.curtain').each(function()
{
var $elem = $(this);
setTimeout(function()
{
$elem.animate({"height":0+'px'}, 2000);
}, 1000);
});
Problem is they still all animate together without pause. How can I go about doing something in this fashion. The divs are dynamically generated and there can be 5 - 20 of them so doing a hardcoded logic is out, any ideas?
function animateIt () {
var elems = $('.curtain').get();
(function next() {
if(elems.length){
var elem = $(elems.shift());
elem.animate({"height":0+'px'}, 2000, next);
}
})();
}
animateIt();
running example
Another way like queue
function animateIt () {
var divs = $('.curtain');
divs.each( function(){
var elem = $(this);
$.queue(divs[0],"fun", function(next) { elem.animate({"height":0+'px'}, 2000, next); });
});
divs.eq(0).dequeue("fun");
}
Looks like a simple recursive function might work for you here -
function doAnimation(elapsed){
var iterations = $('.curtain').length;
var current = elapsed+1;
if (current <= iterations){
setTimeout(function(){
$('.curtain:eq(' + elapsed + ')').animate(...);
doAnimation(current);
},50);
}
}
doAnimation(0);
Here's a simple demo

Javascript function shows only last element of array

Please take a look at this function:
var msgdiv, i=0;
msgdiv=$("#message");
messages=["Welcome!","Добро пожаловать!"];
function fadeMessages(messages, div){
while(i<messages.length){
div.fadeOut(1000).html('').append(messages[i]).fadeIn(1000);
i=i+1;
}
}
fadeMessages(messages,msgdiv);
What I want to do is, to show one by one elements of array. But, function above shows only last element of array messages.length time. Where I did wrong?
Live example: http://jsfiddle.net/QQy6X/
The while executes much much faster than the fadeOut/fadeIn calls, so you only see the last result. You need to make each animation wait for the previous ones to finish.
I like to solve these problems recursively. Note, it does alter the messages array, but it's not too hard to convert this to use a counter instead (like your original version). Here you go:
var $msgdiv = $('#message'),
messages = ['Xoş gəlmişsiniz!', 'Welcome!', 'Добро пожаловать!'];
function showNext() {
var msg = messages.shift();
if (msg) {
$msgdiv.fadeOut(1000, function () {
$(this).text(msg).fadeIn(1000, showNext);
});
}
}
showNext();
Demo: http://jsfiddle.net/mattball/Exj95/
Here's a version that leaves messages intact:
var $msgdiv = $('#message'),
messages = ['Xoş gəlmişsiniz!', 'Welcome!', 'Добро пожаловать!'],
i = 0;
function showNext() {
if (i < messages.length) {
var msg = messages[i];
$msgdiv.fadeOut(1000, function () {
i++;
$(this).text(msg).fadeIn(1000, showNext);
});
}
}
showNext();
Demo: http://jsfiddle.net/mattball/wALfP/
Your while loop finishes executing before the div has had a chance to fade out. Use an if statement and recursion:
var msgdiv = $("#message");
var i = 0;
var messages = ["Welcome!", "Добро пожаловать!"];
(function fadeMessages() {
if (i in messages) {
msgdiv.fadeOut(1000, function() {
$(this).html('').append(messages[i++]).fadeIn(1000, fadeMessages);
});
}
})();
http://jsfiddle.net/QQy6X/6/
Your while loop finishes very quickly; instead you should wait for the animation to finish before starting the next one. This is easy to do by adding a callback function to fadeIn. I would use this:
+function(){
var $msgdiv = $("#message");
var i = -1;
var messages = ["Xoş gəlmişsiniz!","Welcome!","Добро пожаловать!"];
+function fadeNext(){
$msgdiv.fadeOut(1000, function(){
$msgdiv.text(messages[i = (i + 1) % messages.length]);
$msgdiv.fadeIn(1000, fadeNext);
});
}();
}();
http://jsfiddle.net/Paulpro/QQy6X/7/
In jQuery, you can't intertwine animations and non-animations in the way you are doing and expect them to run in the right order. The animations will go into the animation queue and get sequenced one after another there, but the non-animations will all run immediately. Thus, things won't happen in the right order.
To do something like you want to do, you can use code like this.
messages=["Welcome!","Добро пожаловать!"];
function fadeMessages(msgs, div) {
var i = 0;
function next() {
if (i < msgs.length) {
div.fadeOut(1000, function() {
div.html(msgs[i++]).fadeIn(1000, next);
});
}
}
next();
}
fadeMesssages(messages, div);
This uses the completion functions of both fadeIn() and fadeOut() to carry out the next steps. Here's how it works:
It fades out the div.
In the completion function of the fadeOut, it sets the next message and then starts the fadeIn.
It advances the message counter.
In the completion function from the fadeIn, it calls the function to start the next iteration.
If you want a delay before the fadeOut (to make sure a given message displays for a certain amount of time), you can add that with this .delay(2000) added in the right place:
messages=["Welcome!","Добро пожаловать!"];
function fadeMessages(msgs, div) {
var i = 0;
function next() {
if (i < msgs.length) {
div.delay(2000).fadeOut(1000, function() {
div.html(msgs[i++]).fadeIn(1000, next);
});
}
}
next();
}
fadeMesssages(messages, div);
If you want a delay before the next iteration starts, you can do that like this with a setTimeout:
messages=["Welcome!","Добро пожаловать!"];
function fadeMessages(msgs, div) {
var i = 0;
function next() {
if (i < msgs.length) {
div.fadeOut(1000, function() {
div.html(msgs[i++]).fadeIn(1000, function() {
setTimeout(next, 2000);
});
});
}
}
next();
}
fadeMesssages(messages, div);

Javascript, local copying of a variable's value... struggling to achieve it

I have what i thought was a simple javascript / jquery function (fade out of one div, fade into another... loop until it reaches a maximum and then start back from the begining. The problem i have though is that to fadein the next div i need to increment the global counter. Doing this increments double increments it because i'm assuming the local variable i've created maintains the same reference to the global variable.
The code sample below should explain a little easier. Can anyone spot what i'm doing wrong?
var current_index = 1;
$(document).ready(function() {
$(function() {
setInterval("selectNextStep()", 3000);
});
});
function selectNextStep() {
$("#step_"+current_index).fadeOut('slow', function() {
var next = current_index;
next = next + 1;
$("#step_"+next).fadeIn('slow', function() {
if (current_index == 4) current_index = 1;
else current_index ++;
});
});
}
I think you're ending up with race conditions due to the interval trying to fade things in and the callbacks trying to fade things out. For this setup it makes more sense to let the fade callbacks start the next round.
Also using a 0-based index makes the math easier.
var current_index = 0; // zero indexes makes math easier
$(document).ready(function () {
$(function () {
// use timeout instead of interval, the fading callbacks will
// keep the process going
setTimeout(selectNextStep, 3000);
});
});
function selectNextStep() {
// +1 to adapt index to element id
$("#step_" + (current_index + 1)).fadeOut('slow', function () {
var next = current_index + 1;
// keeps index in range of 0-3
next = next % 4; // assuming you have 4 elements?
current_index = (current_index + 1) % 4;
// callback will start the next iteration
$("#step_" + (next + 1)).fadeIn('slow', function () {
setTimeout(selectNextStep, 3000);
});
});
}
demo: http://jsbin.com/exufu
I do not see any double increment the way your code is..
the problem is that the next variable goes beyond the 4 value that seems to be the limit, and trying to fadein an element that does not exist. so the code that resets the currentIndex never executes..
try adding if (next > 4 ) next = 1; after increasing the next variable
Example at http://jsfiddle.net/5zeUF/
isn't $(function() {}); the same as $(document).ready(function(){}), so you are initializing selectNextStep twice (hence the double increment)?
Try this. Simplifies things a little. Increments (and resets if needed) the current_index before the next fadeIn().
Example: http://jsfiddle.net/r7BFR/
var current_index = 1;
function selectNextStep() {
$("#step_" + current_index).fadeOut('slow', function() {
current_index++;
if (current_index > 4) current_index = 1;
$("#step_" + current_index).fadeIn('slow');
});
}
$(document).ready(function() {
setInterval(selectNextStep, 3000);
});
EDIT: Added example, and fixed my misspelling (camelCase) of current_index.
Here's an alternate way of doing the increment:
current_index = (current_index % 4) + 1;
Try this, slightly different approach but does what you need it to do I believe, also you can add more steps without modifying the script and doesn't pollute the global namespace (window)
[HTML]
​<div class="step defaultStep">One</div>
<div class="step">Two</div>
<div class="step">Three</div>
<div class="step">Four</div>
<div class="step">Five</div>
[CSS]
.step { display: none; }
.defaultStep { display: block; }​
[JS]
$( function() {
var steps = $( ".step" );
var interval = setInterval( function( ) {
var current = $( ".step" ).filter( ":visible" ), next;
if( current.next( ).length !== 0 ) {
next = current.next( );
} else {
next = steps.eq(0);
}
current.fadeOut( "slow", function( ) {
next.fadeIn( "slow" );
} );
}, 3000);
} );
Maybe you also want to have a look at the cycle plugin for jquery. There you can actually achieve such nice transitions. I think with a little work this would ease up everything.
http://jquery.malsup.com/cycle/
Regarding your code snippet. I think you can enhance it a little in this way:
$(document).ready(function() {
var current_index = 0;
window.setInterval(function() {
$("#step_"+ current_index).fadeOut('slow', function() {
$("#step_" + (current_index + 1)).fadeIn('slow', function() {
current_index = (current_index + 1) % 4;
});
});
}, 3000);
});
This should do the exact same work. As the interval function closes over the current_index variable it should be valid inside the function. Sorry, if you're not a fan of all these closures but I rather preferr passing the function I want to execute directly to the setInterval function, than defining it anywhere else.
P.S. Be aware that the changes I introduced imply that your #step_ IDs start at 0.

Categories

Resources