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>
Related
I have this almost working but not quite. I just want to be able to keep switching between two unordered list items on a button click fading the first item out as the second fades in. Then do it the opposite way on another click. On the first click it works, as does the second, but I'm not sure where to go after that. The first li item is just a bg image that will change to some text on click, then back to the image on another click. Thanks in advance. T
$(document).ready(function() {
$('#myButton').click( function() {
$('.contentOne').fadeOut( 'slow', function() {
$('.contentTwo').fadeIn('slow', function() {
$('#myButton').click(function() {
$('.contentTwo').fadeOut( 'slow', function() {
$('.contentOne').fadeIn('slow');
});
});
});
});
return false;
});
});
Maybe this can help you:
html
<button id="changeToText">
Change
</button>
<div class="gizBrainButton">
first class
</div>
<div class="gizBrainButton">
first class
</div>
<div class="showGizText" style="display:none;">
Second class
</div>
<div class="showGizText" style="display:none;">
Second class
</div>
js
$('#changeToText').click(function() {
if ($('.gizBrainButton').is(':visible')) {
$('.gizBrainButton').fadeToggle(1000).promise().done(function() {
$('.showGizText').fadeToggle(1000);
});
} else if($('.showGizText').is(':visible')) {
$('.showGizText').fadeToggle(1000).promise().done(function() {
$('.gizBrainButton').fadeToggle(1000);
});
}
});
You could store the state of one of the content parts and toggle visibilty based on that. For example:
$(document).ready(function () {
/** #var boolean */
var isContentOneVisible = true;
/** #var string */
var fadeSpeed = 'slow';
$('#myButton').click(function () {
if (isContentOneVisible) {
$('.contentOne').fadeOut(fadeSpeed);
$('.contentTwo').fadeIn(fadeSpeed);
isContentOneVisible = false;
return;
}
$('.contentOne').fadeIn(fadeSpeed);
$('.contentTwo').fadeOut(fadeSpeed);
isContentOneVisible = true;
});
});
jQuery provides fadeToggle aswell. It would ease implementing your use case as it keeps track of state itself.
I would prefer a lightweight vanilla solution. For example, you could toggle a classname on an element wrapping the elements you want to show and hide. Use CSS to toggle their visibility, possibly using transitions to mimic the effect jQuery implemented.
Below some example code to get you going.
HTML:
<button class='contentToggler'>Show secondary content</button>
<ul class='toggleableContent'>
<li class='toggleableContent__item toggleableContent__item--first'><!-- content --></li>
<li class='toggleableContent__item toggleableContent__item--second'><!-- content --></li>
</ul>
CSS:
.toggleableContent__item {
opacity: 1;
transition: opacity .5s ease;
}
.toggleableContent--isToggled .toggleableContent__item--first,
.toggleableContent__item--second {
opacity: 0;
}
.toggleableContent--isToggled .toggleableContent__item--second {
opacity: 1;
}
Javascript:
document.addEventListener('DOMContentLoaded', function (event) {
var toggler = document.querySelector('.contentToggler');
var toggleableContent = document.querySelector('.toggleableContent');
if (!toggler || !toggleableContent) {
return;
}
toggler.addEventListener('click', function (event) {
toggleableContent.classList.toggle('toggleableContent--isToggled');
});
});
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.
I'm trying to assign two actions to a button in jQuery. The button is supposed to:
open a hidden div, and...
scroll down to get said div into view.
While both actions are working on the button, they currently require 2 clicks. On the first click the div appears, but to scroll it into view I need to click the button a second time.
Any suggestions how I am going wrong?
jQuery
$(document).ready(function () {
"use strict";
$('.footer a').click(function (event) {
event.preventDefault();
$('.impr-text').hide(); // hide previous popup div
var id = $(this).data("id"); // get the div id which to show
$('#' + id).fadeIn(function () { // show cuurent click link's popup
$(this).css({
'display': 'block'
});
});
$.scrollTo( '#impressum-footer', 800, {easing:'elasout'} );
});
});
HTML
<div id="impressum-footer">
<div class="footer">
<div class="inner-wrap-imp">
<ul class="impressum-links">
<li>Impressum</li>
<li>|</li>
<li>Datenschutz</li>
<li class="impressum-button" ></li>
</ul>
</div>
</div>
<div id="impr-text" class="impr-text">
<div class="inner-wrap"> ...
You need to put the scrollTo in the fadeIn completion callback handler. That way callTo is performed on completion of the fadeIn rather than, essentially, at the same time. Currently you seem to also be placing a callback function where another parameter is to go (either duration or options object depending on which method signature you are using). Not sure why you have the css change there at all.
Try something like this:
$(document).ready(function () {
"use strict";
$('.footer a').click(function (event) {
event.preventDefault();
$('.impr-text').hide(); // hide previous popup div
var id = $(this).data("id"); // get the div id which to show
$('#' + id).fadeIn({
duration: 100, // or whatever duration you want to use
complete: function() {
$.scrollTo( '#impressum-footer', 800, {easing:'elasout'} );
}
});
});
});
if you want to assign 2 different actions on one button, set it 2 different classes (or IDs), lets say
<div class="action1 action2">
After, in jQuery you will be able to do:
$('.action1').on('click', function (e) { console.log('#1'); ... });
$('.action2').on('click', function (e) { console.log('#2'); ... });
JsFiddle: http://jsfiddle.net/g2wdd2cb/
I have now managed to get it going. The approach as explained by #euvl was the one...
I changed my code (the scrolling part) after I realized it wasn't working. The final (working) code now looks like this:
jQuery:
$(document).ready(function () {
"use strict";
$('.footer-action-1 a').click(function (event) {
event.preventDefault();
$('.impr-text').hide(); // hide previous popup div
var id = $(this).data("id"); // get the div id which to show
$('#' + id).fadeIn(function () { // show cuurent click link's popup
$(this).css({
'display': 'block'
});
});
});
});
$(document).on('click','.footer-action-2 a', function(event) {
event.preventDefault();
var target = "#" + this.getAttribute('data-target');
$('html, body').animate({
scrollTop: $(target).offset().top
}, 2000);
});
HTML:
<div id="impressum-footer">
<div class="footer footer-action-1 footer-action-2">
<div class="inner-wrap-imp">
<ul class="impressum-links">
<li>Impressum</li>
<li>|</li>
<li>Datenschutz</li>
<li class="impressum-button" ></li>
</ul>
</div>
</div>
<div id="impr-text" class="impr-text">
<div class="inner-wrap">
The only problem now is that it scrolls a little too far. The moment I add an offset it stops working.
Thanks to you guys, my menu is now usable because the submenu displays long enough for the user to get their mouse to the links. Unfortunately, it's not exactly right. The submenu closes even when the users mouse is over it. I have added the HTML code below along with the revised js file code. I'm thinking the problem is in the $('.myMenu > li').bind('mouseout', closeSubMenu); line. Perhaps an alternative would be to have a timeout delay AFTER the openSubMenu function is called to at least give users 8 seconds or so before the submenu hides. This would be an acceptable solution to me.
<!-- HTML menu code below -->
<ul class="myMenu">
<li class="menuHeader">Employees <img src="images/arrowdown.gif" alt="Employee Links" width="11" height="8" border="0"/>
<ul class="subMenu">
<li>Link1</li>
<li>Link2</li>
<li>Link3</li>
<li>Link4</li>
</ul></li>
</ul>
<!-- js file code below -->
$(document).ready(function() {
$('.myMenu > li').bind('mouseover', openSubMenu);
$('.myMenu > li').bind('mouseout', closeSubMenu);
function openSubMenu() {
$(this).find('ul').css('visibility', 'visible');
};
function closeSubMenu() {
var ul = $(this).find('ul');
setTimeout(function(){
ul.css('visibility', 'hidden');}, 10000);
};
});
Your setTimeout callback did nothing, you should put the code in the callback function.
setTimeout is not something like sleep.
function closeSubMenu() {
var ul = $(this).find('ul');
setTimeout(function(){
ul.css('visibility', 'hidden');
}, 2000);
};
try something like that. if you toggle to hide, then it'll delay for 3 sec before hide. if the toggle to show, $('#toggle-item') will clear the queue and show the item,
function toggle(show){
if (show) {
$('#toggle-item').stop().clearQueue().show();
} else {
$('#toggle-item').delay(3000);
}
}
the setTimeout command works like this setTimeout(the function to execute, delay in milliseconds)
so, this is what you need to do:
setTimeout($(this).find('ul').css('visibility', 'hidden'),3000);
note that from $(this) to 'hidden') is the actual command. if that doesn't work, try this instead:
//place this in your <head> section
function closeDropDownFunction() {
$(this).find('ul').css('visibility', 'hidden');
}
//then place this wherever the timeout needs to be
setTimeout(closeDropDownFunction(), 3000);
I have one drop down menu,
<ul>
<li><a>link 1</a>
<ul><li><a>link 1</a></li></ul>
</li>
</ul>
I am using the following JS to use hover and show child menus.
I want to add delay to the mouse out function (when the class of the LI removed) about 500ms,
$('li').hover(function(){
$(this).addClass('over');
}, function(){
$(this).removeClass('over');
});
Please do needful in this.
thanks in advance
You can do something like this:
$('li').hover(function(){
var timer = $(this).data('timer');
if(timer) clearTimeout(timer);
$(this).addClass('over');
}, function(){
var li = $(this);
li.data('timer', setTimeout(function(){ li.removeClass('over'); }, 500));
});
This clears any timeout when hovering over it (in case you hover, leave, hover back you need to check this) and sets a 500ms delay when leaving the hover, storing the timeout ID on the li itself using .data().
$('li').hover(function(){
$(this).addClass('over');
}, function(){
setTimeout(function(){$(this).removeClass('over')}, 500);
});