jQuery select child of closest element - javascript

Basically I want to be able to select the div level2 parent from the child level4 div. My application does not has such classes, otherwise I'd just select level2 :)
<div class="level1">
<div class="level2">
<div class="level3">
<div class="level4"></div>
</div>
</div>
<div class="level2"> <!-- this is hidden -->
<div class="level3">
<div id="start" class="level4"></div>
</div>
</div>
</div>
I start with $('#start') and search for the first parent which is visible, but I'm not seeing a way to return the child of that parent. Searching for $('#start') inside the parent seems very wasteful as I start with a sub child to begin with.
$('#start').closest(':visible') // returns level1
$('#start').closest(':visible').first() // returns the first level2. I can't just use second because the number of level2s can change.
$('#start').closest(':visible').children().each(function(){ /* do some search to check it contains `$('#start')` }) // seems very wasteful.
Another way to look at what I'm trying to say would be; start in the middle, find the outside (the visible element), and move one element in.

How about this:-
$('#start').parentsUntil(':visible').last();
This will give you all hidden parent div's until its visible parent and last() wil give the outermost parent which is hidden. last is not a selector on position it is the last() in the collection.

You want the .has() method
Description: Reduce the set of matched elements to those that have a descendant that matches the selector or DOM element.
$('#start').closest(':visible').children().has('#start');
See fiddle for example.

You say that the classes don't exist...why not add them? It would make thinks much easier to find. The class names don't need to have actual styles associated.
var allLevel4 = $('#start').closest(':visible').find('.level4');
var firstLevel4 = $('#start').closest(':visible').find('.level4')[0];
var secondLevel4 = $('#start').closest(':visible').find('.level4')[1]; //also, #start

Use .filter():
$('#start').closest(':visible').children().filter(':first-child')
.find() is also good for selecting pretty much anything.

Related

Puppeteer - get parent element

I'm trying to click on one value (odds) based on the name of the other element but those two need to be inside a specific parent element which I get by the text inside it.
The snippet below can be found multiple times on the same page with the same classes so targeting by class is not an option.
I first need to get a container with text "1st Goal. Then I need to get it's parent and in the parent, I need to get the second div element (class parent2). That element holds other elements. Let's imagine I need to get the element of value 200 and click on it.
I've tried using parentElement, parentNode but always get the 'undefiend' when getting a parent of the child element, although the child element is retrieved successfully. I just can't get the parent from where I could go down the tree to the desired element and click on it.
<div class="group ">
<div class="parent1 "><span>1st Goal</span></div>
<div class="parent2">
<div class="container ">
<div">
<div><span>Malaga</span><span class="odds">200</span></div>
<div><span>No 1st Goal</span><span class="odds">300</span></div>
<div><span>Las Palmas</span><span class="gll-odds">400</span></div>
</div>
</div>
</div>
<div></div>
</div>
XPath expressions
If you are okay with using XPath expression, you can use the following statement:
//div[contains(#class, "group") and contains(., "1st Goal")]/div[#class="parent2"]//span[#class="odds"]
This XPath expression queries for a div element having the class group and containing the text 1st Goal somewhere. Then it will query the children div with the class parent2 and query span elements with class odds inside.
Usage within puppeteer
To get the element with puppeteer, use the page.$x function. To click the element, use elementHandle.click.
Putting all together, the code looks like this:
const [targetElement] = await page.$x('//div[contains(#class, "group") and contains(., "1st Goal")]/div[#class="parent2"]//span[#class="odds"]');
await targetElement.click();
const parent_node = await child_node.getProperty('parentNode')
You can try this one

Get Parent of DOM Element Using JavaScript

I’d like to check whether a DOM element is a child of a specific DIV class regardless of the number of DIV/HTML between the element and the parent DIV. I need to use JavaScript (not jQuery). So if I had some HTML like this:
<div class="header grid-12">
<!-- many levels of divs/html -->
<div class="section">
<span id="id1">hello</span>
</div>
</div>
<div class="footer">
<!-- many levels of divs/html -->
<span id="id2">goodbye</span>
</div>
I'd want to do something like this (logically that is):
var domID = document.getElementById("id1");
if (domID a child of 'header grid-12') {
console.log('header grid-12 found');
}
I looked at parentNode children which would allow you to get all of the child nodes but I need to loop in reverse (parentnode parent if you will). I'm thinking it's much faster to start at the child and go up as opposed starting at "header grid-12" and looping through hundreds/thousands of nodes.
Thanks
The Element.closest() method returns the closest ancestor of the current element (or the current element itself) which matches the selectors given in parameter. If there isn't such an ancestor, it returns null.
source
try this,
let parent = !!document.getElementById('id1').closest('.header.grid-12');
if(parent)
{
console.log('parent found');
}
domElement.closest('selector') goes in reverse and return the nearest matching parent element. This will save you from iteratiing through all domChildElements.

How to select a DIV if its child has any children?

I'm trying to select any divs on a page if a certain child of theirs has any children of its own.
Here's how the structure looks:
<div id="ID-SOME_LONG_ID">
<div class="GK">
<div id="SOME_LONGID_#1434646398866197"></div>
</div>
</div>
So I want to select all divs with id ID-SOME_LONG_ID only if the GK DIV has any children. It may or may not.
ID- stays the same and SOME_LONG_ID changes with each one.
The other one SOME_LONG_ID is the same on as the parent, and after the # it's a 16 digit number that is random.
Would using Regex be a good idea to look for them or maybe using jQuery's .children() like $( ".GK" ).children()?
Thank you!
Use :has(), :empty, and :not()
$('#ID-SOME_LONG_ID:has(.GK:not(:empty))')
However, note, :empty will fail if you want real children without text nodes. In that case you can do
$('.GK').filter(function() {
return $(this).children().length > 0;
});

get index out of selected elements

So I have a div with some child elements and when I select one with jQuery I want to get the index of it within a selector
<div>
<div class="red"></div>
<div class="red"></div>
<div class="red"></div>
<div class="blue"></div>
<div class="red"></div>
<div class="blue"></div>
<div class="blue"></div>
<div class="red"></div>
</div>
So lets say that I have the last element in the main div selected. If I call index() on it it will give me '7' because out of all the child elements the index is '7'. But now lets say I want to get the index based on the other 'red' elements, the goal is to return a value of '4' because out of all of the 'red' elements it is the fifth one. I looked through the documentation and didnt find a whole lot, then I experimented with putting selectors in the index() method like index('.red') but I couldn't get anything working.
Well, the documentation says:
.index( element )
element The DOM element or first element within the jQuery object to look for.
So can do:
selectedElements.filter('.red').index(this);
If you don't have selectedElements already, you can select corresponding siblings with, for example:
$(this).parent().children('.red')
If every element has only one class and then the filter can be dynamic:
var index = $(this).parent().children('.' + this.className).index(this);
Use the .index() function documented here
For the above if one wants to get the index of a element of the red class use $('div .red').index(elem);
$('div .red) will create a list of the elements with the red class within the div. .index(elem) will search for the elem within the array.
Running through all of them using id=test as parent
DEMO : http://jsfiddle.net/T7fXR/
$('#test > div').each(function(){
var thisClass=$(this).attr('class');
$(this).css('background',thisClass );
/* get index based on class*/
var idx=$('.'+thisClass).index(this);
$(this).text('Index= '+idx)
})
For me, this works just fine with your given HTML:
$('div').eq(5)​​​​​​​​​​.index('.red') // 3
You can place selectors into the .index() function.

find index of child using jQuery?

If I have an html structure like:
<div id="parent">
<div class="child first">
<div class="sub-child"></div>
</div>
<div class="child second">
<div class="sub-child"></div>
</div>
<div class="child third">
<div class="sub-child"></div>
</div>
</div>
and I have a click handler defined through ($('#parent.child')).click() and then I click on the div with the class of second (first, second, third classes have simply been added to make demo clearer) is there a simple way to get the number 1 as it is the second child? (0 based index)?
Something like $(this).index
Just have a look at the jQuery API. The method you suggest, index, is exactly right:
$('#parent .child').click(function() {
var index = $(this).index();
});
From the docs:
If no argument is passed to the .index() method, the return value is
an integer indicating the position of the first element within the
jQuery object relative to its sibling elements.
Also note that I've changed the selector slightly from your example. I'm guessing that was just a typo in your question though. #parent.child will look for an element with ID "parent" and a class of "child", but you actually want #parent .child (note the space) to find elements with class "child" that are descendants of an element with ID "parent".
The index() method can be used for getting the position of an element inside a collection. In basic circumstances, $(this).index() should work.
But with more specific collections, you can get the position with collection.index(item). Imagine adding something simple into your #parent that should not be counted when measuring index() (a span, img, anything). With the simple method, your code is likely to break, but with the specific method, it won't.
Something like this should work for you:
var $children = $('#parent .child').click(function​ () {
console.log($children.index(this));
});​
jsFiddle Demo

Categories