This is a continuation from this post - :visible selector issue
Anyway, I was wondering if there is a way to detect if a particular code segment is run until it is completed before running a new line of code.
For example,
if(filterVal == 'all') {
jQuery('ul#portfolio li.hidden').fadeIn('slow').removeClass('hidden');
} else {
jQuery('ul#portfolio li').each(function() {
if(!jQuery(this).hasClass(filterVal)) {
jQuery(this).fadeOut('normal').addClass('hidden');
} else {
jQuery(this).fadeIn('slow').removeClass('hidden');
}
});
}
What I want to do is make sure that all the list-item elements are successfully fadeIn(display:block) and fadeOut(display:none) successfully before triggering the jPages function to create pagination.
There's a parameter in .fadeIn() that takes care of that.
$('ul#portfolio li.hidden').fadeIn('slow', function()
{
// Fade has finished, continue here.
//
//
});
Give it a callback function. Try:
jQuery(this).fadeOut('normal', function(){
$(this).addClass('hidden');
})
If you have to do it many times, use:
jQuery('ul#portfolio li').each(function() {
if(!jQuery(this).hasClass(filterVal)) {
jQuery(this).addClass('hidden');
} else {
jQuery(this).removeClass('hidden');
}
});
$('ul#portfolio li.hidden').fadeOut('normal', function(){
//Finished
});
$('ul#portfolio li:not("hidden")').fadeIn('slow', function(){
//Finished
});
So I think I found out how to do it using .promise()
My code looks something like this:
jQuery('ul#portfolio li').promise().done(function()
{
jQuery('ul#portfolio li').each(function()
{
console.log(jQuery(this).attr('class') + '-' + jQuery(this).css('display'));
});
});
Related
I know this might be silly but I would like to know if there is a way to realize.
Basically, I would like the dropdown-content element to 'KEEP DISPLAYING' even after 3 secs of mouse moving-out of the parental 'dropbtn' button or element.
E.g. code:
$(function() {
$('#dropbtn').hover(function() {
$('.dropdown-content').css('display', 'block');
}, function() {
// on mouseout:
setTimeout(function(){$('.dropdown-content').css('display', 'none');}, 3000);
});
$('.dropdown-content').hover(function(){
$('.dropdown-content').css('display', 'block');
},function(){
$('.dropdown-content').css('display', 'none');
})
});
Current issue is that setTimeout() function is overriding my desired way on this particular line of JS code:
$('.dropdown-content').css('display', 'block');
In another word, I want setTimeout() to be effective if and only if I set not my mouse cursor on 'dropdown-content' div.
Hope someone can help out :)
Instead of using hover, you could use mouseenter/mouseleave to 'toggle' the .dropdown-content, except the delay of 3s on mouseleave:
$(function() {
var dropdownTimeout = null;
$('#dropbtn').mouseenter(function() {
if(dropdownTimeout) {
clearTimeout(dropdownTimeout);
dropdownTimeout = null;
}
$('.dropdown-content').css('display', 'block');
});
$('#dropbtn').mouseleave(function() {
dropdownTimeout = setTimeout(function(){$('.dropdown-content').css('display', 'none');}, 3000);
});
});
I have next function:
function clearWorkingArea() {
$('.extensionText').children('span').fadeOut(600, function() { $(this).remove() });
$('ul.texts').fadeOut(600, function() { $(this).empty() });
$('.buttonsDiv').fadeOut(600, function() { $(this).remove() });
$('.processingDiv').fadeOut(600, function() { $(this).remove() });
}
I would like to call another function only after all animations in this function are finished.
I tried :
$.when(clearWorkingArea()).done(function() {...});
Also:
clearWorkingArea().promise().done(function() {...});
No luck, it is still not working properly.
Is there is a way, instead of callback hell of fades, to do such function behavior?
Update: just double checked jquery, animations can return a promise. I initially just did promise, but to get a promise with jquery you do promise(). So you don't need the helper function after all.
Below is an example.
Also if you have multiple selectors doing the same thing, you can combine.
eg. below .two & .three fadeOut at 600ms, but I've made .one fadeOut over 1000ms. Also added a none-existent selector to make sure things still work.
Promise.all(
[
$('.one').fadeOut(1000, function () {
$(this).empty(); }).promise(),
$('.two,.three').fadeOut(600, function () {
$(this).empty(); }).promise(),
$('.not-exist').fadeOut(600, function () {
$(this).empty(); }).promise()
]
).then(function () {
console.log('all done');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="one">
Three 1000 ms
</div>
<div class="two">
One 600 ms
</div>
<div class="three">
Two 600 ms
</div>
clearWorkingArea only starts the animations, but these animations are all async.
At the end of clearWorkingArea, your animations are unlikely to be over.
You have to fetch a promise for each animation and then use Promise.all to trigger your code when all promises are over.
According to the documentation, you can get the promise by using the start parameter in the options of fadeOut like methods:
jQuery fadeOut()
Hope this helps!
How about we apply some simple logic like this.
function doWorkWhenAllFinished(counter) {
if (counter == 4) {
//All fade animations have been complete.
//Good to go...
}
}
function clearWorkingArea() {
var counter = 0;
$('.extensionText').children('span').fadeOut(600, function() {
counter++;
$(this).remove();
doWorkWhenAllFinished(counter);
});
$('ul.texts').fadeOut(600, function() {
counter++;
$(this).empty();
doWorkWhenAllFinished(counter);
});
$('.buttonsDiv').fadeOut(600, function() {
counter++;
$(this).remove();
doWorkWhenAllFinished(counter);
});
$('.processingDiv').fadeOut(600, function() {
counter++;
$(this).remove();
doWorkWhenAllFinished(counter);
});
}
I have a simple page which toggles the visibility of departments, with a nice icon to show whether or not it is visible.
I am using font-awesomes icons "fa-eye" and "fa-eye-slash"
Problem is when using addClass jquery ignores the second "-" making
$(this).addClass("fa-eye-slash")
Add the class "fa-eye".
Its very strange and i've never encountered something like this with jquery. Please can someone assist me on how to overcome/work around this.
heres the fiddle http://jsfiddle.net/m5cdpnhk/
Thanks
You have two if conditions which run one after the other.
If the first if runs, then one of the things it does is $(elm).addClass('fa-eye-slash');.
The second if condition is if ($(elm).hasClass("fa-eye-slash")) so if the first if runs then the second will always run.
You need an else statement.
$(elm).addClass('fa-eye-slash');
} else if ($(elm).hasClass("fa-eye-slash")) {
$(elm).removeClass("fa-eye-slash");
Add an else option (the problem is the two if without the else in this case)
$(".box-body ul li i").click(function () {
var elm = $(this);
if ($(elm).hasClass("fa-eye")) {
$(elm).removeClass("fa-eye");
$(elm).css("color", "red");
$(elm).addClass('fa-eye-slash');
}else{
//if ($(elm).hasClass("fa-eye-slash")) {
$(elm).removeClass("fa-eye-slash");
$(elm).addClass("fa-eye");
$(elm).css("color", "green");
//}
}
});
or toggle the class
.red:before{
color:red
}
.green:before{
color:green;
}
$(".box-body ul li i").click(function () {
var elm = $(this);
$(elm).toggleClass("fa-eye").toggleClass("red");
$(elm).toggleClass("fa-eye-slash").togglesClass("green");
});
i don't know why your code don't work but try this :
$(".box-body ul li i").click(function () {
var elm = $(this);
if ($(elm).hasClass("fa-eye")) {
$(elm).removeClass("fa-eye");
$(elm).css("color", "red");
$(elm).addClass('fa-eye-slash');
}else{
$(elm).removeClass("fa-eye-slash");
$(elm).addClass("fa-eye");
$(elm).css("color", "green");
}
});
http://jsfiddle.net/m5cdpnhk/2/
You have done mistake.you have to place "else if" at second if condition.
if ($(elm).hasClass("fa-eye")) {
$(elm).removeClass("fa-eye");
$(elm).css("color", "red");
$(elm).addClass('fa-eye-slash');
}
else if ($(elm).hasClass("fa-eye-slash")) {
$(elm).removeClass("fa-eye-slash");
$(elm).addClass("fa-eye");
$(elm).css("color", "green");
}
QUESTION
How can I prevent a jquery toggle function from running before the previous toggle animation is complete?
I have a simple script to show or hide data depending whether a checkbox is checked.
JQUERY
$('.a').hide();
$('#CB').change(function () {
if ($(this).is(':checked')) {
$('.b').fadeOut(100, function () {
$('.a').fadeIn();
});
} else {
$('.a').fadeOut(100, function () {
$('.b').fadeIn();
});
}
});
PROBLEM
When the event is fired consecutively both elements, in this case .a and .b become visible together. I assume this is because the previous request is not completed prior to firing the function again.
CLICK FOR DEMO
http://jsfiddle.net/keypaul/PbS33/5/
$('.a').hide();
$('#CB').change(function () {
if ($(this).is(":checked")) {
$('.b').stop().fadeOut(100, function () {
$('.a').stop().fadeIn();
});
} else {
$('.a').stop().fadeOut(100, function () {
$('.b').stop().fadeIn();
});
}
});
Using jquery stop()
http://api.jquery.com/stop/
You're right. Animations in jQuery work asynchronously so they could sometimes run at the same time.
To answer your question, I think you already answered it in your question title.
Use a queue.
Set up a flag, name it something like isFading, and when it's true when $("#CB") changes, you queue it instead.
var isFading=false;
var animationQueue = [];
$('#CB').change(function () {
if(isFading){
if ($(this).is(':checked')) {
animationQueue.push(fadeOutFadeIn);
}
else {
animationQueue.push(fadeInFadeOut);
}
}
else{
if ($(this).is(':checked')) {
fadeOutFadeIn();
} else {
fadeInFadeOut();
}
}
);
function fadeOutFadeIn(){
isFading=true;
//insert your fadeout fadein code here
isFading=false;
if(animationQueue.length > 0)
//you're now calling the queued animation to go through
animationQueue.splice(0,1)();
}
function fadeInFadeOut(){
isFading=true;
//insert your fadein fadeout code here
isFading=false;
if(animationQueue.length > 0)
//you're now calling the queued animation to go through
animationQueue.splice(0,1)();
}
I have this code for hiding\showing link depends on state of cBoxoverlay. But when i click to close this item(display:none), and then click again to show it(display:block) my link(#close-news) still not showing.
jQuery(document).click(function () {
if (jQuery("#cBoxOverlay").css("display", "none")) {
jQuery("#close-news").css("display", "none");
} else if (jQuery("#cBoxOverlay").css("display", "block")) {
jQuery("#close-news").css("display", "block");
Where did i make mistake?
try this - no need for if statements. You can just set the #close-news to whatever #cBoxOverLay is
$(document).click(function () {
$("#close-news").css("display", $("#cBoxOverlay").css('display'));
}
Use classes, does a cleaner job.
In case you don't want to use classes, try to use jQuery's toggle, which does basically exactly what you try to achieve: http://api.jquery.com/toggle/
Use is(":visible") to check if the element is visible, and then either show or hide...
jQuery(document).click(function () {
if (jQuery("#cBoxOverlay").is(":visible")) {
jQuery("#close-news").hide();
} else {
jQuery("#close-news").show();
}
});
You can try:
if ($("#cBoxOverlay").css("display") == "none") {
// ...
}
however you can use is method:
if ( $("#cBoxOverlay").is(':hidden')) {
// ...
}
$(document).click(function(){
if ($("#cBoxOverlay").is(":hidden")) { // if #cBoxOverlay is hidden
$("#close-news").hide() // hide the #close-news
} else if ($("#cBoxOverlay").is(":visible")) { // if #cBoxOverlay is visible
$("#close-news").show() // // show the #close-news
}
})
you can remove the the second condition and use else instead as when element is not hidden it is visible, of course.
Try this, based on #Raminson's answer:
$(document).click(function () {
if ($("#cBoxOverlay").is(':hidden')) {
$("#close-news").css("display", "none");
} else{
$("#close-news").css("display", "block");
May be give a try on this one, too:
$(document).click(function(){
$('#close-news').css('display', function(){return $('#cBoxOverlay').css('display');});
});