Check if a div has any children - javascript

I have the below code that checks to see if any of my divs has the class "wrong" and if so it shows the jQuery UI dialog box. However i want to extend the code so that it checks those divs and if there are any that are empty it should not show the dialog box.
I've looked around and some people are suggesting using children().length > 0 to accomplish this, but I'm not sure how to write this with my code.
js:
$("#run").click(function() {
if ($("[id^='Drop']").hasClass("wrong")) {
$("#dialog1").dialog("open");
}
});

The following selectors could be used to test if an element is empty or not:
:empty matches elements that have no children (thus, empty)+
:parent matches elements that have children+
Now, rephrasing your statement:
... so that it checks those wrong divs and if
there are any that are empty they are all full it should
not show the dialog box.
You would write:
var $allWrong = $("id[^='Drop'].wrong"),
$notEmpty = $wrong.filter(":parent");
if ($allWrong.length && $allWrong === $notEmpty) {
// show dialog
}
+ Text nodes are counted when counting children. <span> </span> contains a text node which contains a whitespace. Therefore it matches :parent and does not match :empty.

The logic consists of two parts:
Finding elements with id property starting with "Drop" and having the .wrong class.
Checking whether any of those elements are empty.
To do this, I'm saving the first step in an intermediate variable, before doing the final condition:
var $wrongFields = $('[id^="Drop"].wrong');
if ($wrongFields.length && !$wrongFields.filter(':empty').length) {
// at least one field exists with:
// - id starting with "Drop"
// - class of "wrong"
// and none of those fields are empty
$("#dialog1").dialog("open");
}
Demo

This would also work
$("#run").click(function(){
if ($("[id^='Drop']").hasClass("wrong") && $("[id^='Drop'].wrong:empty").length ) {
$( "#dialog1" ).dialog( "open" );
}
});

Related

jQuery .remove() Not Working After Valid Selection of Element

JSFiddle: https://jsfiddle.net/coh1xr77/5/
I need to delete an <LI> DOM Element correctly selected with a Selector based on its exact content. My list contains a set of Time LI's and my choice is to delete the first one in the list, 12:15am, based on the exact text match, when I click the button.
I can see that my selection is correct because I'm getting an [Object] reference in the alert box, rather than "Undefined".
However, the subsequent remove() on this element does nothing: the element remains.
var myselection = '12:15am';
$('#remove').click(function() {
var current = $('.ui-timepicker-list li').filter(function() {
return $(this).text() === myselection;
});
alert('current = ' + current); // This works, element found
$(current).remove(); // This does nothing (or doesn't remove properly)
});
You need to change the condition to check if the li's innerText starts with the selected time string. Like: $(this).text().indexOf(myselection) == 0
Here's the updated fiddle: https://jsfiddle.net/coh1xr77/11/
Update
Considering that all time values have the bracketed relative time strings at the end, you could try splitting based on that bracket (, and compare with the first part of that string. Like: $(this).text().split('(')[0].trim() == myselection
Here's the fiddle with that: https://jsfiddle.net/coh1xr77/12/
Update 2
If you are absolutely certain that the structure of li elements will not change, you could access the text using the childNodes. Like: $(this)[0].childNodes[0].textContent == myselection;
Here's the updated fiddle: https://jsfiddle.net/coh1xr77/14/

Click outside element - JQuery

I'm looking to understand how to hide an element when you click outside.
Here's one from:
https://css-tricks.com/dangers-stopping-event-propagation/
$(document).on('click', function(event) {
if (!$(event.target).closest('#menucontainer').length) {
// Hide the menus.
}
});
Could someone break this down for me please? I don't understand why we need to use the length property?
Also does closest traverse up to the top of the DOM from wherever it starts and then stop one it reaches the top?
Cheers
You need to check the length because jQuery queries always return a result, which is empty if nothing was found. Once you check the length you can tell if the click is inside (length > 0, an element was found) or outside (length === 0, no element was found)
Here is a break down:
line 1:
$(document).on('click', function(event) { ... });
binds on any click made in your document (DOM). make use that you unbind (.off('click', .....); after you used it. Otherwise it will be endlessly executing on every click.
line 2:
if (!$(event.target).closest('#menucontainer').length) {
event.target ===(equals) the element that is click in the dom.
.closest('#menucontainer') = get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree. Meaning: when there is clicked inside MenuContainer it will return an array with the first '#menucontainer' element. When there is click outside the MenuContainer it will return an Empty array. (no element found).
.length = The default behavior from JQuery is to return an empty array when nothing is found. If you put and empty array in a If statement it will return true. because its an Defined Object. Its defined as an Array. however the number 0 == false. thats with they put .length on the array. It will return 0 (false) when its empty of > 0 (true) when it found an element.
In JavaScript, everything is 'truthy' or 'falsy', and for numbers 0 (and NaN) means false, everything else true.
check NickG his link( Is there an "exists" function for jQuery? )
A jQuery selector will return an array with all the matched elements. If you use an ID as selector such as ('#menucontainer') the length will be 0 or 1. The closest menu will not be found, if we click something outside of the menu, the negation will be true and menu can be hidden.
// Get the current clicked element
!$(event.target)
// Get closest container with this id, bubbling up the DOM
.closest('#menucontainer')
// returns 1 if we clicked something inside the menu and 0 if we clicked something outsite
.length

check element has some element inside using jquery

You can do like if($('.div').find('.someelem').length == 0 .. to check whether .someelem is available inside the div,
but what if I want to check for any element? I don't know what is the class within.
<div>
</div>
^ Check above div contain something or not.
A faster way to do it is using .find() cause it will not trigger the somewhat expensive jQuery's Sizzle Selector Library:
if( !$(".div").find(">")[0] ){
// Maybe has text, but has absolutely no children Elements.
}
If you want to be more specific about your selectors, instead of using ">" (any immediate child) you can use "div" aswell, to restrict your search to DIV Elements only.
You can also check with "if is empty"
$(".div:empty").someMethodYouWant(); // Do some stuff on empty elements. (Really empty)
or
if( $(".div").is(":empty") ){
// Has no elements and no text
}
note that the above will yield false if you have just some text (means it's not empty).
If you rather want to go for immediate children > elements
if( !$(".div:has(>)").length ){
// Maybe has text, but has absolutely no children Elements.
}
or also:
if( !$(".div:has(>)")[0] ){
// Maybe has text, but has absolutely no children Elements.
}
or even simpler:
if( !$(".div >")[0] ){
// Maybe has text, but has absolutely no children Elements.
}

Javascript: How to perform count on visible elements only?

I'm using jQuery to get a string from a search field and hide items that don't match. It loops through a list of divs and uses $(this).fadeOut(); to hide those elements.
This works very well, but I would like to add further searches within that search. I've added an extra search field, but of course it doesn't inherit the fade outs from the previous search and it starts again from the beginning.
I need a way to specify to the searches to only search visible elements of the list. This needs to work in reverse order as users might enter in the the second search field, then the first.
Here's a JSFiddle of my code illustrating the problem
JSFiddle Here
And a code snippet of one search function
$("#filter").keyup(function () {
var filter = $(this).val(),
count = 0;
$(".records2 div").each(function () {
// If the list item does not contain the text phrase fade it out
if ($(this).text().search(new RegExp(filter, "i")) < 0) {
$(this).fadeOut();
// Show the list item if the phrase matches and increase the count by 1
} else {
$(this).show();
count++;
}
});
});
You can use:
element.is(":visible")
To test if a given element is visible or not.
So in your case you'd just do:
if ($this).is(":visible")); {count++;}
Or you can add ":visible" to the end of your selectors to only pick the visible items:
$(".someselector div:visible").each(...);
Edit: I just checked the jquery documentation. You get better performance if you do:
$(".someselector div").filter(":visible").each(...);
This is because :visible isn't part of the CSS specification so jquery has to implement it manually.

remove delete button on first set of fields

http://jsfiddle.net/NzbRQ/2/
I allow the user to add multiple rows of fields, but I do not want to include a delete link on the very first row of fields, so they can't delete all the fields.
Also, how do I limit it to only 3 rows of fields?
Try this fiddle: Fiddle
For the first part of hiding the delete on the first row, I called the following on page load:
$(".removeoutcome").hide();
Then to make sure they can't add more than 3 or delete the last one, I've added length checks in your click methods, see:
$('.addoutcome').live('click', function() {
if ($(".outcomegroup").length < 3) {
$('#template').clone().removeAttr('id').insertAfter($(this).closest('.outcomegroup')).find('.minus').show();
renumber();
}
});
$('.removeoutcome').live('click', function() {
if ($(".outcomegroup").length > 1) {
$(this).closest('.outcomegroup').remove();
renumber()
}
});
Also, on a side note, live is deprecated now, so if you're using jQuery 1.7, change these methods to on or if you're pre-1.7, use delegate.
You can just hide the del for first element and limit it to add only 3 more set using the following code
var count = 3;
$('.minus').first().hide();
$('.addoutcome').live('click', function() {
count--;
if(count < 0 )return;
$('#template').clone().removeAttr('id').insertAfter($(this).closest('.outcomegroup')).find('.minus').show();
});
here is the working fiddle http://jsfiddle.net/joycse06/uW9NQ/
Updated: http://jsfiddle.net/NzbRQ/5/
First off, ditch .live. I added the section to give a more specific selector than body, but there's probably something better that you can use in your original DOM.
Just don't remove the last row with some simple logic. Your logic for showing the future "del" link was actually already there! You don't even really need the last-row-removal logic at all since just not displaying "del" is enough, but I was just being thorough.
I don't know why anyone haven't paid close attention to this line:
.find('.minus').show();
where he definitely was un-hiding the del element. In short, the only thing you need to do is add the proper CSS rule:
.minus { display: none; }
and that's it, the first element won't show a del link and the others will.
The limit to three elements simply.
$("[parent element]").on('click', '.addoutcome', function() {
if($('.addoutcome').length > 2) return;
...
});
A better selector [parent selector] is needed and depends totally in your layout. Basically, it is the element that wraps all these elements, the parent element of all of them.

Categories

Resources