jQuery .Text() function is replacing HTML within element - javascript

I am trying to replace text within an element on the fly, however .text() function is replacing both text and HTML. Any thoughts on how I only edit the actual text?
<div>
<h3 class="titleHeading">My Title <a ng-click="openTooltip('getMoreInfo')"><span class="toolTip"></span></a>
<div>
I want to change the words "My Title" to "My New Title", however whenever I use .text() function, it replaces all of my html and my anchor tag disappears.
Here is my jQuery:
$('h3.titleHeading').text("My New Title")
My output is then - again, the code removes my anchor tag which I need for a tooltip.
<div>
<h3 class="titleHeading">My New Title
<div>

When developing HTML, if you have an element with child HTML elements, it is a bad idea to have it contain plain-text as well. This causes problems like what you see here.
An easy solution is to put your text inside a span. (Note: Don't forget to close your h3.)
<div>
<h3 class="titleHeading">
<span id="titleHeadingText">My Title</span>
<a ng-click="openTooltip('getMoreInfo')">
<span class="toolTip"></span>
</a>
</h3>
<div>
You can change the elements of the text easily, now, without affecting the other elements.
$("#titleHeadingText").text("My New Title");

If you do not have access to the code, loop through only the text nodes and replace their textContent with your new content. This will keep the other existing HTML intact.
Taken from this answer.
$('h3.titleHeading').contents().filter(function() {
return this.nodeType == 3
}).each(function(){
this.textContent = this.textContent.replace('My Title','My New Title');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<h3 class="titleHeading">My Title <a ng-click="openTooltip('getMoreInfo')"><span class="toolTip"></span></a>
<div>

You should do a few things as outlined in the code below
Close the <h3> element
Wrap the text you want to change in a span
Example
<div>
<h3 class="titleHeading">
<span class="titleHeadingText"> My Title</span>
<a ng-click="openTooltip('getMoreInfo')">
<span class="toolTip"></span>
</a>
</h3>
jQuery
$('h3.titleHeadingText').text("My New Title")

To achieve expected result, just update innerText for h3 by contents() data instead of using text()
Jquery contents() will return object of DOM elements
'data' property will provide the innerText of element
$('.titleHeading').contents()[0].data = "My New Title"
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<h3 class="titleHeading">My Title <a ng-click="openTooltip('getMoreInfo')"><span class="toolTip"></span></a>
<div>
codepen - https://codepen.io/nagasai/pen/YoXXjd?editors=1010

Related

Optimal way to retrieve HTML nodes having text using JavaScript/JQuery

How to get all the HTML nodes having text in an optimal way without having to loop through every node?
In other words, grab all HTML nodes having visible text.
For example, if I have a dom as below
<div>
<span>Hello This is a Text Span</span>
<div>
<p> This is a text Paragraph</p>
<button> This is Button Label</button>
</div>
<div> This is also a visible text</div>
</div>
I should select
span having text Hello This is a Text Span
p having text This is a text Paragraph
button having text This is Button Label
div having text This is also a visible text
The outermost div in the above example doesn't have text of its own so should not be part of the result.
Edit: What problem am I trying to solve?
The framework I use escapes HTML characters in labels of fields, buttons, headings etc.
For example: < is converted to & lt;'
So I am trying to write a client side code which triggers after the page is completely rendered which will unescape all the HTML texts to a readable format.
Any help will be appreciated.
Thanks in advance
The DOM property holds a numeric code indicating the node's type; text nodes use the code 3, So you can find those text nodes by filtering them having nodeType 3.
Wrap your all nodes in a div by giving a class.
Select your content by it's class like this: $(".getTextNodes").contents();.
Filter contents having nodeType 3.
selectedElement = $(".getTextNodes").contents();
textNodes = selectedElement.filter(function() {
return this.nodeType === 3;
});
console.log(textNodes);
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<div class="getTextNodes">
<span>Hello This is a Text Span</span>
<div>
<p> This is a text Paragraph</p>
<button> This is Button Label</button>
</div>
<div> This is also a visible text</div>
</div>
Check this link out to read more.
I'm using just only vanilla js
My algorithm is just select all element that has no element inside it
It means select all element that has directly Text Node
let el = document.querySelectorAll('div,span,p,button');
var arr = [];
el.forEach(function(m){
if (m.querySelectorAll('div,span,p,button').length == 0){
arr.push(m)
console.log(m)
}
})
// console.log(arr)
<div>
<span>Hello This is a Text Span</span>
<div>
<p>This is a text Paragraph</p>
<button> This is Button Label</button>
</div>
<div>This is also a visible text</div>
</div>
Jsfidle link click here
There's no css selector to get your needs and looping is only the solution.

css selector select only the first child text and not the div

I want to use css selector to select only the text (which is in my example "1.42") from this div<div class="one"> for scraping purpose:
<div class="one">
1.42
<div class="nested">..</div>
</div>
I tried this but return the whole <div class="one"> (and I want only the text):
div.one:first-child
and this also:
div.one:first-child:not(.nested)
They all return the text plus the content inside div.nested
EDIT:
I want to use the selector to scrape the specific text using Beautifulsoup
soup.select_one('div.one:first-child:not(.nested)')
You cannot css-select something that isn't inside of a html tag with or without a css class. In your case you should wrap your 1.42 text in a html tag, like a <p>.
That is also best practice, never to print text directly within a div, without a semantic text tag like a p.
Once you have your <p class="...">Text here</p> you can select div:first-child or simply select the p or p.theclassname. Another method is div:nth-child(1).

Get text after certain element (JavaScript or JQuery) [duplicate]

This question already has answers here:
Using .text() to retrieve only text not nested in child tags
(30 answers)
Closed 5 years ago.
Could some one give me some guidance on what's the best way to do this.
I'm trying to get all the text which is after ".main"
I know this might be simple, but it's been picking at my brain all day just before Christmas. So i thought instead of stressing myself out, I would look for some guidance.
The example code only brings back the Text in P tag but i'd like to bring back Text not in it's own element and the p tag
console.log($("#container").find(".main").next().text());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
<div class="main"> WOOP IN MAIN </div>
Text not in it's own element
<p> Text in P tag </p>
</div>
The simplest way to achieve this is to clone() the container, remove the .main element from it, then get the text(), like this:
var text = $("#container").clone().find('.main').remove().end().text();
console.log(text.trim());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
<div class="main"> WOOP IN MAIN </div>
Text not in it's own element
<p> Text in P tag </p>
</div>
You could alternatively recursively traverse through the DOM nodes that follow the .main element, but this is much more complicated and gives the same result.
It's because Text not in it's own element is considered a text node, therefore next() will target the <p/> tag, being that it's an HTMLElement. If you were to go native you'd use a combination of nextSibling, which is agnostic of the two node types and nextElementSibling, which as it's method name implies, grabs the next sibling element:
const main = document.querySelector('.main');
const txt = [
main.nextSibling.textContent.trim(),
main.nextElementSibling.textContent.trim()
];
console.log(txt)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
<div class="main"> WOOP IN MAIN </div>
Text not in it's own element
<p> Text in P tag </p>
</div>

Hide a parent element based on specific html tag contents

I'm trying to do something similar to How to hide an element, based on its text, with JavaScript? and Hiding a parent element using JS/JQuery based on the alt tag of a child element
but it's a bit more complicated than that. Here's the entire element (a list item containing lots of stuff) I want to hide:
<li>
<div class="wrapper">
<div class="fulllink" data-href="hideme/some/url" data-title="hideme - some more text">
<a href="/some/url" rel="stuff">
</div>
<div id="fullimage" class="theimage">
<img src="/some/url" title="hideme - some more text" alt="thisis/hideme text">
</div>
<div class="captionwrapper">
<div class="caption">
<p>
<a class="" title="" href="hideme/some/url">more text</a>
</p>
</div>
</div>
</div>
</li>
I want to hide this li element based on the specific content "hideme", which appears several times, but as you can see never on its own. It should be hidden as the page loads, so no user action required.
I've tried to come up with a solution based on similar questions on stackoverflow, but so far unsuccessfully.
You can use the html() function to get the html contents of each li and then search if it contains the desired text: "hideme".
$("li").each(function () {
if ($(this).html().indexOf('hideme') > -1) {
$(this).hide();
}
});
Demo

Select grandchildren inside a parent div using Jquery

Below is the code I am working with, as you can see, there is an id named "parent" and an id named "grandchilden". My goal is to get the content inside of this div "grandchildren". How can I achieve it?
I've tried $(this).closest('.grandchildren'), but didnt work.
<div id="parent">
<a href="#">
<div>
<p id="grandchildren">
This is a content
</p>
</div>
</a>
</div>
If you have a ID on that div you can use $('#grandchildren').html()
If you don't have a ID for it, what is the pattern? div > a > div > p ? In that case you can use this:
$('div#parent > a > div > p').html();
Demo here
Please notice the difference between .text() and .html(), if you just need to get text use .text() instead of .html()
If you have a reference like this you could use find which searches downwards, with the selected element as starting point:
$(this).find('.someClass')
$('#parent').find('#grandchildren').text();

Categories