Replacing Text Nodes With jQuery

Posted September 7, 2011 at 9:34 AM by Ben Nadel

Tags: Javascript / DHTML

This morning on Twitter, I came across a Tweet from Robert Rawlins (aka. @SirRawlins) asking about replacing text values within a DOM element. He had a situation in which a node contained mixed children; that is, the node contained both element nodes (type 1) and text nodes (type 3). What he wanted to do was replace one of the text nodes, leaving the element nodes unaltered. While we primarily deal with element nodes, jQuery is certainly equipped to deal with text nodes when necessary.

NOTE: Rob Rawlins already solved this problem by the time I finished writing this; but, I figured I would post it for reference.

Typically, when we think about gathering the children of a DOM node using jQuery, we think about the children() method. This collects all of the elements that are the direct descendants of the given node. In most cases, this is what we want - the Element nodes. In rare cases, however, we do want to get at the Text nodes contained within an element. To do this, we can use the contents() method. The contents() method, like the children() method, gathers up directly descendant nodes; however, unlike the children() method, the contents() method includes both Element and Text nodes within its aggregate.

Once we can include text nodes in our jQuery collections, we can start to replace them as we would replace any other DOM node we have a reference to. To see this in action, take a look at the following code:

  • <!DOCTYPE html>
  • <html>
  • <head>
  • <title>Replacing Text Nodes With jQuery</title>
  • <script type="text/javascript" src="./jquery-1.6.1.js"></script>
  • </head>
  • <body>
  •  
  • <h1>
  • Replacing Text Nodes With jQuery
  • </h1>
  •  
  • <p class="statement">
  • Helena Bonham Carter is <em>hella</em> cool.
  • </p>
  •  
  •  
  • <!--
  • Now that the DOM has *mostly* loaded, let's replace out
  • some of the TEXT data with new TEXT data using jQuery.
  • -->
  • <script type="text/javascript">
  •  
  •  
  • // I return true if the current context (node) is a text node
  • // in an HTML DOM.
  • //
  • // NOTE: This will be used as a filter() argument.
  • function isTextNode(){
  •  
  • // If this is a text node, return true.
  • return( this.nodeType === 3 );
  •  
  • }
  •  
  •  
  • // Get the text nodes in our statement paragraph. Contents()
  • // will get us ALL children, including non-element nodes.
  • // Then, we can filter those down to the final text one.
  • var textNodes = $( "p.statement" ).contents()
  • .filter( isTextNode )
  • ;
  •  
  • // Now, let's only look at the LAST text node ("cool.").
  • var lastTextNode = textNodes.last();
  •  
  • // Replace the last text node with a new text node.
  • //
  • // NOTE: I could have just passed a simple string into the
  • // replaceWith() function; however, I chose to go with a
  • // createTextNode() in order to make sure that jQuery didn't
  • // misinterpret the value that was being passed-in.
  • lastTextNode.replaceWith(
  • document.createTextNode( " sexy!!!" )
  • );
  •  
  •  
  • </script>
  •  
  • </body>
  • </html>

Here, we have a paragraph that contains mixed children - both element and text nodes. When the DOM has loaded, we are getting a reference to the last text node within the paragraph and replacing it with a new text node. And, when we run the above code, we get the following output:

Helena Bonham Carter is hella sexy!!!

Notice that the "cool." was replaced with "sexy!!!". Also, notice that my replacement text takes into account that the last text node includes both leading and trailing white space. As such, the replacement text also has to include leading and (optionally) trailing white space so as not to have the resultant text insertion butt-up against the previous element.

Most of the time, jQuery allows us to work very efficiently with Element nodes contained within the DOM. However, at times, we need to access non-Element nodes; we need to access the raw Text nodes of the DOM tree. In such cases, we can still use jQuery to make our lives easier.




Reader Comments

Sep 7, 2011 at 10:45 AM // reply »
1 Comments

Ah, good man!

Good job on writing this up, thank you!

It's great when you get introduced to new approaches of traversing through the DOM like this, opens up so many other lines of thought, breaking age-old habits of using methods like children() all the time.

Cheers again bud.

Robert


Sep 7, 2011 at 9:00 PM // reply »
1 Comments

Excellent writeup Ben. We often forget that there are other things besides simple elements to work with.


Sep 9, 2011 at 7:37 AM // reply »
1 Comments

Great article dude!

One thing i am always missing, when reading one of your posts including sourcecodes is a better syntax-highlighter. Its a bit more difficult than it has to be.

Cheers


Sep 9, 2011 at 3:06 PM // reply »
10,743 Comments

@Robert,

Hey man, thanks for the inspiration :)

@Richard,

Using elements just makes things so easy. If I recall correctly from Rob's tweets, he was dealing with content that he was not actually authoring (as such, he had to deal with the text nodes). Probably, if you could go back and do it from scratch, it'd be easier to just throw a SPAN in there somewhere for easy reference. Elements are just easier to do anything with.

@Philipp,

Yeah, WORD UP to that! My color coder basically only works for ColdFusion. When it hits JavaScript, it has no idea what to do. I really gotta work on this.

Part of the problem is that I can't use the typically syntax highlighters because my code is stored in Unordered Lists which makes dealing with them a bit more difficult (but gives me greater control over the layout and flow).

I'll put some time in to updating this. Especially now that I am working with JavaScript so much more than I used to.


Dec 20, 2011 at 12:13 PM // reply »
1 Comments

Thanks for your nice piece of code.

Keep up the good work!


Jan 12, 2012 at 8:42 PM // reply »
1 Comments

Thank you so much for this! I spent all evening trying to figure this out and I'm not that handy with JS (which is why I use jQuery). This article came to the rescue and saved me many hours of stress!


Jan 17, 2012 at 10:25 AM // reply »
1 Comments

Thanks! Excactly what I've searched for.


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
InVision App - Prototyping Made Beautiful With Prototyping Tools Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 21, 2012 at 1:58 AM
Updated: Converting A ColdFusion Query To CSV Using QueryToCSV()
Hi Ben, why do you need to have so many double quotes when adding the field and field name to the row data? ----------------------------------------- <cfset LOCAL.RowData[ LOCAL.ColumnIndex ] = ... read »
AXL
May 21, 2012 at 1:24 AM
URL Rewriting And ColdFusion's WriteToBrowser Image Functionality (CFFileServlet)
@Mounir, Open your lower case URL Rewrite rule and add the following condition. Condition input: {REQUEST_URI} Check if input string: Does Not Match the Pattern Pattern: ^/CFFileServlet/_cf_ca ... read »
May 20, 2012 at 4:28 AM
Understanding The Complex And Circular Relationships Between Objects In JavaScript
@Will Vaughn I tried your javascript example but got this error:- foo.print is not a function ... read »
May 19, 2012 at 5:37 AM
A Graphical Explanation Of Javascript Closures In A jQuery Context
Thanks for this article, but I fear you missed an important point. If variables in the outer context change, these changes affect the inner anonymous functions as well. That means: if you change the ... read »
May 18, 2012 at 3:39 PM
Parsing CSV Data With An Input Stream And A Finite State Machine
Can you use file upload button with this? and read live? or does the file have to already be on the server saved? ... read »
May 18, 2012 at 1:06 AM
VIRGO (Aug. 23-Sept. 22): Dead On The Money!
A friend of mine and I were arguing about astrology and she told me that he believes in astrology. She hasn't provided me with any evidence that the belief makes any sense to me. She she been telling ... read »
May 17, 2012 at 11:32 PM
Using ColdFusion to Handle 404 Errors (Page Not Found) On Development Server
Very easy the configuration. I read a lot pages and I can't find the solution. I open the administrator and change this Administrator/server settings/Error Handlers/Missing Template Handler and p ... read »
May 17, 2012 at 3:13 PM
LOCAL Variables Scope Conflicts With ColdFusion Query of Queries
I never cease to be amazed that almost EVERY random CF issue I come across lands me on your site. Thank you for documenting your findings for the world. ... read »