views:

77

answers:

1

Hi all,

This is kind of difficult to explain, so I'll paste the function, and explain what it does

function close(r){
 if(r !== undefined){
  $('#close').attr('name','1');
  $('#close').css({
   top: 30,
   left: 30
  });
  $('#close').html('First click here');
 }else{
  switch($('#close').attr('name')){
   case '1':
    $('#close').attr('name','2');
    $('#close').animate({
     bottom: 30,
     right: 30
    },1000);
    $('#close').html('Now click here');
   break;
   case '2':
    $('#close').attr('name','3');
    $('#close').animate({
     bottom: 30,
     left: 30
    },1000);
    $('#close').html('A now click here');
   break;
   case '3':
    $('#close').attr('name','4');
    $('#close').animate({
     top: 30,
     right: 30
    },1000);
    $('#close').html('And finally click here');
   break;
   case '4':
    $('#close').remove();
   break;
  }
 }
}

If you require explanation, here it goes

  1. The close function is first called as close(1). This sets the position to top: 30 and left: 30. Note that its position is already set to absolute in the stylesheet. This first part works, and wherever I choose to place it is obeyed.
  2. The #close element has an oclick assigned to close(). Each time it is clicked, as you can see, a different action occurs. Everything works fine (i.e. the html and name attribute changes), except for the animation. The #close element remains stationary.
  3. On the last click, the element successfully disappears.

Does anyone have any ideas?

Cheers

Gausie

+1  A: 

First time round you set left: 30px. Second time round you set right: 30px. But left: 30px is still set. They are not exclusive properties; setting both is supposed to make the element expand to fit the amount of space between a 30px-left-edge and a 30px-right-edge.

However I'm guessing you have a fixed width on the close element. This leaves left: 30px; right: 30px; width: 100px which is over-constrained, causing the right property to be ignored, producing no movement. The same goes for top​/​bottom​/​height.

To animate between a left-aligned and right-aligned position you will need to script only one of left or right. To find out what the pixel position of left for a right-aligned position would be you will have to look at the size of the element's containing block. Assuming the containing block is the whole document:

<div id="close" style="background: red; position: absolute; width: 100px; height: 50px;">foo</div>
<script type="text/javascript">
    var close_step= 0;
    $('#close').click(function() {
        if (close_step>=4) {
            $(this).remove();
            return;
        }
        var w= $(window).width()-$(this).width()-30*2;
        var h= $(window).height()-$(this).height()-30*2;
        var x= [0, 1, 0, 1][close_step]*w+30;
        var y= [0, 1, 1, 0][close_step]*h+30;
        var pos= {left: x+'px', top: y+'px'};
        if (close_step===0)
            $(this).css(pos);
        else
            $(this).animate(pos);
        $(this).text([
            'First click here', 'Now click here', 'And now click here', 'And finally click here'
        ][close_step]);
        close_step++;
    }).click();
</script>

If #close were nested in a block with a position, you'd need to look at the width/height of that block instead of window.

bobince
What an awesome answer - thanks!I had just worked out the overconstraining problem by inspecting them DOM. But thankyou so much!
Gausie
How would one refer to the tactic of following an array with the key you wish to retrieve (` $(this).text([ 'First click here', 'Now click here', 'And now click here', 'And finally click here' ][close_step]);`)?
Gausie
hmmm... I don't know that there's a proper name for it as it's a fairly normal consequence of any language with array literals. I'll make up the name Inline Array Literal Dereferencing to make it sound posh.
bobince