fDruga
fDruga

Reputation: 269

Bootstrap dropdown - shown.bs.dropdown event not firing after css transition

I have this problem with the shown.bs.dropdown event handler for the bootstrap dropdown. At the show event i set the animation class and i want that after the animation is complete to remove the class. Unfortunately the event is firing immediately after the show event.

I tried applying the class in the attribute at runtime (thought that this way bootstrap will be aware about the css transition to be applied and to delay the shown event) but with no result. The animation classes are provided by animate.css library. I set up a fiddle to show my issue. - http://jsfiddle.net/u08bt6ck/

Here is my markup:

<ul class="nav navbar-nav">
    <li id="userMenu" class="dropdown">
        <a href="#" data-toggle="dropdown" class="dropdown-toggle">Open me</a>
        <ul class="dropdown-menu">
            <li><a href="#"><i class="fa fa-sliders"></i>lnk 1</a></li>
            <li><a href="#"><i class="fa fa-user"></i>lnk 2</a></li>
            <li><a href="#"><i class="fa fa-clock-o"></i>lnk 3</a></li>
        </ul>
    </li>
</ul>

And this is the js:

$('#userMenu').on({
    "show.bs.dropdown": function () {
        $('.dropdown-menu', this).addClass('animated fadeInDown');
    },
    "shown.bs.dropdown": function () {
        $('.dropdown-menu', this).removeClass('animated fadeInDown');
    },
    "hide.bs.dropdown":  function() {
        $('.dropdown-menu', this).addClass('animated fadeOutDown');
    },
    "hidden.bs.dropdown": function () {
        $('.dropdown-menu', this).removeClass('animated fadeOutDown');
        //alert('ni ca s-a terminat');
    }
});

Upvotes: 1

Views: 13817

Answers (4)

user773156
user773156

Reputation:

I had exactly the same problem and it made no sense why the dropdown events wouldn't fire for me properly; turns out that class="dropdown-toggle" in my <a> element interfered with its data-toggle="dropdown" attribute.

Why this is the case, no idea (probably a package issue I'm not willing to spend more time delving into), but removal of this class did it for me; no need for all those crazy manual animation class hacks in the events.

Upvotes: 0

Carol Skelly
Carol Skelly

Reputation: 362350

You just need to create delays for when the animation classes are added/removed. For the "hide" event, you'll need to prevent Bootstrap from hiding it too soon by manually removing the open class after your animation classes are added...

$('#userMenu').on({
  "shown.bs.dropdown": function () {
    $(this).find('.dropdown-menu').addClass('animated fadeInDown');
    setTimeout(function(){
        $('.dropdown-menu').removeClass('animated fadeInDown');
    },1000);
  },
  "hide.bs.dropdown":  function(e) {
    e.preventDefault();
    $(this).find('.dropdown-menu').addClass('animated fadeOutUp');
    setTimeout(function(){
        $('.dropdown-menu').removeClass('animated fadeOutUp').parent().removeClass('open');
    },1000);
  }
});

Demo: http://bootply.com/iZObFaEJwr

Upvotes: 1

fDruga
fDruga

Reputation: 269

For everyone having this problem i'll post here how i managed to work around this issue/problem.

Basically i set the fade in class when the user clicks and let it there until the menu is closing. If the menu starts to close, the fadeIn class is removed, the fadeOut class is added and after the animation is complete (handeled by the jquery .on([animationEndSelectors])) i remove the fadeOut class and close the submenu (by revmoving the open class on the ul).

var animationEndSelectors = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
var inAnimation = 'animated ' + 'fadeInDown';
var outAnimation = 'animated ' + 'fadeOutUp';

$('#userMenu').on({
    "show.bs.dropdown": function () {
        $('.dropdown-menu', this).addClass(inAnimation);
    },
    "hide.bs.dropdown":  function() {
        var ddl = this;

        $(ddl).addClass('closing');
        $('.dropdown-menu', this).removeClass(inAnimation);
        $('.dropdown-menu', this).addClass(outAnimation);
        $('.dropdown-menu', this).one(animationEndSelectors, function () {
            $('.dropdown-menu', ddl).removeClass(outAnimation);
            $(ddl).removeClass('open closing');
        });
        return false;
    }
});

Upvotes: 2

aaramans
aaramans

Reputation: 217

Try this way.

$('#userMenu').on({"show.bs.dropdown",function () {
    $('.dropdown-menu').addClass('animated fadeInDown');
});

$('#userMenu').on({"shown.bs.dropdown",function () {
    $('.dropdown-menu').removeClass('animated fadeInDown');
});

$('#userMenu').on({"hide.bs.dropdown",function() {
    $('.dropdown-menu').addClass('animated fadeOutDown');
});

$('#userMenu').on({"hidden.bs.dropdown",function () {
    $('.dropdown-menu').removeClass('animated fadeOutDown');
});

Upvotes: 0

Related Questions