0

This is my html code:

<div class ="row respect-row">
    <div class="col-xs-6 myclass1">
        <h2 id ="respect-hover">MY HEADER</h2>
        <p style="display:none">paragraph text paragraph text paragraph text paragraph text paragraph text</p>
    </div>
</div>

This is my js code:

$(".respect-row").mouseover(function(){
            $(this).find("h2").animate({
                'marginTop' : "-=40px"
            },200);
            $(this).find("p").show(function(){
                $(this).find("p").animate({
                '   marginTop' : "-=40px"
                },200);
            });
            // $(this).find(".col-xs-6").animate({ "left": "+=160px" }, "slow" );
             $(this).css("width","320");
        });
        $(".respect-row").mouseout(function(){
            $(this).find("h2").animate({
                'marginTop' : "+=40px"
            });
            $(this).find("p").hide();
            $(this).css("width","160");
        });

What i want to achieve:

  1. Slide up, or animate in my case up 40px the h2 (header)on mouseover
  2. after when the h2 is moved up, i want to to change the width first from 160 to 320 and slide left with 160px
  3. when my div is slided left, i want to show my paragraph. Take a look also to the image: enter image description here

and on mouseout the opposite of what happened to mouseover. Can someone help me with this ?

UPDATE: http://jsfiddle.net/z468j1a4/1/

Jozsef Naghi
  • 1,085
  • 3
  • 14
  • 32

2 Answers2

0

This is somewhat tricky. jQuery animation queues are geared around animating/stopping a single element. Making a well-behaved queue for multiple elements is not straightforward.

What do I mean by "well behaved"? The behaviour you want can be achieved in several ways see Kevin B's answer here. However, it's not so simple to stop an animation queue comprising multiple elements. That is an issue for rapid mouseenter-mouseleave actions. Try it in your own solution and you will find that the animation can become confused.

There's probably several ways to overcome this issue. Here's one involving promise chains plus a mechanism for killing them if a previous animation chain is still in progress.

var t = 700;
$(".respect-row").on('mouseenter', function () {
    //In case an earlier animation is still in progress ...

    //...(i) withdraw permission for any earlier animation to continue
    var $this = $(this).data('continue', false);

    //...(ii) stop everything.
    $this.stop(true, true);
    var $h2 = $this.find("h2").stop(true, true);
    var $p = $this.find("p").stop(true, true);

    // Animations, each defined as a named function that returns a promise
    function anim1() {
        if($this.data('continue')) {
            return $h2.animate({
                'marginTop': '0px',
                'marginBottom': '20px'
            }, t).promise();//allow the rest of the animation chain to continue
        } else {
            return $.Deferred().reject().promise();//suppress the rest of the animation chain
        }
    }
    function anim2() {
        if($this.data('continue')) {
            return $this.animate({
                'width': '320px'
            }, t).promise();//allow the rest of the animation chain to continue
        } else {
            return $.Deferred().reject().promise();//suppress the rest of the animation chain
        }
    }
    function anim3() {
        if($this.data('continue')) {
            return $p.fadeIn(t).promise();//allow the rest of the animation chain to continue
        } else {
            return $.Deferred().reject().promise();//suppress the rest of the animation chain
        }
    }

    //Invoke forward animations with `continue` set to true
    $this.data('continue', true);
    anim1().then(anim2).then(anim3);
});
$(".respect-row").on('mouseleave', function revert() {
    //In case an earlier animation is still in progress ...

    //...(i) withdraw permission for any earlier animation to continue
    var $this = $(this).data('continue', false);

    //...(ii) and stop everything.
    $this.stop(true, true);
    var $h2 = $this.find("h2").stop(true, true);
    var $p = $this.find("p").stop(true, true);

    // Animations, each defined as a named function that returns a promise
    function anim1() {
        if($this.data('continue')) {
            return $h2.animate({
                'marginTop': '20px',
                'marginBottom': '0px'
            }, t).promise();//allow the rest of the animation chain to continue
        } else {
            return $.Deferred().reject().promise();//suppress the rest of the animation chain
        }
    }
    function anim2() {
        if($this.data('continue')) {
            return $this.animate({
                'width': '160px'
            }, t).promise();//allow the rest of the animation chain to continue
        } else {
            return $.Deferred().reject().promise();//suppress the rest of the animation chain
        }
    }
    function anim3() {
        if($this.data('continue')) {
            return $p.fadeOut(t).promise();//allow the rest of the animation chain to continue
        } else {
            return $.Deferred().reject().promise();//suppress the rest of the animation chain
        }
    }

    //invoke reverse animations with `continue` set to true
    $this.data('continue', true);
    anim3().then(anim2).then(anim1);
});

DEMO - slowed down to make the sequence easier to observe.

I'm afraid the simplicity of your own solution has vanished and this won't be the most obvious solution unless you are used to working with promises, but you will find it to be reliable with regard to rapid mouse movements.

BTW: A previous attempt to use .queue() and dequeue() was more elegant in achieving the required animation sequences but suppressing it proved difficult. I gave up and retreated back to promises, which I understand.

Community
  • 1
  • 1
Roamer-1888
  • 19,138
  • 5
  • 33
  • 44
0

Finally, I manage it out. Here is the my answer: http://jsfiddle.net/z468j1a4/2/

$(".respect-row").mouseenter(function(){

            $(this).find("h2").stop(true, true).animate({
                'marginTop' : "-=60px"
            },200);

            $(this).stop(true, false).animate({ width: "320px" });
            //$(this).find("p").show();
            $(this).find("p").fadeIn( 1200 );
        });
        $(".respect-row").mouseleave(function(){
            $(this).find("h2").stop(true, true).animate({
                'marginTop' : "+=60px"
            },200);
            $(this).stop(true, false).animate({ width: "160px" });
            $(this).find("p").hide();
        });

If you have a better version, would gladly accept it and mark it.

Jozsef Naghi
  • 1,085
  • 3
  • 14
  • 32
  • The animation looks fine but do you realise that the three steps run in parallel, not sequentially? – Roamer-1888 Jan 26 '15 at 11:39
  • I figure it out when i finished the script and thats what i am working for at the moment. If you can post an answer to this, i will accept it as answer – Jozsef Naghi Jan 26 '15 at 11:53
  • OK, I have replaced my original answer with something that actually works and is well behaved. – Roamer-1888 Jan 26 '15 at 15:32