How can I select elements (using jQuery) that do not contain any elements?
For example, in the following tree:
<div class="a">
<div class="b">
<div class="c"></div>
</div>
<div class="d"></div>
<div class="e">Lorem</div>
</div>
Only the <div>s with class c, d, and e will be selected.
$(':not(:has(*))')...
LIVE DEMO
If you want to do it with the filter function, be aware that > element will be deprecated in next jQuery versions!
you can use this:
$('*').filter(function(){
return $('*', this).length == 0
})
:empty selector won't work here because there is text node in the <div class="e">
use :empty selector:
$(':empty')...
docs:
Description: Select all elements that have no children (including text nodes).
Try this:
$('*').filter(function() {
return $(this).children().length == 0;
});
You might also be able to use (faster) native DOM access inside the filter function:
return this.children.length == 0;
Related
Is there any way to make the selectors here required:
var $el = $('.top').children(':gt(2), :contains("word")');
According to Multiple-Selectors, it will find the elements that match any of these two selectors.
How to find the elements that match all the selectors not any of them? jQuery( "selector1, selector2, selectorN" )
You can simply connect the two selectors to eachother:
var $el = $('.top').children(':gt(2):contains("word")');
The easiest to combine the selectors:
$('.a.b.c').css({'color':'blue'});
Another way would be to use a filter() function with the first selector and add the selector 2 to N inside the filter() using the is() function - see demo below:
/*This combines the three selectors .a .b and .c*/
$('.a').filter(function(){
return $(this).is('.b') && $(this).is('.c')
}).css({'color':'blue'});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="a">1</div>
<div class="b">2</div>
<div class="c">3</div>
<div class="a b">4</div>
<div class="a c">5</div>
<div class="b c">6</div>
<div class="a b c">7</div>
I'm trying to make my JS logic to use the $(this) so I can re-use my code in multiple elements in the same page so that they are each triggered individually.
this is my JS code:
$(".fab").on("click", function(){
$(this).toggleClass("clicked");
$(".screen2").addClass("active");
$(".box2 ,.box1 ,.box3").addClass("active");
});
$("#close").on("click", function(){
$(".screen2").removeClass("active");
$(".fab").removeClass("clicked");
$(".box1 ,.box2 ,.box3").removeClass("active");
});
My HTML:
<div class="app">
<div class="header"></div>
<div class="content">
<h1>Click the fab</h1>
</div>
<div class="fab"></div>
<div class="screen2">
<h1>new window</h1>
<div id="close"></div>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</div>
</div>
how can I use properly the $(this) ? All I'm trying to do is to make that JS code re-usable for multiple elements in the same page so that it triggers ONLY for the element where I clicked the .fab button...
You also need to use $(this), .prev(), .next(), .find(), .closest() etc. to traverse the DOM to refer to the elements near the one you're working on, otherwise it will target all of the classes in your document.
$(".fab").on("click", function(){
$(this).toggleClass("clicked");
$(this).next(".screen2").addClass("active");
$(this).next(".screen2").find(".box2 ,.box1 ,.box3").addClass("active");
});
$("#close").on("click", function(){
$(this).closest(".screen2").removeClass("active");
$(this).closest(".screen2").prev(".fab").removeClass("clicked");
$(this).closest(".screen2").find(".box1 ,.box2 ,.box3").removeClass("active");
});
You can store the jQuery selectors in an array, iterate through it, and for each jQuery selector in the array, use jQuery's .each() to iterate through its inner elements.
In the following example, there may be multiple instances of class1 in the DOM, for example.
var arrElements = [$('#id1'), $('#id2'), $('.class1')];
for (var i = 0; i < arrElements.length; i++) {
arrElements[i].each(function() {
$(this).on('click', function() {
// do stuff (use $(this) to refer to the current object)
});
})
}
Is there a way to check if a child div is the first item of the parent div?
For example:
<div id="parent">
Some text <--------- not the first thing in the div
<div id="child"></div>
</div>
Or
<div id="parent">
<div id="child"></div> <--------- is the first thing in the div
Some text
</div>
Something like
var isFirst = $('#child').is($('#parent').contents().filter(function () {
return this.nodeType != 3 || $.trim(this.nodeValue) != ''
}).first())
Demo: First, Not
There are few conditions to check
need to test text nodes so have to use .contents()
since empty text nodes has to be left alone need to use filter to filter empty text nodes out
I'm using the liferay framework and I need to add a JavaScript detected inline height to a very very specific div in my page. The problem is I need to target it going through an unknown number of dynamically added divs with dynamically added classes and IDs. To complicate this even further, the divs are randomly siblings or nested in each other.
Here's what it looks like:
<div class="known-class">
<div class="unknown dynamicallygenerated"></div>
<div class="unknown dynamicallygenerated">
<div class="unknown dynamicallygenerated">
<div class="unknown dynamicallygenerated"></div>
<div class="unknown dynamicallygenerated">
<div class="DIV-I-WANT-TO-TARGET">this is the div i need to Target with my css/javascript</div>
</div>
</div>
</div>
obviously I can't target it simply with
function resize() {
var heights = window.innerHeight;
jQuery('.DIV-I-WANT-TO-TARGET').css('height', heights + "px");
}
resize();
Because that class is present elsewhere, I would rather target it with something like.
jQuery('.known-class .DIV-I-WANT-TO-TARGET')
Which obviously doesn't work because there's a ton of other divs in the middle and my div is not a child of ".known-class"
I was asking myself if there was any jQuery that could help. Something like:
Catch any div with .DIV-I-WANT-TO-TARGET class that is "generically" inside another div that has .known-class
Is this possible? thanks a lot for your help!
Something like this would work:
// this will target the known-class and find all children with DIV-I-WANT-TO-TARGET
$('div.known-class').find('div.DIV-I-WANT-TO-TARGET');
// this will target the known-class and find the first DIV-I-WANT-TO-TARGET
$('div.known-class').find('div.DIV-I-WANT-TO-TARGET').first();
$('div.known-class').find('div.DIV-I-WANT-TO-TARGET:first');
$('div.known-class').find('div.DIV-I-WANT-TO-TARGET:eq(0)');
$('div.known-class').find('div.DIV-I-WANT-TO-TARGET').eq(0);
You can try in your css file
.known-class div div div div{}
The last div being the DIV-I-WANT-TO-TARGET
Assuming that you are adding the divs starting from the outer to the inner
Assign an equal name plus a number starting from 1
<div class="known-class">
<div class="unknown dynamicallygenerated" id="dynamicdiv1"></div>
<div class="unknown dynamicallygenerated" id="dynamicdiv2">
<div class="unknown dynamicallygenerated" id="dynamicdiv3">
<div class="unknown dynamicallygenerated" id="dynamicdiv4"></div>
<div class="unknown dynamicallygenerated" id="dynamicdiv5">
<div class="DIV-I-WANT-TO-TARGET" id="dynamicdiv6"></div>
</div>
</div>
</div>
The use jQuery [.each][1] to loop through all the divs on the document
$( document.body ).click(function() {
$( "div" ).each(function( i ) {
if ( this.style.color !== "blue" ) {
this.style.color = "blue";
} else {
this.style.color = "";
}
});
});
When you reach the last item in numeric order. (you can use any split function) add the attributes to that div
you need to select last div inside the known-class:
$('.known-class').find('div:last').css('background', 'Red')
OR if you want to select all the .known-class :
$('.known-class').each(function() {$(this).find('div:last').css('background', 'Red')});
Actually your selector works just fine:
$('.known-class .DIV-I-WANT-TO-TARGET')
With a space, selectors will find any descendant.
The search is only limited to direct descendants (immediate children) if you use the > operator.
So $('.known-class > .DIV-I-WANT-TO-TARGET') would not find what you wanted.
In my javascript experience, I found that is a very common task "searching the nearest ancestor of an element with some condition (tag name, class,...)".
Can the parents() method of jquery do the job? The order of returned elements of parents() is predictable? Is top-to-bottom or bottom-to-top?
For the moment I use this utility function:
function ancestor(elem, selector) {
var $elem = $( elem ).parent();
while( $elem.size() > 0 ) {
if( $elem.is( selector ) )
return $elem;
else
$elem = $elem.parent();
}
return null;
}
Can someone tell me if there is a clever way to do the job?
Edit: Since jQuery 1.3, this has been built in as the closest() function. eg: $('#foo').closest('.bar');
yep - parents() traverses up the tree.
<div id="a">
<div id="b">
<p id="c">
<a id="d"></a>
</p>
</div>
</div>
$('#d').parents("div:first"); will select div b.
Adding to #nickf's answer:
jQuery 1.3 simplifyed this task with closest.
Given a DOM:
<div id="a">
<div id="b">
<p id="c">
<a id="d"></a>
</p>
</div>
</div>
You can do:
$('#d').closest("div"); // returns [ div#b ]
[Closest returns a] set of
elements containing the closest parent
element that matches the specified
selector, the starting element
included.
You should use closest, because parents won't give you the result you expect if you're working with multiple elements. For instance, let's say you have this:
<div id="0">
<div id="1">test with <b>nested</b> divs.</div>
<div id="2">another div.</div>
<div id="3">yet <b>another</b> div.</div>
</div>
and you want to add a class to the divs that have a <b> element as their immediate child (ie, 1 and 3). If you use $('b').parents('div'), you get divs 0, 1 and 3. If you use $('b').parents('div:first'), you only get div 1. To get 1 and 3, but not 0, you have to use $('b').closest(elem).
closest() starts at current element, if the parent you are looking for has the same tag as current (eg. both are divs), use parent().closest()