<div class="a">
<span class="a">a</span>
<span class="a">b</span>
<span class="a">c</span>
</div>
Assuming I have a variable called divA representing the top level div node. divA.querySelectorAll('.a') will return a list of the 3 span.as. I wonder if there's an easy way to return a list of 4 elements including the divA itself?
I know I could start from a higher level node, but let's assume there might be other .a elements that I don't want to mess with them.
In reality I still need to test whether divA matches my selector or not. So is there a way for css selector to test an element itself?
I could create a parent node and run querySelectorAll from there. But if there's an easier way, I don't need to go that far.
I still need to test whether divA matches my selector or not. Is there
a way for css selector to test an element itself?
querySelector() cannot return the context element it's running on.
What you can do is use #Andreas' solution followed by a filter()/matches() combo.
[divA, ...divA.querySelectorAll('.a')].filter(el => el.matches('.a'));
This is what you're looking for I guess: :scope
EDIT:
Just like in this answer: https://stackoverflow.com/a/43354126/14034888
const parent = document.querySelector('.parent');
console.log(parent.querySelectorAll(':scope .box'));
should return (if it exists in the DOM of course) a NodeList of length 5 with .parent as the first element in the list and the children (and grand children) filling the remaining four indices...
<div class='parent box'>
<div class='box'></div>
<div class='box'>
<div class='inner box'></div>
</div>
<div class='box'></div>
</div>
Related
Let's say I have this piece of html:
<div>
<a class="target"/>
<div>
<a class="target"/>
<div>
<hr class="source"/>
</div>
</div>
</div>
I'd like to find the closest target from the source, meaning the one where I need to climb the fewest amount of parents. With a binding, I get the source element, that I'll note source. I want to find the second anchor, which is two levels deep, as it's closer to my source hr.
Here's what I have right now is, which works:
var target = source
.parentsUntil(".target").eq(0)
.find(".target")[0];
It seems rather uneffective though, because parentsUntil will test and return too many of the parents. I'd like it to stop on the first parent containing a .target element. Then I feel like calling find after makes jQuery look for target once more while it had already found it before with parentsUntil.
I can think of another solution that would involve iterating over source.parents() and calling find until I have a result but that would still search into branches that have already been explored.
Is there a function in jQuery or a custom algorithm I could leverage to get my result by exploring only the part of the tree that needs to be explored?
I'd suggest:
// starts at the element(s) with the class of
// 'source':
$('.source')
// finds the closest <div> element that contains
// an <a> element with the class-name of 'target':
.closest('div:has("a.target")')
// finds that contained <a> element with
// the class of 'target':
.find('a.target');
$('.source').closest('div:has("a.target")').find('a.target').addClass('found');
a::before {
content: attr(class);
}
.found {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<a class="target"></a>
<div>
<a class="target"></a>
<div>
<hr class="source" />
</div>
</div>
</div>
References:
addClass().
closest().
find().
:has() selector.
In your case you can use .parent() to select the parent div of .source element and use .prev() to get the previous element which is <a> in your case
$('.source').parent().prev()
or you can use
$('.source').parent().parent().find('a.target')
I have read this question and its answer, and wish to take it a little bit further.
I want to use CasperJS.click(selector) function to click multiple links matching a selector. Please note that the links do not have a significant href tag.
Consider the following markup:
HTML:
<div>
<h1 class='myLink'>Cocacola</h1>
<div>
<div>
<h1 class='myLink'>Sprite</h1>
</div>
</div>
</div>
The answers I've mentioned on top here suggest deleting the links so we can click the remaining elements with casper.exists and so on. What if I don't want to manipulate the page?
For reasons beyond my conception, using:
document.querySelector("div .myLink:nth-of-type(1)");
catches the first h1, Cocacola. But:
document.querySelector("div .myLink:nth-of-type(2)");
returns null.
Fiddle here.
Any ideas? Many thanks!
CSS spec for :nth-of-type says that:
The :nth-of-type(an+b) pseudo-class notation represents an element that has an+b-1 siblings with the same expanded element name before it in the document tree, for any zero or positive integer value of n, and has a parent element.
That is, the elements will have to be siblings.
For example,
<div>
<h1 class='myLink'>Cocacola</h1>
<h1 class='myLink'>Miranda</h1>
<div>
<div>
<h1 class='myLink'>Sprite</h1>
</div>
</div>
</div>
The selector div .myLink:nth-of-type(2) will select Miranda. That is, given n siblings of type 'div .myLink', the selector will select the second element from them.
Here is the fiddle for the above example.
Hope this helps!
As mentioned, the reason :nth-of-type(1) works but :nth-of-type(2) doesn't is because there is only exactly one h1 of each type as a child of its parent div. The class selector .myLink is a separate condition entirely and does not affect how :nth-of-type() works.
The reason your first statement appears to return the first element, even though there are technically two elements matching :nth-of-type(1), is because querySelector() returns only the first match.
To obtain the first and second elements matching your selector, use querySelectorAll() instead of querySelector(), and an indexer instead of the :nth-of-type() pseudo-class:
var cocacola = document.querySelectorAll("div .myLink")[0];
var sprite = document.querySelectorAll("div .myLink")[1];
Let's suppose to have the following html structure (1).
From $('.child') element I can access the $('.gran-parent') element making something like $('.child').parent().parent();.
Anyway I don't think this is a good way because is not generic.
Let's suppose there are other divs between $('.gran-parent') and $('.child').
What is the most generic way to refers to the first parent which class is gran-parent, starting from $('.child') ?
<div class='gran-parent'>
<div class='parent'>
<div class='child'>
</div>
</div>
</div>
You want:
$('.child').closest(".grand-parent");
.closest will keep traversing up until it finds a .grand-parent. You can also do .parents(".grand-parent") but that could return more than one result, depending on your DOM hierarchy, so you would have to do:
.parents(".grand-parent").eq(0)
or:
.parents(".grand-parent").slice(0)
or:
.parents(".grand-parent:first")
all of which are less elegant than .closest().
See:
http://api.jquery.com/closest/
http://api.jquery.com/parents/
You're looking for the .parents() operator.
Example:
$('.child').parents('.gran-parent');
Is there a way I can find the grand parent of a div and apply style to it?
<div class="wrapBoxes">
<div class="filters"></div>
<div class="wrapContainer"> <-- Need to apply style to this -->
<div class="leftNav"></div>
<div id="container">
<div class="box"></div> <-- From here -->
</div>
</div>
</div>
Something with this logic?
$(".box").find(grandParent).applyWhateverCss to GrandParent
use parent twice:
$(".box").parent().parent().css('color', 'blue');
parent docs:
Description: Get the parent of each element in the current set of matched elements, optionally filtered by a selector.
You can use the closest as well.
$(".box").closest('.wrapContainer').css('color', 'blue');
closest docs:
Description: Get the first element that matches the selector, beginning at the current element and progressing up through the DOM tree.
If you are sure it will always be the grand parent, use parent().parent() otherwise use closest
as a performance u can also use .closest(selector[,context]) i.e
$('.box').closest('.wrapContainer','.wrapBoxes').css('color','yellow');
In this way u can limit the DOM traversal to the context of div.wrapBoxes only
$(".box").parent().parent().css('color','red'); should do it.
Alternatively if the class of "wrapContainer" is always there:
$(".box").parents('.wrapContainer').css('color','red');
I have following HTML:
<div id="123" class="test">
<div class="testMessage">Foo</div>
<div><div class="testDate">2010</div></div>
<div id="127" class="test">
<div class="testMessage">Bar</div>
<div><div class="testDate">2011</div></div>
</div>
</div>
And I have following JS/jQuery code:
$(".test").find(".testDate").val("cool 2010");
How to change JS/jQuery to find "testDate" class element except in children "test" class block without using children?
P.S. I know only about class name and I don't know how many divs can be nested.
Update
Its probably the weirdest selector I've ever written:
$("div.test").not(':has(> .test)').siblings().find('.testDate').text('cool 2010');
Demo: http://jsfiddle.net/mrchief/6cbdu/3/
Explanation:
$("div.test") // finds both the test divs
.not(':has(> .test)') // finds the inner test div
.siblings() // get all other divs except the inner test div
Try this and also div elements do not have a value property, use html() method to set the inner html or text()
$("div.test :not(.test)").find(".testDate").html("cool 2010");
If you can modify your main div id to "_123", you can straight away use the id selector like this
$("#_123 > div.testDate").html("cool 2010");
I think the not() selector might help. You can learn more about it here: http://jsperf.com/jquery-css3-not-vs-not
Anytime you try to select $('.test'), it will grab all elements with a class='test'. You need to start at the outermost body tag:
$('body').children('.test').children(':not(.test)').find('.testDate').text('cool 2010');