How to get HTML elements by their inner text using queryselectors? - javascript

I need to get all the HTML divs that contains many HTML elements which has the innerText = ' * ' and store it in an array, How can I achieve that using typescript?. If I find a span containing the innerText= ' * ', I need to put the div inside an array. Here, in my code, there are 2 divs contains span elements with innerText= ' * ' and I need to put only that 2 divs inside an array. I don't need the 3rd div in the array, because it does not contains any HTML elements with innerText="*".
<div class="div">
<label>
<span> Subject </span>
<span> * </span>
</label>
</div>
<br>
<div class="div">
<label> Yes/No </label>
<span> * </span>
</div>
<br>
<div class="div">
<label> Email Id </label>
<span> hello </span>
</div>

There is currently no standard API to get elements by their content, so you would have to loop over them manually:
const myElements = Array.from(document.querySelectorAll('*'))
.filter(() => this.children.length === 0 && this.textContent === ' * ');
The '*' passed here to querySelectorAll is not related to the text you are looking for, it's just the universal selector to select all elements on the page. As this might be expensive, you'd better use some other selector to limit the scope.

Related

JQuery select all where arbitrary parent has class X

I'm trying to figure out a jquery selector where I can grab all DOM elements with name A, that ALSO have a grandparent with class X. Here's an example HTML, I will have many of these
<div class="interface_controlgroup">
<div class="form-switch me-3">
<input name="layout[]" type="checkbox" class="form-check-input">
</div>
</div>
<!-- note some inputs will have "d-none" on the grandparent -->
<div class="interface_controlgroup d-none">
<div class="form-switch me-3">
<input name="layout[]" type="checkbox" class="form-check-input">
</div>
</div>
...
<!-- repeated -->
Now I would like to select all inputs, as well as all inputs where the grandparent has d-none
let all_inputs = $('input[name=layout\\[\\]]');
//cannot use this because the entire section may be hidden when this is run
let hidden_inputs = $('input[name=layout\\[\\]]:hidden');
//I need something more like
let hidden_inputs = $('input[name=ide_layout_std\\[\\]]'.parent().parent()".d-none");
I am looking for a solution that allows me to only select when the parent's parent has a certain class, but I don't know how to create this match. I also can't rely on ":hidden" in the jquery selector because the entire section/page may be hidden when this javascript is running.
Using JQuery 3.6 and Bootstrap 5
You can use the x > y child selector to solve this. x > * > z matches z with a grandparent x (the parent in the middle can be anything).
let hidden_inputs = $('.d-none > * > input[name=ide_layout_std\\[\\]]:hidden');

Get div value from class name

I have a very large HTML that contains lots of divs with the same name, I want a way to only filter or extract that value from that div.
Here is an example:
<td class="last">
<div class="container-relative">
<div class="name" title=""User" <John Appleseed>"></div>
<div class="date">9/17/2019</div>
<div class="tool"></div>
</div>
</td>
I need to extract only what's between <John Appleseed>, in this case is 'John Appleseed'.
You could use querySelectorAll to take all the elements with class name, then get the title attribute with getAttribute, and finally use a regular expression to match text between <>.
document.querySelectorAll('.name').forEach(item => {
let title = item.getAttribute('title');
console.log(title.match(/\<.*\>/));
});
<td class="last">
<div class="container-relative">
<div class="name" title=""User" <John Appleseed>"></div>
<div class="date">9/17/2019</div>
<div class="tool"></div>
</div>
</td>
var divs=[];
for(i=0,j=0,obj=document.getElementsByClassName("name");i<obj.length;i++)
if(obj[i].title.includes("John Appleseed") &&
/* obj[i].title.split("\"")[2].trim()=="<John Appleseed>" && */
obj[i].tagName.toLowerCase()=="div"){
divs[j++]=obj[i];
}
console.log(divs);
separate your div using div ID. Then get your respective div using that value of ID. Then in javascript you can use getElementByID.
You can use Xpath,
.//div[contains(#class, 'Test')]
Then extract you required text from it.

Getting text content of a div element excluding its children

I have the following HTML code and I need to console.log only Shipping.
I tried a few methods but can't seem to get it to work.
I tried selecting first its children and printing out the textContent of its parent - no go. I could delete its children and print out what's left but I can't do that.
Any suggestions?
<div class="accordion shadowed-box shipping collapsed summary">
<fieldset>
<legend>
Shipping
<div id="shippingTooltip" class="form-field-tooltip cvnship-tip" role="tooltip">
<span class="tooltip">
<div class="tooltip-content" data-layout="small tooltip-cvn">
<div id="cart-checkout-shipping-tooltip" class="html-slot-container">
<p>We ship UPS, FedEx and/or USPS Priority Mail.<br>
<a class="dialogify" data-dlg-options="{"height":200}" href="https://www.payless.com/customer-service/ordering-and-shipping/cs-ordering-shipping-schedule.html" title="shipping information">Learn more about our shipping methods and prices.</a>
</p>
</div>
</div>
</span>
</div>
Edit
</legend>
</fieldset>
</div>
I tried this:
var accordionChildren = document.querySelector('.accordion.shadowed-box.shipping>fieldset>legend *');//selects the first child
var accordionTitle = accordionChildren.parentElement;
var text = accordionTitle.textContent;
console.log(text);
I want to get Shipping but instead I get still all the text contents of the legend element.
you can access Text nodes by iterating over the child nodes (or access the intended node directly) of the accordionTitle variable.
let textNode = accordionTitle.childNodes[0],
text = textNode.textContent;
console.log(text);
See https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes and https://developer.mozilla.org/en-US/docs/Web/API/Text
You just need to find the TextNode child from all of the elements children, you do this by iterating over all of the childNodes and when the node type matches TextNode, return its textContext.
For a jQuery based solution on how to pick the TextNode child of an element see this question - but my example shows how to do it in vanilla ES (with a for loop over childNodes):
Object.defineProperty(HTMLElement.prototype, 'onlyTextContent', {
enumerable: false,
configurable: false,
get: function() {
for(let i = 0; i < this.childNodes.length; i++) {
if(this.childNodes[i].nodeType === Node.TEXT_NODE) {
return this.childNodes[i].textContent.trim();
}
}
return null;
}
});
document.addEventListener('DOMContentLoaded', function() {
console.log(
document.getElementById('legend1').onlyTextContent
);
});
<div class="accordion shadowed-box shipping collapsed summary">
<fieldset>
<legend id="legend1">
Shipping
<div id="shippingTooltip" class="form-field-tooltip cvnship-tip" role="tooltip">
<span class="tooltip">
<div class="tooltip-content" data-layout="small tooltip-cvn">
<div id="cart-checkout-shipping-tooltip" class="html-slot-container">
<p>We ship UPS, FedEx and/or USPS Priority Mail.<br>
<a class="dialogify" data-dlg-options="{"height":200}" href="https://www.payless.com/customer-service/ordering-and-shipping/cs-ordering-shipping-schedule.html" title="shipping information">Learn more about our shipping methods and prices.</a>
</p>
</div>
</div>
</span>
</div>
Edit
</legend>
</fieldset>
</div>
You can get the contents of the <legend> tag as a string and then use a regular expression to remove the HTML tags and their content inside. Like this:
let legends = document.querySelector('.accordion.shadowed-box.shipping>fieldset>legend');
let title = legends.innerHTML.replace(/<.*/s, '');
// title = "Shipping"
The regular expression matches the first < character and everything that follows. So we replace that match with an empty string ''.

Mass replace of elements [duplicate]

This question already has answers here:
Recursively change element type with jQuery, why it's partially working?
(2 answers)
Closed 7 years ago.
I'm trying to replace all the child elements in a certain element to DIVs.
I have the following structure:
<div id="wrapper">
<span>
<span>
<span>
<span></span>
<span></span>
</span>
</span>
</span>
</div>
I've tried replaceElements($('#wrapper')):
function replaceElements($element){
var children = $element.find("*");
var current;
for(var i=0; i<children.length; i++){
current = $(children[i]);
current.replaceWith("<div>" + current.html() + "</div>");
}
}
However this doesn't work because when it tries to change the N+1 element it all ready doesn't exist because it was replaced when doing the Nth element. N+1 is a descendant of N and thus is being changed when changing the .html() of N. Preserving element attributes is not an issue here.
How can I change all the child SPANs into DIVs, please?
You should not use the html content in the replaced element, instead need to add the dom elements to it
function replaceElements($element) {
$element.find("*").replaceWith(function() {
return $('<div></div>', {
html: this.childNodes
});
})
}
replaceElements($('#wrapper'))
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="wrapper">
<span>1
<span>2
<span>3
<span>4</span>
<span>5</span>
</span>
</span>
</span>
</div>
Note: No attributes of the elements will be copied

Change html element nested inside a random html element with jquery

I have a JQuery function that randomly chooses a DIV in a page full of DIVs. I'm trying to modify the function so that it checks the length of the H3 tag nested in the random DIV. If the string inside the H3 tag is over 10 characters long (including whitespace), the function should truncate the string and replace the contents of the H3 with this new shorter string and display it.
Example:
(jquery)
if ($('#main').length !== 0) {
var new_item = $('#main div').eq(Math.floor(Math.random() * $('#main div').length));
new_item.css('display','block');
}
(html file)
<div id="main">
<div id="m1" style="display:none;">
<h3>Apples are red</h3>
</div>
<div id="m2" style="display:none;">
<h3>Oranges are orange</h3>
</div>
<div id="m3" style="display:none;">
<h3>Bananas are yellow</h3>
</div>
</div>
(desired output - what user sees if DIV#m2 is randomly selected)
Oranges ar
$(new_item).find('h3').text($(new_item).find('h3').text().substr(0,10));
You already have the code that gets the random div element. The part you want to add is fairly trivial:
var h3_item = new_item.children("h3");
h3_item.html(h3_item.html().substring(0, 10));

Categories