How to read text "LE 88" from the following HTML using Javascript. the text LE is not constant, it keeps on changing. It neither contains ID's, nor class names.
<body>
<div id="Record">
<div>
<div>Grade A </div>
</div>
<div>19-04-2022
</div>
<div>
<div>Subject H1
</div>
<div>
<div>LE 88
</div>
</div>
</div>
<div>
</div>
</div>
</body>
You can iterate the dom div and check for the children. In this case the div with text does not have any child. So use children and check for the textContent. If the matching text is found do the required operation
document.querySelectorAll('div').forEach((curr) => {
const child = curr.children;
if (child.length === 0 && curr.textContent.trim() === 'Marks 88') {
curr.textContent = 'Marks 88 changed'
}
})
<div>
<div>
<div>Grade A </div>
</div>
<div>19-04-2022</div>
<div>
<div>Subject H1</div>
<div>
<div>Marks 88</div>
</div>
</div>
<div>
</div>
</div>
Related
Can I access the last div with the + content only with css & child combinators? I would like to style it.
<body>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
+
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
with :last child i can't reach so deep into the tree.
The selector div:(not(:has(div)) will match any DIV that doesn't have another DIV nested inside it.
:has(selector) matches an element whose contents include an element that matches selector. Putting this in :not() reverses the condition.
This is a relatively new CSS selector, and it's not yet supported by Firefox as of version 108. See the compatibility table.
div:not(:has(div)) {
color: red;
}
<body>
a
<div>
b
<div>
c
<div>
d
<div>
e
<div>
f
<div>
g
<div>
h
<div>
i
<div>
j
<div>
+
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
i want to click element within div whose name is "name1", description is "description1"
and title is "title1" using cypress.
below is the dom,
<div data-testid="table-body" role="rowgroup">
<div role="row" data-testid="table-row-0">
<div role="cell">
<input data-testid="table-row-checkbox"/>
</div>
<div data-testid="table-cell-row-0-column-name">
<button data-testid="expand-row"></button>
<a class="subtle-link">name1</a>
</div>
<div data-testid="table-cell-row-0-column-description">
description1
</div>
<div data-testid="table-cell-row-0-column-isIcon">
<div>
<svg>
<title>title2</title>
</svg>
</div>
</div>
</div>
<div role="row" data-testid="table-row-1">
<div role="cell">
<input data-testid="table-row-1-checkbox"/>
</div>
<div data-testid="table-cell-row-1-column-name">
<button data-testid="expand-row"></button>
<a class="subtle-link">name1</a> //i want to click this element
</div>
<div data-testid="table-cell-row-column-description">
description1
</div>
<div data-testid="table-cell-row-column-isIcon">
<div>
<svg>
<title>title1</title>
</svg>
</div>
</div>
</div>
<div role="row" data-testid="table-row-2">
<div role="cell">
<input data-testid="table-row-checkbox"/>
</div>
<div data-testid="table-cell-row-2-column-name">
<button data-testid="expand-row"></button>
<a class="subtle-link">name2</a>
</div>
<div data-testid="table-cell-row-1-column-description">
description2
</div>
<div data-testid="table-cell-row-0-column-isIcon">
<div>
<svg>
<title>title1</title>
</svg>
</div>
</div>
</div>
</div>
As seen from above dom there is two divs with name name1 and description description1. but title is "title1", "title2"
i have tried like below,
cy.get('div[role="row"]')
.find('div', 'name1')
.contains('svg', 'title1')
.parent()
.click();
this selects the first element with name1 although title is title2
This is quite tricky, the simplest way I found is to use a filter with callback.
The row parameter is the raw element (not jQuery wrapped), so use .textContent() to get the text of the node and its descendants - MDN - textContent().
cy.get('div[role="row"]') // 3 elements found
.filter((_, row) => {
return row.textContent.includes('title1') &&
row.textContent.includes('description1') &&
row.textContent.includes('name1') // filters to 1 element
})
.find('a')
.click()
You can also use a selector with the filters built in
const selector = 'div[role="row"]' +
':contains("title1")' +
':contains("description1")' +
':contains("name1")';
cy.get(selector)
.find('a')
.click();
Text search within the row may be a bit imprecise, depending on if the text you are looking for appears in other columns.
A more precise filter would target the elements of each text (using jQuery here),
cy.get('div[role="row"]')
.filter((_, row) => {
const title = Cypress.$(row).find('title').text();
const description = Cypress.$(row).find('div[data-testid="table-cell-row-column-description"]').text();
const name = Cypress.$(row).find('a.subtle-link').text();
return title === 'title1' &&
description === 'description1' &&
name === 'name1';
})
.find('a')
.click()
I would like to find all elements which contains title on page and add new attribute to all of them.
Example:
<div title='something 1'></div>
<p>Test<div title='something 2'></div></p>
<div>
<div>
<div>
<div title='something 3'></div>
</div>
</div>
</div>
How it should look like after page load:
<div title='something 1' rel='tooltip'></div>
<p>Test<div title='something 2' rel='tooltip'></div></p>
<div>
<div>
<div>
<div title='something 3' rel='tooltip'></div>
</div>
</div>
</div>
Previously I did it manually which is bad solution for me
$('#collection_map > div > div > button').attr('rel', 'tooltip');
Try this code:-
$('div[title]').each(function() {
$(this).attr('rel', 'tooltip');
});
You don't even need jQuery for this. Here is a working example in plain JavaScript.
var elems = document.querySelectorAll('[title]')
elems.forEach(elem => elem.setAttribute('rel', 'tooltip'))
<div title='something 1'></div>
<p>Test<div title='something 2'></div></p>
<div>
<div>
<div>
<div title='something 3'></div>
</div>
</div>
</div>
Get all elements which have attribute title and then loop over it to add new attribute rel to each object.
paragraph tag cannot have block elements like div nested in it. See - https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p
Paragraphs are block-level elements, and notably will automatically
close if another block-level element is parsed before the closing </p>
tag.
$('[title]').attr('rel', 'tooltip');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div title='something 1'></div>
<p>Test
<div title='something 2'></div>
</p>
<div>
<div>
<div>
<div title='something 3'></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.
I have an element is called divElement:
<div ....>
</div>
and I have p element is called pElement:
<p ....>
</p>
I did:
divElement.appendChild(pElement);
and I got new element:
<div ....>
<p ....>
</p>
</div>
now I want to add this unicode text (▽) after the p element in order to get:
<div ....>
<p ....>
</p>
▽
</div>
I tried:
divElement.innerHTML = "▽";
but I got:
<div ....>
▽
<p ....>
</p>
</div>
any help appreciated!
You could do this:
divElement.appendChild(document.createTextNode("▽"))
Or, if you don't want to include the literal character:
var charDiv = document.createElement('div')
charDiv.innerHTML = "▽"
document.body.appendChild(charDiv)
Simply concatenate the sign with the innerHTML of the div.
HTML :
<div id="divElement">
<p id="pElement">
Hello
</p>
</div>
javaScript :
var element = document.getElementById("divElement");
element.innerHTML += "▽";
Demo