76

I would like to change the text of a HTML element but preserve the rest of the inner html with jQuery.

For instance:

<a href="link.html">Some text <img src="image.jpg" /></a> 

replace "Some text" with "Other text", and the result should look like:

<a href="link.html">Other text <img src="image.jpg" /></a> 

EDIT: My current solution is following:

var aElem = $('a');
var children = aElem.children();

aElem.text("NEW TEXT");
aElem.append(children); 

But there must be some more elegant way of doing this.

Drejc
  • 14,196
  • 16
  • 71
  • 106

14 Answers14

40

This seems to work just fine.

Live Demo

<html>
    <head>
    </head>
    <body>
        <a href="link.html">Some text <img src="img.jpg" /></a>
    </body>

    </html>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>
    <script type="text/javascript">
        $(function(){
            var $link = $('a');
            var $img = $link.find('img'); 
            $link.html('New Text');
            $link.append($img);
        });
    </script>
Brandon Boone
  • 16,281
  • 4
  • 73
  • 100
37

Since you can't modify the link an option would be to simply use replace

$("a").html($("a").html().replace("Some text", "Other text"));

Example on jsfiddle.

Mark Coleman
  • 40,542
  • 9
  • 81
  • 101
  • 3
    Why the down vote? using this method would preserve the original markup. Ex. `Some text ` with detach/reattach results in `Other Text` while using a simple replace maintains the structure. – Mark Coleman Mar 09 '11 at 13:28
  • 4
    What if the `` tag contains `Some text` ?? – Philippe Lavoie Jul 08 '13 at 16:01
  • I don't know why I downvoted your answer, must have been a mistake. Just saw a “+9” on my score and wondered why one point was missing and saw my downvote here. I can't revoke the downvote until the answer is edited :/ – max-m Dec 11 '14 at 19:00
  • 4
    A bit naive, right? I voted this down because obviously the string "Some text" won't be the one being replaced when deployed. This will of course be other strings in a dynamic site. Therefore it's impossible to rely on string matching like this. – Niklas Wulff Jun 30 '15 at 09:54
  • Could be improved by caching the jQuery selection – anthonygore Jun 15 '16 at 07:05
  • Also this replaces only the first occurrence. If you want to replace it more than once, [RegExp will do](https://stackoverflow.com/questions/1144783/how-to-replace-all-occurrences-of-a-string-in-javascript). – CodeBrauer May 24 '18 at 10:07
23

Wrap the text you want to change in a span

<a href="link.html"><span>Some text</span> <img src="image.jpg" /></a> 

$('a span').html( 'new text' );
meouw
  • 41,754
  • 10
  • 52
  • 69
14

My solution, though a little late.

$('a').each(function() {
    var contents = $(this).contents();
    if (contents.length > 0) {
        if (contents.get(0).nodeType == Node.TEXT_NODE) {
            $(this).html('NEW TEXT').append(contents.slice(1));
        }
    }
});

Some notes:

  1. contents() includes text nodes, unlike children().
  2. It is necessary to create a copy of the contents via var contents = ... or else the remaining elements are lost forever once replaced by $(this).html('NEW TEXT').
  3. The length check is optional but recommended.
  4. The nodeType check is optional but recommended.
Andrew Cheong
  • 29,362
  • 15
  • 90
  • 145
13

An alternative way would be to use the contents() method as follows:

Given

<a href="link.html">Some text <img src="image.jpg" /></a>

you can replace 'Some text' with jQuery

var text = $('a').contents().first()[0].textContent;
$('a').contents().first()[0].textContent = text.replace("Some text", "Other text");

jsFiddle example here.

The idea of contents() was inspired by this question, answered by user charlietfl.

Community
  • 1
  • 1
jim_kastrin
  • 4,830
  • 2
  • 26
  • 28
12

You can change it by .contents()

$('.yourElement').contents()[0].data = 'New Data';

where in your case the "[0].data" is your text data

Darryl Ceguerra
  • 181
  • 1
  • 7
2

just use some plain js functionality:

$('a')[0].firstChild.nodeValue = "New Text";

Drea58
  • 429
  • 2
  • 6
1

An efficient and robust way that doesn't require you to know what the inner elements are or what the text is:

var $a = $('a');
var inner = '';
$a.children.html().each(function() {
    inner = inner + this.outerHTML;
});
$a.html('New text' + inner);
anthonygore
  • 4,722
  • 4
  • 31
  • 30
1

try this code

$('a').live('click', function(){
    var $img = $(this).find('img'); 
    $(this).text('changed');
    $(this).append($img);
});
xkeshav
  • 53,360
  • 44
  • 177
  • 245
  • This will not work as it will replace the whole inner part including the holding HTML elements. – Drejc Mar 08 '11 at 13:26
0

This is an improvement I've made to the jquery.uniform library. Specifically the $.uniform.update() function. I took the idea from acheong87 and changed it a bit.

The idea is to change the text in a span but preserve the inner HTML and event bindings. No need to store and append HTML this way.

if ($e.is("input[type=button]")) {
    spanTag = $e.closest("span");
    var contents = spanTag.contents();

    if (contents.length) {
        var text = contents.get(0);

        // Modern browsers support Node.TEXT_NODE, IE7 only supports 3
        if (text.nodeType == 3)
            text.nodeValue = $e.val();
    }
}
Tim Vermaelen
  • 6,869
  • 1
  • 25
  • 39
0

I added a jQuery function for that need.

you may need to convert the html-entities to text representation, so i added decodeEntities function.

function decodeEntities(encodedString) {
 if (typeof encodedString != "string") return encodedString;
 if (!encodedString) return "";
 var textArea = document.createElement('textarea');
 textArea.innerHTML = encodedString;
 return textArea.value;
}
jQuery.fn.textOnly = function(n) {
  if (this.length > 0)
   $(this).html(decodeEntities($(this).html()).replace($(this).text(), n));
  return $(this);
 }

Usage example $('selector').textOnly('some text')

0

My generic version:

let button = $('#yourElement');
button.html(button.html().replace(button[0].innerText, "New Text"));
oceanBT
  • 204
  • 6
  • 11
0

Shorthand for more elements and leading text to change:

elemshtml = '';
$("a *").each(function(){elemshtml +=$(this)[0].outerHTML});
$("a").html('Some text' + elemshtml);
user3270784
  • 460
  • 5
  • 5
0

You'll need to add in a <span> element and change the text of that element, e.g.:

<a href="link.html"><span id="foo">Some text</span><img src="image.jpg" /></a>

Then, you can call from jQuery:

$("#foo").html("Other text");

And your result will effectively be:

<a href="link.html"><span id="foo">Other text</span><img src="image.jpg" /></a>
Brian Driscoll
  • 19,373
  • 3
  • 46
  • 65