37

I have an element like this:

<td>
  <a>anchor</a>
  [ some text ]
</td>

And i need to set it's text in jQuery, without removing the anchor.

The element's contents could vary in order (text before or after), and the actual text is unknown.

Thanks

New Update

This is what i came up using, assumes only a single text node:

    function setTextContents($elem, text) {
        $elem.contents().filter(function() {
            if (this.nodeType == Node.TEXT_NODE) {
                this.nodeValue = text;
            }
        });
    }

    setTextContents( $('td'), "new text");
J.C. Inacio
  • 4,442
  • 2
  • 22
  • 25
  • 2
    Can you identify if the contents will be before or after the `anchor` in your javascript? If so, you can then set a variable `prepend()` or `append()` based on your case. – Dave Kiss May 27 '11 at 18:50
  • Quite complex. Isn't there a possibility to include the text in a span? – GolezTrol May 27 '11 at 18:50
  • Im not sure i understand your question, but you could select the anchor tag and use .after() or .before() – Mike Fielden May 27 '11 at 18:51
  • I assume you have some convention that lets you know where the anchor should appear in the text? – Jamie Treworgy May 27 '11 at 18:52
  • 1
    If it's not your HTML (i.e. this is for a greasemonkey script or something) you could probably copy the anchor element, wipe out the TD fill it with what you want and replace the anchor. – Fosco May 27 '11 at 18:53
  • I've seen (and experienced) this issue before. I wonder why it's so hard to access text nodes? – Mark Snidovich May 27 '11 at 18:53
  • "I wonder why it's so hard to access text nodes" - it is, but I can't think of any downside to wrapping them in `span` tags if you need that kind of access. – Jamie Treworgy May 27 '11 at 18:55
  • Many people are unaware that text is a node in the DOM, and you can set its value with [textnode].value. Finding the node is the only issue (working on a fiddle for this example). – Wylie May 27 '11 at 19:04
  • Possible duplicate of **[In jQuery how can I change an element's text without changing its child elements?](http://stackoverflow.com/questions/4106809)** – hippietrail Oct 11 '12 at 06:24

4 Answers4

49

Neal's answer is my suggestion. jQuery doesn't have a way to select text nodes How do I select text nodes with jQuery?.

Changing your HTML structure will make for the simplest code. If you can't do it, you can just use the childNodes property looking for nodes of type 3 (TEXT_NODE)

Here's some sample code that assumes the last node is the node you want to edit. This is a better approach than replacing the entire contents of the td because you could lose event handlers when you recreate the HTML

$('a').click(() => console.log('<a> was clicked'))

$('#btn').click(() =>
  $('.someClass').get(0).lastChild.nodeValue = " New Value");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='someClass'>
  <a href="javascript:void(0)">anchor</a> [ some text ]
</div>

<button id='btn'> Change text without losing a tag's handler</button>
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
10

If it is possible to put the text in a span:

<td id='someID'>
  <a>anchor</a>
  <span>[ some text ]</span>
</td>

You can do:

$('td#someID span').text('new text')
Naftali
  • 144,921
  • 39
  • 244
  • 303
  • 1
    Almost identical to what I was posting. – g.d.d.c May 27 '11 at 18:53
  • @g.d.d.c ahhh but you didn't :-P – Naftali May 27 '11 at 18:54
  • 1
    I did, but after I added my comment to yours. :) – g.d.d.c May 27 '11 at 18:54
  • 2
    Downvoted. This is not the solution to what he was asking, this was the easy way out. – daryl May 27 '11 at 19:14
  • 1
    @tfbox: The easy way out is often the best way out. Why would you structure your HTML so it's harder to access? This may not accurately answer the specific question but does propose a good solution. – Ruan Mendes Jun 06 '11 at 22:17
  • 2
    @JuanMendes In some cases, you have no control over HTML, or it would lead to shotgun editing to gather control over HTML: Imagine you use some standard templates of a CMS, and only changing a small bit of HTML would lead to copy-paste actions into a custom template and probably some configuration work to integrate it. – Cedric Reichenbach Jan 11 '14 at 15:00
  • 1
    @CedricReichenbach I know, but for cases where you do have control over the HTML, this is a better solution. Just saying it's not worth a downvote – Ruan Mendes Nov 07 '16 at 22:36
4

Without changing markup:

Live Demo

var anchor = $('td').find('a').clone();
$('td').text('{ some other text }').prepend(anchor);
drudge
  • 35,471
  • 7
  • 34
  • 45
  • Works but is not very elegant. The a tag is unnecessarily removed and added back to the DOM. This is doable with a much smaller change to the DOM, see my answer – Ruan Mendes Jun 02 '11 at 22:03
0

After this topic I make some improvement, nothing deal. Because if you get a long script and then the selector is not there the nodeValue return TypeError and stop the script on that line, so I use the show() basic effect into a function to execute if that element exists on DOM, then if is true use nodeValue to change it (I am noob on java so mabye this not

$('td').show(function() {
 $(this).contents()[0].nodeValue = "new text"
});
Oreo
  • 21
  • 2