Jquery .remove() does not update DOM - javascript

I am trying to remove an element form the DOM using the .remove() jQuery method
Basically i am parsing a list and removing certain elements. Then right after, i reparse the list for some treatment for the rest of the elements.
But a simple printout of the size of the list gives me the impression that the elements to be filtered out were not removed
$list = $(".elements_list");
alert( $list.size());
$list.each(function(){
if ( $(this).data("quantity") == 0)
{
$(this).slideUp(1000,function(){
$(this).remove();
});
}
});
change_background_colors();
Right after this treatment, i call another function that has the following code in the beginning:
function change_background_colors() {
$list = $(".elements_list");
alert($list.size());
...
}
I get the same size of the list before and after removing elements...
Is there something wrong in my approach ?
Thanks!

if you call the size alert in a setTimeOut function you will see
$list = $(".elements_list");
alert($list.size());
$list.each(function () {
if ($(this).data("quantity") == 0) {
$(this).slideUp(1000, function () {
$(this).remove();
});
}
});
setTimeout(function () {
$list = $(".elements_list");
alert($list.size());
}, 2000);
JSFiddle:
https://jsfiddle.net/upkkLq2m/2/

The element is not removed until after 1000 milliseconds pass and the animation completes. Wait until then to count the elements.
edit: here's the more complicated way to delay till all animates complete:
$list = $(".elements_list");
var n = 0;
$list.each(function(){
if ( $(this).data("quantity") == 0) {
n = n + 1; // one more callback to wait for
$(this).slideUp(1000,function(){
$(this).remove();
n = n-1;
checkIfAllDone();
});
}
});
function checkIfAllDone(){
if(n===0){ // be sure that n was declared in the same scope as this function
change_background_colors();
}
}

Related

do something when js element is loaded , is not working

I have this Jquery function to click on an element when its ready. its an interval doing it , the following function:
MonitorAndClick(selector) {
var ele = $(selector);
if (ele.length == 0) {
var intervalid = setInterval(function () {
var ele = $(selector);
if (ele.length > 0) {
ele[0].click();
clearInterval(intervalid);
return true;
}
}, 500);
} else {
ele[0].click();
return true;
}
}
the problem is in some cases , its not working. however this is an interval , and it's checking the element to be ready every 0.5 sec, so how can it be possible ? is there any other way to check the element is ready ?
additional note:
I have an accordion. I have a function to open the accordion->open one of the items->open the tab page in detail section
this is the function :
//--reach to this point, open accordion index 2--------
ShowAccordion(2);
//----open the item with specific Id in accordion items------
setTimeout(function () {
var selector = "tr[gacategory = '/myprotection/mywills/item_" + parseInt(willId) + "]";
MonitorAndClick(selector);
}, 500);
the point is this element SHOULD be there , sometimes its not loading fast enough , and I WANT TO HAVE A WAY TO CHECK IF ITS LOADED, THEN CLICK ON THAT.
Updated code after comments
var selector = "tr[gacategory = '/myprotection/mywills/item_" + parseInt(willId) + "]";
$("#selector").ready(function () {
console.log('**********.... selector is loaded ....*****');
if (!$("#selector").hasClass('selected'))
MonitorAndClick(selector);
});
still not working.
Why do you want to rely on 0.5 seconds delay to make sure your element is present in DOM. You should be invoking this function only after your element is present in the DOM. If there is another condition that drives when this element is added to the DOM, then call this function once that condition is achieved.
You may want to try https://api.jquery.com/ready/
It seems like jquery ready function can be applied on individual elements too

How do I make jQuery statement execute after .load()?

Sorry for the possibly terrible question title. I don't know how to word it properly. Please offer suggestions.
Anyhoo, I have this html:
<ul class="image_reel">
<li class="thin"><img class="gal_thumb" src="8681.jpg"></li>
<li class=""><img class="gal_thumb" src="DSC_7586.jpg"></li>
<li class="thin"><img class="gal_thumb" src="DSC_7601.jpg"></li>
</ul>
I want to assign the li either a 'thick' or 'thin' class based on the height of the child img. So I have this jQuery:
// add 'thin' class to parent li
jQuery('.image_reel li a img').load(
function() {
var t = jQuery(this);
var h = this.naturalHeight;
if( h < 800 ) {
jQuery(t).parent().parent().addClass( 'thin' );
}
});
// now sort lis
var $images = jQuery('.image_reel');
var $imagesli = $images.children('li');
$imagesli.sort(function(a,b){
var aT = jQuery(a).hasClass('thin');
var bT = jQuery(b).hasClass('thin');
if( aT == true && ( bT == false ) )
return 1;
else
return 0;
});
$imagesli.detach().appendTo($images);
The problem seems to be that the first block seems to execute -after- the second block. Or maybe they execute synchronously? Regardless, the code doesn't work. So... how do I make the first block of code execute -before- the 2nd?
The weird thing is that, if I use the Firefox 'Q' debugger, the code actually 'works'. But without the debugger it doesn't. I assume that the debugger forces the code to run in some sort of special order.
Wrap your section block in a function, and then call it after the load function ends, like put it in the return
// add 'thin' class to parent li
jQuery('.image_reel li a img').load(function() {
var t = jQuery(this);
var h = this.naturalHeight;
if( h < 800 ) {
jQuery(t).parent().parent().addClass( 'thin' );
}
return loadBlock();
});
function loadBlock() {
// now sort lis
var $images = jQuery('.image_reel');
var $imagesli = $images.children('li');
$imagesli.sort(function(a,b){
var aT = jQuery(a).hasClass('thin');
var bT = jQuery(b).hasClass('thin');
if( aT == true && ( bT == false ) ) {
return 1;
} else {
return 0;
}
});
$imagesli.detach().appendTo($images);
}
Or use a package like async .waterfall or .series
You can use something like async as I mentioned above to have better flow control over async functions here's an example on how you could avoid calling on every callback
async.each($("img"), function(e, callback) {
$(this).load(function() {
console.log("bdbdbd");
callback(); // Done loading image
});
}, function() {
console.log("Done loading images");
loadBlock();
});
Async package can and will be your best friend if utilized properly.
I'm on mobile so I can't really test but this worked just fine on jsbin just throw your code in there and it should work.
this works because when you call jQuery('.image_reel li a img').load this will run its own loop on every element it finds and attach the event listener to it.
The method I used was I used async.each which takes an array, in this case I provided $('#img') as the array which will be a collection of any element it finds that matches the query, then async.each will run the loops in parallel so we don't have to wait for one to finish before the loop can proceed to the next thing.
Then in the loop body we call .load on .this which is attaching the .load function on only 1 element at a time and not trying to do its own internal loop on all the elements, so this way when the function completes we know that its done cause that function is only running on on element. Then we call callback(); which is required for async.each to let .each know that the function body is done and it can proceed, when all loops trigger their callback the loop ends and then the main function executes (the function that's the third argument to .each). You can see more about async.each here: async.each
The second block executes before the first block because the load() resolves immediately and only calls the first block later when it has finished. To do what you want, call the second block at the end of the first block.
// add 'thin' class to parent li
jQuery('.image_reel li a img').load(
function() {
var t = jQuery(this);
var h = this.naturalHeight;
if( h < 800 ) {
jQuery(t).parent().parent().addClass( 'thin' );
}
doWork();
});
function doWork() {
// now sort lis
var $images = jQuery('.image_reel');
var $imagesli = $images.children('li');
$imagesli.sort(function(a,b){
var aT = jQuery(a).hasClass('thin');
var bT = jQuery(b).hasClass('thin');
if( aT == true && ( bT == false ) )
return 1;
else
return 0;
});
$imagesli.detach().appendTo($images);
}

.slideToggle nested ajax repeater

I have a function that writes out to a cooke the value of the DIV that holds that data that I want to show, the cookie code works, the toggle code works but when the page refreshses, I can get the list of repeater elements, itterate through them, determine if the section should be hidden or not but I can't use visible, I can't use .show() or .hide(), I know this has to be easy but what am I over looking???
This is my working code for the slidetoggle that works and writes the true or false to the cooke based on the repeater title attribute:
$(document).ready(function () {
$("a.toggle").click(function () {
var inObj = $(this).parent().find('div#fader');
var inTitle = inObj.attr('title');
inObj.slideToggle('fast', function () {
docCookies.setItem(inTitle, inObj.is(':visible').toString());
});
});
});
This is the code block that I have the problem with, specifically, the .show() and the .hide() are not known methods, so I have the object in inObj[] collection, I am not sure how to cast this or deal with this in javascript.....
$(window).load(function () {
var inObj = $('div#fader');
for (var i = 0; i < inObj.length; i++) {
var objTitle = inObj[i].title;
var item = docCookies.getItem(objTitle);
if (item == "true") {
inObj[i].show();
}
else {
inObj[i].hide();
}
}
});
Use $(inObj[i]).show() and $(inObj[i]).hide().

How to initiate an action after 3 mouse clicks

I am new to writing code but I'm trying to figure out to have a div disappear after being clicked three times. I know how to get it to disappear after one or two clicks but I'm not sure how to do it after three. I wrote a while loop that should iterate up once after each click but instead the function doesn't wait for the div to be clicked and goes ahead and fades out the div.
var threeClick = function() {
var n = 0;
while(n > 2) {
$(document).ready(function() {
$('div').click(function(){
n++;
});
});
$(document).ready(function(){
$('div').fadeOut('slow');
});
}
}
threeClick();
var n
$(document).ready(function()
{
n=0;
$('div').click(function()
{
n++;
if(n==3)
{
n=0;
$('div').fadeOut('slow');
}
});
}
$(document).ready(function() {
var n = 0;
$('div').click(function() {
n++;
if (n == 3) {
$(this).fadeOut('slow');
}
});
});
see this
You don't have to repeat $(document).ready. This is a method (from jQuery) called when DOM is ready. So your code should go in this function;
This should work:
$(document).ready(function() {
var n = 0;
$('div').click(function() {
n++;
if(n == 3) {
$('div').fadeOut('slow');
}
});
});
I'm wondering why your while loop doesn't block execution while it sits and spins. JavaScript is not multi-threaded; there is a single thread of execution and I would imagine that the while would block that thread. But aside from that it won't really work because you're never checking the value of n before you fade out the div. This is why the fade-out happens almost immediately. There is also no need for numerous $(document).ready(...) calls; one will do.
I would also recommend using .on:
$(document).ready(function() {
var n = 0;
$('div').on('click', function() {
n++;
if(n >= 3) {
$('div').fadeOut('slow');
}
});
});
This works because the n which has been defined in the anonymous function (passed to .ready) is available to the callback (closure) passed to .on or .click. Closures are lexically bound to the scope in which they are defined, which means that anything defined in the enclosed scope is available to the closure. So your n's value will be updated and available to the closure.
You may try this too
$(function(){
$('#myDiv').on('click', function(){
var clicks = $(this).data('clicks') || 0;
$(this).data('clicks', clicks+1);
if($(this).data('clicks') >=3 ) $(this).fadeOut();
});
});
DEMO.
You need to create the variable holding the count outside of the function or it will reset each time the function is called. Give the div a class name - here i have used 'divClassName'.
var numClicks = 0;
$(function() {
$(document).on("click",".divClassName",function() {
numClicks+=1;
if (numClicks > 2) {
$('div').fadeOut('slow');
}
}
};
With jQuery you could do something like that
var counter=0;
$('div').on('click',function(){
counter++;
if(counter==3)$('div').fadeOut();}
);

A Function to Check if the Mouse is Still Hovering an Element Every 10 Milliseconds (and run a function if it is)

I was wondering if there is a function to be run after an element (e.g. div class="myiv") is hovered and check every X milliseconds if it's still hovered, and if it is, run another function.
EDIT: This did the trick for me:
http://jsfiddle.net/z8yaB/
For most purposes in simple interfaces, you may use jquery's hover function and simply store in a boolean somewhere if the mouse is hover. And then you may use a simple setInterval loop to check every ms this state. You yet could see in the first comment this answer in the linked duplicate (edit : and now in the other answers here).
But there are cases, especially when you have objects moving "between" the mouse and your object when hover generate false alarms.
For those cases, I made this function that checks if an event is really hover an element when jquery calls my handler :
var bubbling = {};
bubbling.eventIsOver = function(event, o) {
if ((!o) || o==null) return false;
var pos = o.offset();
var ex = event.pageX;
var ey = event.pageY;
if (
ex>=pos.left
&& ex<=pos.left+o.width()
&& ey>=pos.top
&& ey<=pos.top+o.height()
) {
return true;
}
return false;
};
I use this function to check that the mouse really leaved when I received the mouseout event :
$('body').delegate(' myselector ', 'mouseenter', function(event) {
bubbling.bubbleTarget = $(this);
// store somewhere that the mouse is in the object
}).live('mouseout', function(event) {
if (bubbling.eventIsOver(event, bubbling.bubbleTarget)) return;
// store somewhere that the mouse leaved the object
});
You can use variablename = setInterval(...) to initiate a function repeatedly on mouseover, and clearInterval(variablename) to stop it on mouseout.
http://jsfiddle.net/XE8sK/
var marker;
$('#test').on('mouseover', function() {
marker = setInterval(function() {
$('#siren').show().fadeOut('slow');
}, 500);
}).on('mouseout', function() {
clearInterval(marker);
});​
jQuery has the hover() method which gives you this functionality out of the box:
$('.myiv').hover(
function () {
// the element is hovered over... do stuff
},
function () {
// the element is no longer hovered... do stuff
}
);
To check every x milliseconds if the element is still hovered and respond adjust to the following:
var x = 10; // number of milliseconds
var intervalId;
$('.myiv').hover(
function () {
// the element is hovered over... do stuff
intervalId = window.setInterval(someFunction, x);
},
function () {
// the element is no longer hovered... do stuff
window.clearInterval(intervalId);
}
);
DEMO - http://jsfiddle.net/z8yaB/
var interval = 0;
$('.myiv').hover(
function () {
interval = setInterval(function(){
console.log('still hovering');
},1000);
},
function () {
clearInterval(interval);
}
);

Categories