How to change only text node in element
If you use contents()
method it will also return text nodes. Since jQuery doesn't have text node methods, convert last node to a DOM node
$('label[for="user_name"]').contents().last()[0].textContent='Title';
Demo: http://jsfiddle.net/yPAST/1/
jQuery way to replace just a text node with a mix of HTML and text?
You basically want to replace the first child (text node) with the new content. You need http://api.jquery.com/replaceWith/
// Text node we want to process and removevar textNode = $("#target").contents().first();// Break the text node upvar parts = textNode.text().split(/\s/);// Put links around themvar replaceWith = "";for (var i =0; i < parts.length;i++) { replaceWith += "<a href='http://www.google.com'>" + escapeHTML(parts[i]) + "</a> ";}// Replace the text node with the HTML we createdtextNode.replaceWith(replaceWith);
function escapeHTML(string) { return string.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><div id="target">example, handles escaping properly, you should see an ampersand followed by "amp;" here: & <img src="/foobar.png"></div>
Change textNode value
If you have a specific node (of type #text) and want to change its value you can use the nodeValue property:
node.nodeValue="new value";
Note:
innerText (and possibly textContent) will return/set both the current node and all descendent nodes text, and so may not be the behaviour you want/expect.
Use javascript to change text only in an element
Get the first textNode by firstChild
property and update the content.
function change_stuff() { // get the first child node, in your code which is the text node var t = document.getElementById('to_change').firstChild;
// update the text contents in the node t.nodeValue = "";
// or t.textContent = "";
// or remove the node itself // t.parentNode.removeChild(t)}
<div id="to_change"> This is a huge block of text that I want to replace while leaving the image in place <img src="./the_image.jpg"></div><button onclick="change_stuff();"> ThE dOER!!</button>
Replace text in the middle of a TextNode with an element
To 'change' a text node into an element, you must replace it with an element. For example:
var text = tree.currentNode;
var el = document.createElement('foo');
el.setAttribute('bar','yes');
text.parentNode.replaceChild( el, text );
If you want to retain part of the text node, and inject an element "in the middle", you need to create another text node and insert it and the element into the tree at the appropriate places in the tree.
Edit: Here's a function that might be super useful to you. :)
Given a text node, it runs a regex on the text values. For each hit that it finds it calls a custom function that you supply. If that function returns a string, then the match is replaced. However, if that function returns an object like:
{ name:"element", attrs{onmouseover:"sendWord('foo')"}, content:"foo" }
then it will split the text node around the match and inject an element in that location. You can also return an array of strings or those objects (and can recursively use arrays, strings, or objects as the content
property).
Demo: http://jsfiddle.net/DpqGH/8/
function textNodeReplace(node,regex,handler) {
var mom=node.parentNode, nxt=node.nextSibling,
doc=node.ownerDocument, hits;
if (regex.global) {
while(node && (hits=regex.exec(node.nodeValue))){
regex.lastIndex = 0;
node=handleResult( node, hits, handler.apply(this,hits) );
}
} else if (hits=regex.exec(node.nodeValue))
handleResult( node, hits, handler.apply(this,hits) );
function handleResult(node,hits,results){
var orig = node.nodeValue;
node.nodeValue = orig.slice(0,hits.index);
[].concat(create(mom,results)).forEach(function(n){
mom.insertBefore(n,nxt);
});
var rest = orig.slice(hits.index+hits[0].length);
return rest && mom.insertBefore(doc.createTextNode(rest),nxt);
}
function create(el,o){
if (o.map) return o.map(function(v){ return create(el,v) });
else if (typeof o==='object') {
var e = doc.createElementNS(o.namespaceURI || el.namespaceURI,o.name);
if (o.attrs) for (var a in o.attrs) e.setAttribute(a,o.attrs[a]);
if (o.content) [].concat(create(e,o.content)).forEach(e.appendChild,e);
return e;
} else return doc.createTextNode(o+"");
}
}
It's not quite perfectly generic, as it does not support namespaces on attributes. But hopefully it's enough to get you going. :)
You would use it like so:
findAllTextNodes(document.body).forEach(function(textNode){
replaceTextNode( textNode, /\b\w+/g, function(match){
return {
name:'element',
attrs:{onmouseover:"sendWord('"+match[0]+"')"},
content:match[0]
};
});
});
function findAllTextNodes(node){
var walker = node.ownerDocument.createTreeWalker(node,NodeFilter.SHOW_TEXT);
var textNodes = [];
while (walker.nextNode())
if (walker.currentNode.parentNode.tagName!='SCRIPT')
textNodes.push(walker.currentNode);
return textNodes;
}
or if you want something closer to your original regex:
replaceTextNode( textNode, /(^|\W)(\w+)/g, function(match){
return [
match[1], // might be an empty string
{
name:'element',
attrs:{onmouseover:"sendWord('"+match[2]+"')"},
content:match[2]
}
];
});
How can I change an element's text without changing its child elements?
Mark’s got a better solution using jQuery, but you might be able to do this in regular JavaScript too.
In Javascript, the childNodes
property gives you all the child nodes of an element, including text nodes.
So, if you knew the text you wanted to change was always going to be the first thing in the element, then given e.g. this HTML:
<div id="your_div">
**text to change**
<p>
text that should not change
</p>
<p>
text that should not change
</p>
</div>
You could do this:
var your_div = document.getElementById('your_div');
var text_to_change = your_div.childNodes[0];
text_to_change.nodeValue = 'new text';
Of course, you can still use jQuery to select the <div>
in the first place (i.e. var your_div = $('your_div').get(0);
).
How can I get only the content of text nodes (not nested tags) from an HTML tag element in JS?
You have a couple of options:
bob
is in a Text
node in the div. You can't select a Text
node directly, but you can access it via the childNodes
on its parent (or nextSibling
on the span
in front of it, etc.):
const div = document.getElementById("mydiv");
console.log("`nodeValue` of each text node in the div:");
for (const child of div.childNodes) {
if (child.nodeType === Node.TEXT_NODE) {
console.log(child.nodeValue);
}
}
<div id="mydiv">
<span>foo</span>
<span>bar</span>
bob
</div>
jQuery replace only the text of a node, ignoring current internal nodes
If you have access to the HTML I'd wrap the text in a span
so that you can address it easily. However, with what you have so far you can simply iterate over all nodes in the element and change the textContent
of the first text node (nodeType==3
):
$(function(){ $("label").contents().each(function() { if(this.nodeType == 3){ this.textContent = "Quick Search: "; return false; } }) });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><label>Search: <input id="search-box" type="text"/></label>
Replace a textNode with HTML text in Javascript?
You'll need to replace the textNode with an HTML element, like a span, and then set your linkified-text as that element's innerHTML.
var replacementNode = document.createElement('span');
replacementNode.innerHTML = linkify(n.textContent);
n.parentNode.insertBefore(replacementNode, n);
n.parentNode.removeChild(n);
Related Topics
Javascript: Using a Condition in Switch Case
Javascript: How to Dynamically Create Nested Objects Using Object Names Given by an Array
Is This Simple String Considered Valid JSON
How to Get the Status Code from an Http Error in Axios
What Is "Function*" in JavaScript
Overriding a JavaScript Function While Referencing the Original
JavaScript Closures and 'This'
Array.Push() If Does Not Exist
Migrating Angularjs to Angular 4,5 (With Demo)
How to Handle the 'Onkeypress' Event in Reactjs
JavaScript Regex Hangs (Using V8)
How to Simulate Key Presses or a Click with JavaScript
Limited Parallelism with Async/Await in Typescript/Es7
Make Checkbox Behave Like Radio Buttons with JavaScript