How to change text inside span with jQuery, leaving other span contained nodes intact?
Solution 1
Try something like:
$('a.changeme').on('click', function() {
$(this).closest('.target').contents().not(this).eq(0).replaceWith('Do it again ');
});
demo: http://jsfiddle.net/eEMGz/
ref: http://api.jquery.com/contents/
Update:
I guess I read your question wrong, and you're trying to replace the text if it's already there and inject it otherwise. For this, try:
$('a.changeme').on('click', function() {
var
$tmp = $(this).closest('.target').contents().not(this).eq(0),
dia = document.createTextNode('Do it again ');
$tmp.length > 0 ? $tmp.replaceWith(dia) : $(dia).insertBefore(this);
});
Demo: http://jsfiddle.net/eEMGz/3/
Solution 2
You can try this.
var $textNode, $parent;
$('.changeme').on('click', function(){
$parent = $(this).parent();
$textNode= $parent.contents().filter(function() {
return this.nodeType == 3;
});
if($textNode.length){
$textNode.replaceWith('Content changed')
}
else{
$parent.prepend('New content');
}
});
Working demo - http://jsfiddle.net/ShankarSangoli/yx5Ju/8/
Solution 3
You can use .contents()
:
//set the new text to replace the old text
var newText = 'New Text';
//bind `click` event handler to the `.changeme` elements
$('.changeme').on('click', function () {
//iterate over the nodes in this `<span>` element
$.each($(this).parent().contents(), function () {
//if the type of this node is undefined then it's a text node and we want to replace it
if (typeof this.tagName == 'undefined') {
//to replace the node we can use `.replaceWith()`
$(this).replaceWith(newText);
}
});
});
Here is a demo: http://jsfiddle.net/jasper/PURHA/1/
Some docs for ya:
-
.contents()
: http://api.jquery.com/contents -
.replaceWith()
: http://api.jquery.com/replacewith -
typeof
: https://developer.mozilla.org/en/JavaScript/Reference/Operators/typeof
Update
var newText = 'New Text';
$('a').on('click', function () {
$.each($(this).parent().contents(), function () {
if (typeof this.tagName == 'undefined') {
//instead of replacing this node with the replacement string, just replace it with a blank string
$(this).replaceWith('');
}
});
//then add the replacement string to the `<span>` element regardless of it's initial state
$(this).parent().prepend(newText);
});
Demo: http://jsfiddle.net/jasper/PURHA/2/
Solution 4
You step out of jQuery because it doesn't help you to deal with text nodes. The following will remove the first child of every <span>
element with class "target" if and only if it exists and is a text node.
Demo: http://jsfiddle.net/yx5Ju/11/
Code:
$('span.target').each(function() {
var firstChild = this.firstChild;
if (firstChild && firstChild.nodeType == 3) {
firstChild.data = "Do it again";
}
});
András Szepesházi
Updated on June 09, 2022Comments
-
András Szepesházi almost 2 years
I have the following HTML snippet:
<span class="target">Change me <a class="changeme" href="#">now</a></span>
I'd like to change the text node (i.e. "Change me ") inside the span from jQuery, while leaving the nested
<a>
tag with all attributes etc. intact. My initial huch was to use.text(...)
on the span node, but as it turns out this will replace the whole inner part with the passed textual content.I solved this with first cloning the
<a>
tag, then setting the new text content of<span>
(which will remove the original<a>
tag), and finally appending the cloned<a>
tag to my<span>
. This works, but feels such an overkill for a simple task like this. Btw. I can't guarantee that there will be an initial text node inside the span - it might be empty, just like:<span class="target"><a class="changeme" href="#">now</a></span>
I did a jsfiddle too. So, what would be the neat way to do this?
-
hippietrail over 11 years
-
-
András Szepesházi about 12 years"Btw. I can't guarantee that there will be an initial text node inside the span - it might be empty" this test case fails.
-
Jasper about 12 years@AndrásSzepesházi I didn't realize you wanted to add the new string to empty containers as well. I updated my answer, here's a demo: jsfiddle.net/jasper/PURHA/2
-
András Szepesházi about 12 yearsyou forgot to update your fiddle, but the code quoted above works nicely for both cases (i.e. having / not having) initial text.
-
András Szepesházi about 12 years"Btw. I can't guarantee that there will be an initial text node inside the span - it might be empty" this test case fails. Otherwise cool.
-
András Szepesházi about 12 years"Btw. I can't guarantee that there will be an initial text node inside the span - it might be empty" this test case fails. Otherwise cool.
-
András Szepesházi about 12 years"Btw. I can't guarantee that there will be an initial text node inside the span - it might be empty" this test case fails. Otherwise cool.
-
Jasper about 12 yearsOne strange behavior is if there are text nodes on both sides of the
<a>
element they will both be replaced with the new text: jsfiddle.net/jasper/yx5Ju/9 -
ShankarSangoli about 12 years@Jasper - If that is going to be the case then it can be handled in the code. OP will know it better if such condition exists.
-
Code Junkie about 12 yearsIt seems like this might be a good place to extend jQuery higher up in the code, just to keep the working code clean; do you think so?
-
András Szepesházi about 12 yearsThanks! With a slight change this works for both cases I needed (both text replace and insert modes), jsfiddle.net/yx5Ju/12
-
Yoshi about 12 years@CodeJunkie I'm not sure. If this was just over and over again, then a plugin might be ok, but otherwise I'd stick without extending jquery for such little tasks.