make 'each' cycles occur consecutively - javascript

I have two actions I need to apply to a set of DIV's, but I need one cycle to happen before the other is finished.
Here is my code:
$("div").each(function(){
//do stuff first
}).each(function(){
//do stuff next
});
but at present, do stuff next happens before do stuff first finishes. Anything I can do to stop this?
Full Script
$("div").each(function(){
if($(this).html() === "yes"){
$(this).fadeOut(time,function(){
$(this).parent().height(0);
});
}
}).each(function(){
if($(this).html() !== "yes"){
$(this).parent().height(25);
$(this).fadeIn(time);
}
});

Knowing that you want to fadeIn and then set height, will this do what you require?
var divs = $('div');
divs.fadeIn(function () {
divs.height('200');
});
Using each to allow different settings for different divs:
$('div').each(function () {
var div = $(this), toggle = true;
div.fadeIn(function () {
if (toggle = !toggle) {
div.height('200');
} else {
div.width('200');
}
});
});
Seeing your code snippet I believe I got it now:
var yesDivs = $('div').filter(function () {
return $(this).html() === 'yes';
});
yesDivs.fadeOut(time, function () {
yesDivs.parent().height(0);
$('div').filter(function () {
return $(this).html() !== 'yes';
}).fadeIn(time).parent().height(25);
});

Related

use if statement to check if an element is display: block jquery

I'm trying to check if an element is display block, and if it is then i want to execute some code. Below is my code, its a large function but where I'm trying to check if a div is display block is at the bottom, and if it is display block then i want to execute the blur method.
As you can see near the bottom, I started writing if ($suggestionsWrapper === and my intention was to write if suggestions wrapper is display none, then do this. I just can't figure out how to execute this, what I've written doesn't work. Also I am new to all of this so sorry if this is really messy or doesn't make sense, still very much learning.
//Header Search Handler
function headerSearchHandler(){
var $searchInput = $(".header-search input[type=text]"),
$searchSubmit = $(".header-search input[type=submit]"),
$mobSearchBtn = $(".mobile-search-btn"),
$myAccountText = $(".menu-utility-user .account-text"),
$miniCart = $("#header #mini-cart"),
$searchForm = $(".header-search form"),
$headerPromo = $(".header-promo-area");
$suggestionsWrapper = $('#suggestions-wrapper');
//
$mobSearchBtn.on("click touchend", function(e) {
$(this).hide();
//$myAccountText.hide();
$searchInput.show();
$searchInput.addClass('grey-line');
$searchSubmit.show();
$miniCart.addClass("search-open");
$searchForm.addClass("search-open");
setTimeout(function() {
$searchInput.addClass("active").focus();
}, 100);
e.stopPropogation();
});
$searchInput.on("click touchend", function(e) {
$searchInput.addClass('grey-line');
e.stopPropogation();
}).blur(function(e) {
var $this = $(this);
if($this.hasClass("active")){
$this.removeClass("active");
$searchSubmit.hide();
$mobSearchBtn.show();
$miniCart.removeClass("search-open");
$searchForm.removeClass("search-open");
}
});
$searchInput.focus(function(e){
$(this).css('width', '145px');
})
if ($suggestionsWrapper.css('display') == 'none') {
$searchInput.blur(function(e){
$(this).removeClass('grey-line');
$(this).css('width', '145px');
}
})
}//End Header Search Handler
You can create a helper method to check if display is block or not :
function checkDisplay(element) {
return $(element).css('display') == 'block';
}
Then you can check it like :
if(checkDisplay("#myElement")){
console.log("Display is Block")
}
else {
console.log("Display is NOT Block")
}
here is an example : https://jsfiddle.net/fafgqv7v/
You can do something like this I think:
if ($suggestionsWrapper.css('display') == 'block')
{
// true
} else {
// false
}
Based off of your code I think you have the }) wrong, it should be:
if ($suggestionsWrapper.css('display') == 'none') {
$searchInput.blur(function(e){
$(this).removeClass('grey-line');
$(this).css('width', '145px');
})
}
I hope this helps!

Call one event on a set of matches

I do what something like:
$('div > img').onAll('load', function() { alert('Loaded!') })
Which would alert "Loaded!" only once
I don't want this:
$('div > img').on('load', function() { alert('Loaded!'); });
because this would call the event after every single image has been loaded
Is there any ready function in jQuery that calls an event on a set of matches? Or do I have to write a custom function for it?
Create your own method
$.fn.onAll = function(ev, callback) {
var xhr = [];
this.each(function() {
var def = new $.Deferred();
var ele = document.createElement(this.tagName.toLowerCase());
ele['on'+ev] = function() {
def.resolve();
}
ele.src = this.src;
xhr.push(def);
});
$.when.apply($, xhr).then(callback);
return this;
}
to be used as
$('div > img').onAll('load', function() { alert('Loaded!'); });
FIDDLE
Try this
var $images = $("div > img")
, imageCount = $images.length
, counter = 0;
// one instead of on, because it need only fire once per image
$images.one("load",function(){
// increment counter everytime an image finishes loading
counter++;
if (counter == imageCount) {
// do stuff when all have loaded
alert('Loaded!');
}
}).each(function () {
if (this.complete) {
// manually trigger load event in
// event of a cache pull
$(this).trigger("load");
}
});
try something like this
$('body').on('load','div > img',function() { alert('Loaded!') });
Happy Coding :)

Wait until div is not visible to process next line

I need to write some code which is supposed to wait until a predefined div is no longer visible in order to process the next line. I plan on using jQuery( ":visible" ) for this, and was thinking I could have some type of while loop. Does anyone have a good suggestion on how to accomplish this task?
$( document ).ready(function() {
$(".scroller-right" ).mouseup(function( event ) {
alert('right');
pollVisibility();
});
});
function pollVisibility() {
if ($(".mstrWaitBox").attr("visibility")!== 'undefined') || $(".mstrWaitBox").attr("visibility") !== false) {
alert('inside else');
microstrategy.getViewerBone().commands.exec('refresh');
} else {
setTimeout(pollVisibility, 100);
}
}
$( document ).ready(function() {
$(".scroller-right" ).mouseup(function( event ) {
alert('right');
pollVisibility();
});
});
function pollVisibility() {
if (!$(".mstrWaitBox").is(":visible")) {
alert('inside if');
microstrategy.getViewerBone().commands.exec('refresh');
} else {
setTimeout(pollVisibility, 100);
}
}
div when not visible:
<div class=​"mstrWaitBox" id=​"divWaitBox" scriptclass=​"mstrDialogImpl" dg=​"1" ty=​"edt">​
</div>​
div when visible:
<div class=​"mstrWaitBox" id=​"divWaitBox" scriptclass=​"mstrDialogImpl" dg=​"1" ty=​"edt" visibility="visible">​
</div>​
You can use the setTimeout function to poll the display status of the div. This implementation checks to see if the div is invisible every 1/2 second, once the div is no longer visible, execute some code. In my example we show another div, but you could easily call a function or do whatever.
http://jsfiddle.net/vHmq6/1/
Script
$(function() {
setTimeout(function() {
$("#hideThis").hide();
}, 3000);
pollVisibility();
function pollVisibility() {
if (!$("#hideThis").is(":visible")) {
// call a function here, or do whatever now that the div is not visible
$("#thenShowThis").show();
} else {
setTimeout(pollVisibility, 500);
}
}
}
Html
<div id='hideThis' style="display:block">
The other thing happens when this is no longer visible in about 3s</div>
<div id='thenShowThis' style="display:none">Hi There</div>
If your code is running in a modern browser you could always use the MutationObserver object and fallback on polling with setInterval or setTimeout when it's not supported.
There seems to be a polyfill as well, however I have never tried it and it's the first time I have a look at the project.
FIDDLE
var div = document.getElementById('test'),
divDisplay = div.style.display,
observer = new MutationObserver(function () {
var currentDisplay = div.style.display;
if (divDisplay !== currentDisplay) {
console.log('new display is ' + (divDisplay = currentDisplay));
}
});
//observe changes
observer.observe(div, { attributes: true });
div.style.display = 'none';
setTimeout(function () {
div.style.display = 'block';
}, 500);
However an even better alternative in my opinion would be to add an interceptor to third-party function that's hiding the div, if possible.
E.g
var hideImportantElement = function () {
//hide logic
};
//intercept
hideImportantElement = (function (fn) {
return function () {
fn.apply(this, arguments);
console.log('element was hidden');
};
})(hideImportantElement);
I used this approach to wait for an element to disappear so I can execute the other functions after that.
Let's say doTheRestOfTheStuff(parameters) function should only be called after the element with ID the_Element_ID disappears, we can use,
var existCondition = setInterval(function() {
if ($('#the_Element_ID').length <= 0) {
console.log("Exists!");
clearInterval(existCondition);
doTheRestOfTheStuff(parameters);
}
}, 100); // check every 100ms

jquery show hide each div onclick

I have a dynamic number of divs which generated through asp.net. I need to show each div contents by clicking on its header. I have tried this {
$(function () {
var myHead = $(".toggle-container").find(".toggle-header");
var myBody = $(myHead).parent().find(".toggle-content");
$(myHead).click(function () {
if ($(myBody).css('display') === 'none') {
$(this).children('i').removeClass('icon-chevron-sign-down').addClass('icon-chevron-sign-up');
$(this).parent().find(".toggle-content").slideDown("slow");
} else if ($(myBody).css('display') === 'block') {
$(this).children('i').removeClass('icon-chevron-sign-up').addClass('icon-chevron-sign-down');
$(this).parent().find(".toggle-content").slideUp("slow");
};
});
});
But it's working only for first header and rest of the headers doesn't collapse it's children content. Here is the JsFiddle Link what I have tried so far. Can anyone give a fix?
The problem was how you were finding the content to be displayed/hidden. You need to find the content related to the clicked header you the code var myBody = $(myHead).parent().find(".toggle-content"); should go inside the click handler as var myBody = $(this).next()
$(function () {
var myHead = $(".toggle-container .toggle-header");
$(myHead).click(function () {
var myBody = $(this).next()
if ($(myBody).css('display') === 'none') {
$(this).children('i').removeClass('icon-chevron-sign-down').addClass('icon-chevron-sign-up');
$(this).parent().find(".toggle-content").slideDown("slow");
} else if ($(myBody).css('display') === 'block') {
$(this).children('i').removeClass('icon-chevron-sign-up').addClass('icon-chevron-sign-down');
$(this).parent().find(".toggle-content").slideUp("slow");
};
});
});
Demo: Fiddle
Note: Still the up-down arrows are nor working because you need to use find() instead of children()
But it can be simplified as
jQuery(function ($) {
var $heads = $(".toggle-container .toggle-header");
$heads.click(function () {
var $this = $(this);
$this.find('i').toggleClass('icon-chevron-sign-down icon-chevron-sign-up');
$this.next().slideToggle("slow");
});
});
Demo: Fiddle
The below would work.
In your original code you had assigned the variable myBody a value at the time of load itself. Since there are many such elements, it used only the first one.
Now I have moved the value setting for the myBody variable to be inside the click event and used $(this). This will make sure that it always finds the element in relation to the current element that was clicked.
$(function () {
var myHead = $(".toggle-container").find(".toggle-header");
$(myHead).click(function () {
var myBody = $(this).parent().find(".toggle-content");
//console.log('yes');
if ($(myBody).css('display') === 'none') {
$(this).children('i').removeClass('icon-chevron-sign-down').addClass('icon-chevron-sign-up');
$(this).parent().find(".toggle-content").slideDown("slow");
} else if ($(myBody).css('display') === 'block') {
$(this).children('i').removeClass('icon-chevron-sign-up').addClass('icon-chevron-sign-down');
$(this).parent().find(".toggle-content").slideUp("slow");
};
});
});
Fiddle Demo

Wait for all async functions to complete in jQuery

I'm filtering table using jQuery and all is well. This code works nicely:
$("*[id$='EquipmentTypeDropDownList']").change(filterTable);
$("*[id$='StateDropDownList']").change(filterTable);
function filterTable() {
var $equipmentDropDown = $("*[id$='EquipmentTypeDropDownList']");
var $stateDropDown = $("*[id$='StateDropDownList']");
var equipmentFilter = $equipmentDropDown.val();
var stateFilter = $stateDropDown.val();
$("tr.dataRow").each(function () {
var show = true;
var equimpent = $(this).find("td.equipment").text();
var state = $(this).find("td.readyState").text();
if (equipmentFilter != "Any" && equipmentFilter != equimpent) show = false;
if (stateFilter != "Any" && stateFilter != state) show = false;
if (show) {
$(this).fadeIn();
} else {
$(this).fadeOut();
}
});
$("table").promise().done(colorGridRows);
}
function colorGridRows() {
//for table row
$("tr:visible:even").css("background-color", "#DED7D1");
$("tr:visible:odd").css("background-color", "#EEEAE7");
}
colorGridRows function changes background color of even/odd rows for readability
Now, It would be nice if I can replace show/hide calls with fadeIn/fadeOut but I can't because coloring doesn't work (it runs before UI effect completed. If it was just one function parameter - I would just create function for completion and be done with it. But my table has many rows and loop runs through each. How do I wait for ALL to compelete?
EDITED: Code sample updated showing how I try to use promise() but it doesn't work. It fires but I don't get odd/even coloring.
Use the promise object for animations.
$("*[id$='StateDropDownList']").change(function () {
var filtervar = $(this).val();
$('tr td.readyState').each(function () {
if (filtervar == "Any" || $(this).text() == filtervar) {
$(this).parent().fadeIn();
} else {
$(this).parent().fadeOut();
}
}).parent().promise().done(colorGridRows);
//colorGridRows();
});

Categories

Resources