How can I change text-nodes text?
HTML:
<p class='theClass'> bbb <a href=#> foo</a> aaa </p>
I'm trying to change 'aaa' and 'bbb' to hello world. I successed to select those nodes but couldn't change their text.
Jquery so far:
var $textNodes = $('.theClass').contents().filter(function() {
return this.nodeType == Node.TEXT_NODE;
});
JSFiddle
What can I do with this $textNodes to change their text?
Use the nodeValue or data property of the text node. Both are equally valid and well supported:
$textNodes.each(function() {
this.data = "CHANGED";
});
Incidentally, Node.TEXT_NODE does not exist in IE < 9, so you'd be better off simply using 3 instead.
You can't directly edit a text node with jQuery.
Just use the native data or nodeValue property directly on the nodes.
$textNodes.each(function() {
this.data = "Hello world";
// this.nodeValue = "Hello world";
});
jsFiddle
Found it after a lot of time in MDN:
This propery is called nodeValue not value for some stupid reason...
fixed JQuery:
var $textNodes = $('.theClass').contents().filter(function() {
return this.nodeType == Node.TEXT_NODE;
}).each(function(){
this.nodeValue = "hello World";
});
Fixed JSFiddle
Related
I have something like this.
<div id="firstDiv">
This is some text
<span id="firstSpan">First span text</span>
<span id="secondSpan">Second span text</span>
</div>
I want to remove 'This is some text' and need the html elements intact.
I tried using something like
$("#firstDiv")
.clone() //clone the element
.children() //select all the children
.remove() //remove all the children
.end() //again go back to selected element
.text("");
But it didn't work.
Is there a way to get (and possibly remove, via something like .text("")) just the free text within a tag, and not the text within its child tags?
Thanks very much.
Filter out text nodes and remove them:
$('#firstDiv').contents().filter(function() {
return this.nodeType===3;
}).remove();
FIDDLE
To also filter on the text itself, you can do:
$('#firstDiv').contents().filter(function() {
return this.nodeType === 3 && this.nodeValue.trim() === 'This is some text';
}).remove();
and to get the text :
var txt = [];
$('#firstDiv').contents().filter(function() {
if ( this.nodeType === 3 ) txt.push(this.nodeValue);
return this.nodeType === 3;
}).remove();
Check out this fiddle
Suppose you have this html
<parent>
<child>i want to keep the child</child>
Some text I want to remove
<child>i want to keep the child</child>
<child>i want to keep the child</child>
</parent>
Then you can remove the parent's inner text like this:
var child = $('parent').children('child');
$('parent').html(child);
Check this fiddle for a solution to your html
var child = $('#firstDiv').children('span');
$('#firstDiv').html(child);
PS: Be aware that any event handlers bounded on that div will be lost as you delete and then recreate the elements
Why try to force jQuery to do it when it's simpler with vanilla JS:
var div = document.getElementById('firstDiv'),
i,
el;
for (i = 0; i< div.childNodes.length; i++) {
el = div.childNodes[i];
if (el.nodeType === 3) {
div.removeChild(el);
}
}
Fiddle here: http://jsfiddle.net/YPKGQ/
Check this out, not sure if it does what you want exactly... Note: i only tested it in chrome
http://jsfiddle.net/LgyJ8/
cleartext($('#firstDiv'));
function cleartext(node) {
var children = $(node).children();
if(children.length > 0) {
var newhtml = "";
children.each(function() {
cleartext($(this));
newhtml += $('<div/>').append(this).html();
});
$(node).html(newhtml);
}
}
How can we change the text data from except span text?
<h2 id="nameUser" >Muhammed <span> mobile :989 531 9991</span></h2>
Is there any solution to change h2 except span?
.contents() returns a collection of nodes, including text nodes. So in your case this would work:
$('#nameUser').contents()[0].nodeValue = 'Another name';
If you want to get every node except the SPAN, try:
$('#nameUser').contents().filter(function() {
return this.nodeName != 'SPAN';
}).each(function(i) {
// modify each text node
this.nodeValue = 'name '+i;
});
DEMO: http://jsfiddle.net/Vks82/
Search for the first textnode in childNodes of the h2 element. Change the value of the textnode.
var element = document.getElementById('nameUser');
element.childNodes[0].nodeValue = 'New String';
..should work. Only for this example, because the first childnode is the textnode you want, you don't have to search for it. Otherwise you do..
This example may help you to change father element without changing child elements:
var content= $('#nameUser').children();
$('#nameUser').text('Altered Text').append(content);
$('#nameUser').contents().each(function() {
if (this.nodeType == 3)
this.data = "The text you want here";
});
Live DEMO
You can do it by saving the children first here is a codepen of it working.
http://codepen.io/beckje01/pen/sGLot
var h2 = $('#nameUser');
var elmsToSave = h2.children();
h2.empty();
h2.text('bob');
h2.append(elmsToSave);
As pointed out in the comments this will only work if the text to change is first.
This will work not only for span but also for any other element which you want the text without the text of it's children.
$("#nameUser")
.clone()
.children()
.remove()
.end()
.text();
For change the text I've create a simple jQuery function:
replaceTextWith = function($element, $replacement){
$oldText = $element.clone().children().remove().end().text();
$element.text($element.text().replace($oldText, $replacement));
}
replaceTextWith($("#nameUser"), "Bruno"); //usage
Here's a live example working on fiddle
try this ...
<h2 id="nameUser" >Muhammed <span id="nameUserSpan"> mobile :989 531 9991</span></h2>
<script>
$(document).ready(function() {
var inspan= $("#nameUserSpan").html();
var newuser='New User';
$("#nameUser").html('');
$("#nameUser").html(newuser + '<span id="nameUserSpan">' + inspan + '</span>');
});
</script>
for example we have this file
<div id="mydiv">
some text here
<div id="inner div">
text for inner div
</div>
</div>
i need to get #mydiv text only with some code like this :
alert($('#mydiv').text()); // will alert "some text here"
hey try this please": http://jsfiddle.net/MtVxx/2/
Good link for your specific case in here: http://viralpatel.net/blogs/jquery-get-text-element-without-child-element/ (This will only get the text of the element)
Hope this helps, :)
code
jQuery.fn.justtext = function() {
return $(this).clone()
.children()
.remove()
.end()
.text();
};
alert($('#mydiv').justtext());
The currently accepted answer is pretty horrible in terms of performance, so I felt obligated to write a more lightweight one:
$.fn.mytext = function() {
var str = '';
this.contents().each(function() {
if (this.nodeType == 3) {
str += this.textContent || this.innerText || '';
}
});
return str;
};
console.log($('#mydiv').mytext());
Like Ja͢ck's answer but no need for iterating explicitly (via .each()) and collecting textContents:
$('#mydiv').contents().filter(function(){return this.nodeType === 3}).text()
OR, if you can use arrow functions:
$('#mydiv').contents().filter((i, el) => el.nodeType === 3).text()
I am trying to build a string of the contents of a webpage, without HTML syntax (probably replace it with a space, so words are not all conjoined) or punctuation.
so say you have the code:
<body>
<h1>Content:</h1>
<p>paragraph 1</p>
<p>paragraph 2</p>
<script> alert("blah blah blah"); </script>
This is some text<br />
....and some more
</body>
I want to return the string:
var content = "Content paragraph 1 paragraph 2 this is some text and this is some more";
any idea how to do this? Thanks.
You can use the innerText property (instead of innerHTML, which returns the HTML tags as well):
var content = document.getElementsByTagName("body")[0].innerText;
However, note that this will also include new lines, so if you are after exactly what you specified in your question, you would need to remove them.
There is the W3C DOM 3 Core textContent property supported by some browsers, or the MS/HTML5 innerText property supported by other browsers (some support both). Likely the content of the script element is unwanted, so a recursive traverse of the related part of the DOM tree seems best:
// Get the text within an element
// Doesn't do any normalising, returns a string
// of text as found.
function getTextRecursive(element) {
var text = [];
var self = arguments.callee;
var el, els = element.childNodes;
for (var i=0, iLen=els.length; i<iLen; i++) {
el = els[i];
// May need to add other node types here
// Exclude script element content
if (el.nodeType == 1 && el.tagName && el.tagName.toLowerCase() != 'script') {
text.push(self(el));
// If working with XML, add nodeType 4 to get text from CDATA nodes
} else if (el.nodeType == 3) {
// Deal with extra whitespace and returns in text here.
text.push(el.data);
}
}
return text.join('');
}
You'll need a striptags function in javascript for that and a regex to replace consecutive newlines with a single space.
You can try using the replace statement below
var str = "..your HTML..";
var content = str.replace(/</?[a-zA-Z0-9]+>|<[a-zA-Z0-9]+\s*/>|\r?\n/g," ");
For the HTML that you have provided above, this will give you the following string in content
Content: paragraph 1 paragraph 2 alert("blah blah blah"); This is some text ....and some more
This is my jquery script that replace string to new string:
$("*").contents().each(function() {
if(this.nodeType == 3)
this.nodeValue = this.nodeValue.replace("1.(800).123.1234", "new");
});
working example : http://jsfiddle.net/webdesignerart/eKRGT/
but i want to add before and after to string html element like new
when i do this :
this.nodeValue = this.nodeValue.replace("1.(800).123.1234", "<b>new</b>");
The Result comes:
<b>new</b>
I want output this: new
i want to allow html tags during replacement.
is jquery .append work with this.
You are replacing the contents of a TextNode element which is always just text. To make the text bold, you will need to create another element, b which wraps around the TextNode. One approach is to use the wrap() from jQuery:
$("*").contents().each(function() {
var me = this;
if(this.nodeType == 3)
this.nodeValue = this.nodeValue.replace("1.(800).123.1234", function(a){
$(me).wrap('<b />');
return "new";
});
});
example: http://jsfiddle.net/niklasvh/eLkZp/
This should work:
$("*").contents().each(function() {
var me = this;
if(this.nodeType == 3
&& this.nodeValue.indexOf("1.(800).123.1234")>-1){
$(this).replaceWith(this.nodeValue.replace("1.(800).123.1234", "<b>new</b>"));
}
});
http://jsfiddle.net/eLkZp/20/
Basically replace the text node rather than just the text within it.
You should really consider if there's some way to narrow down that original filter though. Parsing your entire page is generally a bad idea.