views:

137

answers:

2

This is my first post on stackoverflow, hello everyone!

My first venture into jQuery animation is to have a set of images in two divs, top-half and bottom-half, and make them rotate through with a flip-down transition a-la the ancient alarm clocks with flip-down numbers.

I've got the animation down, but the problem is having more than one of these animating on the page simultaneously. My problem comes from not understanding the scope of jQuery selectors.

 $(document).ready(function(){
  flippers($('.flipper'));
 });

 function flippers(divs){
  divs.each(function(i){
   $(".top_container img").each(function (j){
    $(this).attr("id",i+"t"+j);
   });
   $(".bottom_container img").each( function(j){
    $(this).attr("id",i+"b"+j);
   });
  });
  var flip_wait = 3600;
  setTimeout("flippers_start("+flip_wait+")",flip_wait);
 }

 function flippers_start(time,flipper){
  var curr_top = '#' + $('.top_container img:visible').attr('id');
  var curr_bottom = '#' + $('.bottom_container img:visible').attr('id');
  if( ($('.top_container img').size() - 1) <= curr_top[3] ){
   var next_top = curr_top.substring(0,3) + 0;
   var next_bottom = curr_bottom.substring(0,3) + 0;
  }
  else{
   var next_top = curr_top.substring(0,3) + (parseInt(curr_top[3]) + 1);
   var next_bottom = curr_bottom.substring(0,3) + (parseInt(curr_bottom[3]) + 1);
  }

  var height = $(curr_top).height();
  var width = $(curr_top).width();

  flip(height,width,curr_top,curr_bottom,next_top,next_bottom);
  setTimeout("flippers_start("+time+")",time);
 }

    function flip(height,width,fromtop,frombottom,totop,tobottom){
  var fliptime = 250;

  $(frombottom).css("z-index","1");
  $(tobottom).css("z-index","2");
  $(fromtop).css("z-index","2");
  $(totop).css("z-index","1");

  $(tobottom).css("height","1px").show();
  $(totop).show();
  $(fromtop).stop().animate({height:'0px',width:''+width+'px',marginTop:''+height+'px'},{duration:fliptime});
  window.setTimeout(function() {
  $(tobottom).stop().animate({height:''+height+'px',width:''+width+'px',marginBottom:'0px',opacity:'1'},{duration:fliptime});
  },fliptime-40);
  $(frombottom).slideUp();
  window.setTimeout(function(){
   $(fromtop).height(height).hide().css("margin-top","0px");
  },fliptime*2);

}

when this is run on a set of images that i described,

<div class="flipper">
<div class="top_container">
 <img src="images/pink_floyd_img/dark1.jpg" class="top first" />
 <img src="images/pink_floyd_img/wall1.jpg" class="top second hidden" />
 <img src="images/pink_floyd_img/wish1.jpg" class="top third hidden" />
</div>
<div class="bottom_container">
 <img src="images/pink_floyd_img/dark2.jpg" class="bottom first" />
 <img src="images/pink_floyd_img/wall2.jpg" class="bottom second hidden" />
 <img src="images/pink_floyd_img/wish2.jpg" class="bottom third hidden" />
</div>
</div>

it works just the way I expect it. However when I duplicate the "flipper" div, the animation runs on the first set first, then runs on the second set, etc.

I know it has something to do with the way i'm selecting each image to animate as it happens, but I don't really know how else to do what I'm doing.

The ultimate goal is to be able to put together divs and images marked up with the proper classes and have each set dynamically id'd in order to run the animation--and also for them all to start animation simultaneously--even if they have separate calls for each div(which might end up happening so that they don't all flip at the same time).

Thanks!

A: 

This is also my first time on StackOverflow. I hope I can help.

What I think you need to do is call flippers_start() separately for each flipper on your page. You can use the flipper arg you already have in that function. It should be something like this:

function flippers(divs){
    var flip_wait = 3600;
    divs.each(function(i){
        var flipper = $(this);
        flipper.find(".top_container img").each(function (j){
            $(this).attr("id",i+"t"+j);
        });
        flipper.find(".bottom_container img").each( function(j){
            $(this).attr("id",i+"b"+j);
        });
        setTimeout(function(){
            flippers_start(flip_wait, flipper);
        },flip_wait);
    });
}

I changed the setTimeout call and put it inside the first each() so it's executed for each $('.flipper'). Note also that I'm using flipper.find(".top_container img") instead of $(".top_container img") to select only the images within the current flipper and that I pass the flipper as the second argument to flippers_start().

function flippers_start(time,flipper){
    var curr_top = '#' + flipper.find('.top_container img:visible').attr('id');
    var curr_bottom = '#' + flipper.find('.bottom_container img:visible').attr('id');
    if( (flipper.find('.top_container img').size() - 1) <= curr_top[3] ){
        var next_top = curr_top.substring(0,3) + 0;
        var next_bottom = curr_bottom.substring(0,3) + 0;
    }
    else{
        var next_top = curr_top.substring(0,3) + (parseInt(curr_top[3]) + 1);
        var next_bottom = curr_bottom.substring(0,3) + (parseInt(curr_bottom[3]) + 1);
    }

    var height = $(curr_top).height();
    var width = $(curr_top).width();

    flip(height,width,curr_top,curr_bottom,next_top,next_bottom);

    setTimeout(function(){
        flippers_start(time, flipper);
    },time);
}

In the above function I keep using flipper to select only the images within the current flipper div and changed the setTimeout call as before.

I hope this works for you.

I apologize for any spelling or grammatical errors you may find in what I just wrote. I'm not a native English speaker.

Willington Vega
I'm pretty sure this doesn't need to be CW.
Matt Ball
This is the exact direction I think I needed to head. Thanks very much for your help!PS Your English is better than many native speakers'!
Andy
@Matt Ball you're right. I clicked the checkbox without really knowing what CW mean. I'll be careful next time.
Willington Vega
A: 

The animate() function signature is:

animate(params, options)

One of the options is queue, which will tell the animation whether it should be added to the animation queue (true) or execute immediately (false). For example:

$('#myelement').animate({ left: "50px", opacity: 1 }, { duration: 500, queue: false });

That code will tell the animations to execute asynchronously.

See http://docs.jquery.com/Effects/animate#paramsoptions for more info.

richleland