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

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">
Open me
<ul class="dropdown-menu">
<li><i class="fa fa-sliders"></i>lnk 1</li>
<li><i class="fa fa-user"></i>lnk 2</li>
<li><i class="fa fa-clock-o"></i>lnk 3</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');
}
});

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;
}
});

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

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');
});

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.

Related

animated effect for fadein/fadeout using jQuery

To understand my code please visit this page:
Please click on packaging filter first
http://codepen.io/mariomez/pen/qNrzAr?editors=0010
It's a simplified animated filtering method.
Each red box might have more than one classes as an identifier for the filter.
My goal with this code is to achieve a nice animated way for fade-in and for fade-out. For now I managed to do this only for fade-in.
Even though I wrote the animation for fade-out I can't use it properly in the JS code.
Example for 1 filter: I want all classes except "packaging" to fade-out nicely and have the packaging class fade-in.
jQuery CODE
$(document).ready(function(){
$(".filter-logo").click(function(){
$(".all").fadeOut(normal,addClass('animated fadeOutEffect'));
$(".logo").fadeIn(normal,addClass('animated fadeInEffect'));
});
$(".filter-website").click(function(){
$(".all").fadeOut();
$(".website").fadeIn().addClass('animated fadeInEffect');
});
$(".filter-packaging").click(function(){
$(".all").fadeOut();
$(".packaging").fadeIn().addClass('animated fadeInEffect');
});
$(".filter-forsale").click(function(){
$(".all").fadeOut();
$(".forsale").fadeIn().addClass('animated fadeInEffect');
});
$(".filter-all").click(function(){
$(".all").fadeOut();
$(".logo, .website, .packaging, .forsale, .all").fadeIn().addClass('animated fadeInEffect');
});
});
Trying to use the fade-in animation: (FAILED)
$(".all").not('.packaging').fadeOut().addClass('animated fadeOutEffect');
$(".packaging").fadeIn().addClass('animated fadeInEffect');
});
How can I improve this code?
I have updated your example.
http://codepen.io/jammer99/pen/mEQabN
Essentially you need to set fadeout to finish within 0 seconds forcefully, additionally since you have already used css to generate the animation, you should use hide() and show() instead of fadeOut() and fadeIn()
here's the updated code
$(document).ready(function() {
$(".all").each(function() {
$(this).addClass("animated")
})
$(".filter-logo").click(function(e) {
e.preventDefault();
$(".all").removeClass('fadeInEffect').addClass("fadeOutEffect").hide(0);
$(".logo").show(0).removeClass("fadeOutEffect").addClass('fadeInEffect');
});
$(".filter-website").click(function(e) {
e.preventDefault();
$(".all").removeClass('fadeInEffect').addClass("fadeOutEffect").hide(0)
$(".website").show(0).removeClass("fadeOutEffect").addClass('fadeInEffect');
});
// UPDATE CODE - START ////////////
$(".filter-packaging").click(function(e) {
e.preventDefault();
$(".all").removeClass('fadeInEffect').addClass("fadeOutEffect").hide(0);
$(".packaging").show(0).removeClass("fadeOutEffect").addClass('fadeInEffect');
});
// UPDATE CODE - END ////////////
$(".filter-forsale").click(function(e) {
e.preventDefault();
$(".all").removeClass('fadeInEffect').addClass("fadeOutEffect").hide(0);
$(".forsale").show(0).removeClass("fadeOutEffect").addClass('fadeInEffect');
});
$(".filter-all").click(function(e) {
e.preventDefault();
$(".all").removeClass('fadeOutEffect').addClass("fadeInEffect").show(0)
});
});
EDIT : Here is updated code. http://codepen.io/jammer99/pen/mEQabN?editors=0010
$(document).ready(function() {
$(".all").each(function() {
$(this).addClass("animated")
})
$(".filter-logo").click(function(e) {
e.preventDefault();
$(".all").removeClass('fadeInEffect').addClass("fadeOutEffect")
setTimeout(function() {
$(".all").hide(0)
$(".logo").stop().show(0).removeClass("fadeOutEffect").addClass('fadeInEffect');
}, 500);
});
$(".filter-website").click(function(e) {
e.preventDefault();
$(".all").removeClass('fadeInEffect').addClass("fadeOutEffect")
setTimeout(function() {
$(".all").hide(0)
$(".website").stop().show(0).removeClass("fadeOutEffect").addClass('fadeInEffect');
}, 500);
});
$(".filter-packaging").click(function(e) {
e.preventDefault();
$(".all").removeClass('fadeInEffect').addClass("fadeOutEffect")
setTimeout(function() {
$(".all").hide(0)
$(".packaging").stop().show(0).removeClass("fadeOutEffect").addClass('fadeInEffect');
}, 500);
});
$(".filter-forsale").click(function(e) {
e.preventDefault();
$(".all").removeClass('fadeInEffect').addClass("fadeOutEffect")
setTimeout(function() {
$(".all").hide(0)
$(".forsale").stop().show(0).removeClass("fadeOutEffect").addClass('fadeInEffect');
}, 500);
});
$(".filter-all").click(function(e) {
e.preventDefault();
$(".all").removeClass('fadeInEffect').addClass("fadeOutEffect")
setTimeout(function() {
$(".all").show(0).removeClass("fadeOutEffect").addClass('fadeInEffect');
}, 500);
});
});
For your Example for 1 filter, you're saying you want "packaging" to be the only one to not fade out, but then have "packaging" fade in even though it didn't fade out?
I'm going to assume you want everything to fade out, then have "packaging" fade in. You can do so by calling the fadeIn for "packaging" inside a callback when you fadeOut .all.
Edit:
So the fadeOut function takes a completion callback, a function that will run after the fadeOut animation completes. You just need to pass in an anonymous function to the fadeOut parameter, and inside that function do what you want to do after the animation completes:
$(".filter-packaging").click(function(){
$(".all").fadeOut(function() {
$(".packaging").fadeIn().addClass('animated fadeInEffect');
});
});
Basically your css and js animations are clashing. You should probably stick to one or the other. Also both js animations are running at the same time fadeIn and fadeOut.
An option is to wait until the fadeOut animation ends before starting the fadeIn animation. You can do that with a timeout.
In the example below the function hideThenShow waits until the of the fadeOut animation (500ms) then runs the fadeIn on the selected elements.
As a bonus you could loop through your filters and your list elements instead of repeating the hideThenShow function in the example.
Hope it helps
function hideThenShow($clickedElement, $elementsToShow){
var duration = 500;
$clickedElement.click(function(){
$('.all').fadeOut(duration);
setTimeout(function(){
$elementsToShow.fadeIn();
},duration);
});
}
$(document).ready(function(){
var filterLogo = $(".filter-logo");
var filterWebsite = $(".filter-website");
var filterPackaging = $('.filter-packaging');
var filterForsale = $('.filter-forsale');
var filterAll = $(".filter-all");
var websiteElemetns = $('.website');
var logoElements = $(".logo");
var packagingElements = $('.packaging');
var forsaleElements = $('.forsale');
var allElements = $(".all");
hideThenShow(filterLogo, logoElements);
hideThenShow(filterWebsite, websiteElemetns);
hideThenShow(filterPackaging, packagingElements);
hideThenShow(filterForsale, forsaleElements);
hideThenShow(filterAll, allElements);
});
.ullist li {width:100px;background:#f00; height:100px; display:block; float:left;clear:none; margin:25px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="secmenu">
<ul>
<li>All</li>
<li>Logo</li>
<li>Website</li>
<li>Packaging</li>
<li>For sale</li>
</ul>
</div>
<ul class="ullist">
<li class="website all">text</li>
<li class="website all">text</li>
<li class="website all">text</li>
<li class="packaging all">text</li>
<li class="packaging all">text</li>
<li class="logo all">text</li>
<li class="logo all">text</li>
<li class="logo all">text</li>
<li class="logo all">text</li>
<li class="logo all">text</li>
<li class="forsale all">text</li>
</ul>

JQuery - Cannot seem to bind event to dynamic DOM elements

Using JQuery UI Draggable, I am cloning elements as they leave an unordered list. As these are new to the DOM, i'm trying to use the JQuery On() method to bind an event which will show a hidden link. The anchor with the class cancel has display: none; in the css.
HTML
<ul class="current-campaign">
<li class="draggable">One <a class="pull-right cancel" href="#">
<i style="color:red">Icon</i>
</a>
</li>
</ul>
<ul class="new-campaign sortable"></ul>
JQuery
$(".sortable").sortable();
$(".draggable").draggable({
connectToSortable: ".sortable",
helper: "clone",
});
$(".current-campaign").on("mouseout", ".cancel", function () {
$(".cancel").show();
});
Really having trouble figuring out why the link doesn't show up when it leaves the unordered list. Here's a JS fiddle to see it in action.
http://jsfiddle.net/og937wy7/
FINAL EDIT WITH ANSWER
Armed with the knowledge of how to use the on() function, I fixed up my code so it's working as I intended.
$(document).on("mouseover", ".new-campaign", function (e) {
console.error($(this));
$(".new-campaign").find('.cancel').show();
});
http://jsfiddle.net/og937wy7/4/
You are attaching an event to .cancel, which is not at all in the view:
$(".current-campaign").on("mouseout", ".cancel", function () {
$(".cancel").show();
});
How can you mouseout, when .cancel doesn't have an area? Replace it with .draggable:
$(".current-campaign").on("mouseout", ".draggable", function () {
$(".cancel").show();
});
I guess you are looking for the cancel to be shown once you hover and when you come away, it should hide. So change your code to:
$(".current-campaign, .new-campaign").on("mouseout", ".draggable", function () {
$(".cancel").hide();
}).on("mouseover", ".draggable", function () {
$(".cancel").show();
});
I would also tell this is not a right way, because, it affects all the .cancel. So you might need to use $(this).find():
$(".current-campaign, .new-campaign").on("mouseout", ".draggable", function () {
$(this).find(".cancel").hide();
}).on("mouseover", ".draggable", function () {
$(this).find(".cancel").show();
});
Fiddle: http://jsfiddle.net/dpojx7so/
But, everything can be done using CSS itself!!!
You just need to add this CSS, instead of the whole JS:
.sortable:hover .cancel {
display: inline;
}
Fiddle: http://jsfiddle.net/mx58stx3/

Bootstrap nav-tabs with progress bar

I am building a registration system and I have a progress bar and a bootstrap nav-tabs in that page.
I am trying to setup the JQuery so that the progress bar advances with the nav-tabs. Here is a visual.
I tried to come up with a simple if else conditional jquery using hasClass and addCLass functions but never got to make a dent.
Something like this:
$(document).ready(function () {
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
if (".nav-tabs") hasClass(".active"); {
$(".checkout-bar li").addClass("active");
}
});
});
I am attaching a CODEPEN
Any idea on how to do this client side? I'd rather keep C# out of this one
http://jsfiddle.net/o3637uwh/2/ (update)
in html remove class form all checkout-bar li, except first
HTML
<ul class="checkout-bar">
<li class="active">Get Started</li>
<li class="">About You</li>
<li class="">Looking For</li>
<li class="">Review</li>
</ul>
JQ (update)
$(document).ready(function () {
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
var href = $(e.target).attr('href');
var $curr = $(".checkout-bar a[href='" + href + "']").parent();
$('.checkout-bar li').removeClass();
$curr.addClass("active");
$curr.prevAll().addClass("visited");
});
});
You are not specifying which .checkout-bar li to select. You have to get the index of the .active tab and with this index select the checkount li, I think you shoud do something like this:
$(document).ready(function () {
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
activeTabIndex = $('.nav.nav-tabs > li.active ').index();
(".checkout-bar li.active").removeClass('active');
$(".checkout-bar li:eq("+activeTabIndex+")").addClass('active')
});
});

jQuery sliding menu error

I'm doing animated menu with jQuery (3 levels). I'm using efects slideDown and slideUp. Sometimes (but no always), when I open submenu of first main item, submenu of second main item won't work until I refresh the page. It works OK with efects fadeIn and fadeOut, but I want to use slide.
Here is my code: http://jsfiddle.net/mcCAx/
The problem was the styling on your <ul class="SubStage"> element was being overridden. So, fight fire with fire by re-overwriting the styling in a callback. Your side menu shows up every time. :)
$(document).ready(function()
{
$('li.MainStage').hover(
function()
{
$(this).find('ul.SubStage').slideDown('slow',function(){
$(this).parent().find('ul.SubStage').css({overflow:"visible"});
});
},
function()
{
$(this).find('ul.SubStage').stop().slideUp('slow');
});
$('li.SubStage').hover(
function()
{
$(this).find('ul.Sub2Stage').slideDown('slow');
},
function()
{
$(this).find('ul.Sub2Stage').stop().slideUp('slow');
});
});​
Check it out here.
This fixed it for me Here
$(document).ready(function()
{
$('li.MainStage').hover( function()
{
$(this).stop();
$(this).find('ul.SubStage').slideDown('slow');
}, function()
{
$(this).stop();
$(this).find('ul.SubStage').slideUp('slow');
});
$('li.SubStage').hover( function()
{
$(this).stop();
$(this).find('ul.Sub2Stage').slideDown('slow');
}, function()
{
$(this).stop();
$(this).find('ul.Sub2Stage').slideUp('slow');
});
});

Having trouble with jQuery toggle function for dropdown menu

I have a dropdown menu that slides up and down when toggled to reveal it's menu items. The problem is that when i go to click one of the menu items after the menu has slid down, it is recognized as a toggle and the menu slides up without opening the link of the menu item.
HTML
<li class="dropdown">
Carbohydrates, proteins & fats
<ul>
<li>Carbohydrates</li>
<li>Proteins</li>
<li>Fats</li>
</ul>
</li>
dropdown script:
$(document).ready(function () {
$('.dropdown').toggle(
function () {
//show its submenu
$('ul', this).slideDown(300);
},
function () {
//hide its submenu
$('ul', this).slideUp(300);
}
);
});
I'd appreciate any help with this.
Try moving the triggering link outside of the dropdown items
Carbohydrates, proteins & fats
<div class="divdropdown">
<ul>
<li>Carbohydrates</li>
<li>Proteins</li>
<li>Fats</li>
</ul>
</div>​
And then slightly modify your jquery
$(document).ready(function () {
$('.dropdown').toggle(
function () {
//show its submenu
$('ul', $(".divdropdown")).slideDown(300);
},
function () {
//hide its submenu
$('ul', $(".divdropdown")).slideUp(300);
}
);
});​
Why are you individually closing/opening the menu items? Everything gets hidden anyway when the parent <li> element is hidden -- why do anything after that?
I think you want to disable event bubbling.
EDIT 1: You're over-complicating things. Try this:
$(document).ready(function () {
$('.dropdown').toggle();
});
EDIT 2: Can you be more specific about what you want? If you want a particular element, when clicked, to control the motion of a particular list, try this:
$(document).ready(function () {
$('a.someLink').click(function() {
$('.dropdown').toggle();
});
});
Unfortunately none of the above answers were working for me. I found a solution shortly afterwards.
HTML
<li class="dropdown">
<a class="disablelink" href="#">Carbohydrates, proteins & fats</a>
<ul class="sub_navigation">
<li>Carbohydrates</li>
<li>Proteins</li>
<li>Fats</li>
</ul>
</li>
jquery script
$(document).ready(function() {
$('.dropdown').click(function() {
// When the event is triggered, grab the current element 'this' and
// find it's children '.sub_navigation' and display/hide them
$(this).find('.sub_navigation').slideToggle();
});
$(".disablelink").click(function(e) {
e.preventDefault();
});
});
That solution is working perfectly for me. I added in e.preventDefault(); to stop the page jumping up and down when i clicked on the link.

Categories

Resources