My HTML code looks something like
<div id="partA">
<div class="myClass typeA"> blabla </div>
<div class="myClass typeA"> blabla </div>
<div class="myClass typeA"> blabla </div>
<div class="myClass typeB"> blabla </div>
</div>
<div id="partB">
<div class="myClass typeA"> blabla </div>
<div class="myClass typeA"> blabla </div>
<div class="myClass typeA"> blabla </div>
<div class="myClass typeB"> blabla </div>
</div>
I want to use javascript to count the number of elements of class myClass, but only the one that are within #partA.
When I use
$(".myClass").size()
I get 8 as result (it counts all the elements from both partA and partB).
When I use
$(".myClass.typeA").size()
I get 6 (it gets all myClass and typeA elements, from both parts)
But when I use
$("#partA.myClass").size()
I get 0.
Apparently, that javascript command only looks for elements that have both id=partA and class=myClass.
Is it possible to reformulate that command in order to count the number of myClass class that are contained within the elements with id=partA?
Thanks a lot!
You're missing a space in one of your selectors. Try:
$("#partA .myClass").size()
Alternatively you could do:
$('#partA').find('.myClass').length;
Or
var partA = $('#partA');
$('.myClass', partA).length;
Related
this is the object I'm trying to select: $x('//div[contains(#class,"react-select__value-container")]')
** There are 10 of these **
this is the grandparent object: $x('//div[#class="chart-option"]/label[.="Layer"]/..') ** There is only one of these **
the parent is a simple //div[contains(#class, "react-select")]
So the code looks like this:
<div class="chart-option">
<label>Layer</label>
<div class="react-select css-2b097c-container">
<div class="react-select__value-container css-1hwfws3">
So I need the "value-container" who's grandparent has the child /label[.="Layer"]
But I can't for the life of me get the ordering right and relative syntax to get it. Is there a good tutorial for this? Any help is appreciated.
Try this xpath:
//div[#class="chart-option"][label="Layer"]/div[div[contains(#class,"react-select__value-container")]]
Explanation
//div[#class="chart-option"][label="Layer"]
Looking anywhere in the document, select div tags such that (1) the class is chart-option and (2) there is a child tag called label with the value Layer.
/div[div[contains(#class,"react-select__value-container")]]
Looking at each node in the previous result set above, select all child div tags such that that child div tag itself has a div tag that matches the class pattern you have given. (In other words, match based on the grandchild's class, but ultimately select the child div tag.)
Test Cases
Here are some more test cases that I used. You can test using an online xpath testing tool.
<div>
<div class="chart-option">
<label>nope</label>
<div class="react-select css-WRONG-container">
<div class="react-select__value-container css-WRONG">
</div>
</div>
</div>
<div class="chart-option">
<label>Layer</label>
<div class="react-select css-CORRECT-container">
<div class="react-select__value-container css-CORRECT">
</div>
</div>
</div>
<div class="chart-option">
<label>Not Layer</label>
<div class="react-select css-WRONG-container">
<div class="react-select__value-container css-WRONG">
</div>
</div>
</div>
<label>Layer</label>
<div class="react-select css-WRONG-container">
<div class="react-select__value-container css-WRONG">
</div>
</div>
<div class="chart-option">
<label>Layer</label>
<div class="WRONG-AGAIN">
<div class="WRONG-AGAIN">
</div>
</div>
</div>
</div>
In my below HTML markup, I'd like to query the <div> that has a data-parent set to "true", and the contained child has data-child-gender set to "true" and inner html is "male".
<div id="grandparent">
<div id="parent1" data-parent="true">
<div id="child1" data-child-gender="false">
male
</div>
</div>
<div id="parent2" data-parent="true">
<div id="child2" data-child-gender="true">
female
</div>
</div>
<div id="parent3" data-parent="false">
<div id="child3" data-child-gender="true">
female
</div>
</div>
<div id="parent4" data-parent="true">
<div id="child4" data-child-gender="true">
male
</div>
</div>
</div>
Given the above scenario, the expected <div> is parent4.
What is the JavaScript querySelector to use?
First use querySelectorAll which will give an array. Then iterate over it and check and get element with required data attribute.
After that you can use use a if & check the content inside it
let k = document.querySelectorAll('[ data-parent=true]').forEach(function(item) {
let elem = item.querySelector('[data-child-gender=true]');
if (elem !== null && elem.innerHTML.trim() === 'male') {
console.log(item.id)
}
})
<div id="grandparent">
<div id="parent1" data-parent="true">
<div id="child1" data-child-gender="false">
male
</div>
</div>
<div id="parent2" data-parent="true">
<div id="child2" data-child-gender="true">
female
</div>
</div>
<div id="parent3" data-parent="false">
<div id="child3" data-child-gender="true">
female
</div>
</div>
<div id="parent4" data-parent="true">
<div id="child4" data-child-gender="true">
male
</div>
</div>
</div>
There isn't one querySelector you can use for this (as you can't use it to select specific text within elements). However, you can use .querySelector() with .filter() to get more specific results:
const true_children = [...document.querySelectorAll("[data-parent='true'] [data-child-gender='true']")];
const res = true_children.filter(({innerHTML:g}) => g.trim() === "male");
console.log(res);
<div id="grandparent">
<div id="parent1" data-parent="true">
<div id="child1" data-child-gender="false">
male
</div>
</div>
<div id="parent2" data-parent="true">
<div id="child2" data-child-gender="true">
female
</div>
</div>
<div id="parent3" data-parent="false">
<div id="child3" data-child-gender="true">
female
</div>
</div>
<div id="parent4" data-parent="true">
<div id="child4" data-child-gender="true">
male
</div>
</div>
</div>
The problem that the question describes, cannot be solved using query-selectors alone. This is because of following reasons:
The query selectors always works on descendants, so while evaluating that the child div has data-child-gender="true", there will be no way to return the parent element. The query-selector will return the child div.
There is no way to evaluate the inner text or contained text of an element in query-selector.
These two limitations can be worked around by using JavaScript, provided that you were going to use the query-selector in JS.
Something like the following snippet should work.
document.querySelectorAll('div[data-parent=true] div[data-child-gender=true]')
.filter(function(elem) {
return elem.innerText === 'male'; // filter the elements containing male string.
})[0].parentElement; // return the parent of matched element.
An equivalent logic could be derived for selenium too. Otherwise if this much logic is unacceptable, you can always use the much richer xpath selectors. xpath wouldn't have either of the limitations mentioned above.
In my DOM I have these elements:
<div class="myclass yourclass"></div>
<div class="myclass"></div>
<div class="myclass"></div>
<div class="myclass yourclass"></div>
<div class="myclass"></div>
<div class="myclass yourclass"></div>
I need to get all div of myclass but NOT of yourclass ( so in the case above I need to get 3 elements ).
I tryed this but doesn't work:
document.querySelectorAll('.myclass:not([.yourclass])')
You don't need [] in querySelectorAll, it is invalid syntax.
You can use any CSS selector as it is in querySelectorAll. See the demo below.(colored by using CSS, see console for javascript result)
var myClassElements = document.querySelectorAll('.myclass:not(.yourclass)');
console.log(myClassElements);
div {
color: red;
}
.myclass:not(.yourclass) {
color: green;
}
<div class="myclass yourclass">a</div>
<div class="myclass">b</div>
<div class="myclass">c</div>
<div class="myclass yourclass">d</div>
<div class="myclass">e</div>
<div class="myclass yourclass">f</div>
:not()
The content of the divs is going to be populated with javascript json. Now, I know how to select a div in javascript:
var hsc = document.getElementByID("hsc");
But how would I refer to eg. the title but only in the hsc div.
<div id="hsc">
<div id="title"></div>
<div id="jobs"></div>
...
</div>
<div id="cc">
<div id="title"></div
<div id="jobs"></div>
</div>
On a separate note, wouldn't 'title' and 'jobs' be better classified as classes, and not ids?
This would work:
var hsc = document.querySelectorAll("#hsc > .title");
But you need to change to valid html and use unique IDs and classes instead:
<div id="hsc">
<div class="title"></div>
<div class="jobs"></div>
...
</div>
<div id="cc">
<div class="title"></div>
<div class="jobs"></div>
</div>
IDs must be unique in HTML.
Change them to classes, and then you can use querySelector() to target them:
document.querySelector('.hsc .title').style.color= 'blue';
document.querySelector('.cc .title').style.color= 'red';
<div class="hsc">
<div class="title">Make me blue!</div>
<div class="jobs">Jobs</div>
</div>
<div class="cc">
<div class="title">Make me red!</div>
<div class="jobs">More jobs</div>
</div>
Just try
<div id="hsc">
<div id="a" class="title"></div>
<div id="b" class="jobs"></div>
...
</div>
<div id="cc">
<div id="c" class="title"></div
<div id="d"class="jobs"></div>
</div>
Because your HTML code is invalid because the id is already taken.
Let's say I have the following.
<div class="foo">
<div>
some text
<div class="bar">
</div>
</div>
</div>
<div class="foo">
<div>
some text
<div class="bar">
some text
</div>
</div>
</div>
I want return all the divs of class "foo" that have "some text" inside the div class "bar." So the second would be returned, but not the second. How can I do that?
Try this
$("div.bar:contains('some text')").parents(".foo")
This will do it
$('.foo:has(.bar:not(:empty))')
Make sure there are no characters inside the .bar, even spaces or newlines.
http://jsfiddle.net/Nk4FB/