views:

84

answers:

5

Given a string of text that is both adjacent to a span and inside of a div, what are some methods to modify just that text, leaving the surrounding HTML intact? For example:

<div id="my-div">modify this text<span id="my-span"></span></div>

I have tried things like

$('#my-div').html(function(i, elem){blah;});

but this seems to cause the span to be deleted and a new span to be added (I notice that some styling is lost on the span).

I realize that it would be best to wrap the text string in its own HTML tags before applying client-side code, but that is out of my control.

A: 

Instead of modifying its HTML string, modify its DOM tree, find the top-level text nodes and do with them.

SHiNKiROU
This makes sense, but how do I isolate the text as some kind of object?
Jacob
+2  A: 

What about using jQuery's contents() method?

http://api.jquery.com/contents/

alex
I think we're on to something here...
Jacob
A: 

You could just use string replace:

HTML

<div id="my-div">modify this text <span id="my-span">or this text here</span></div>

Script

$('#my-div').html(function(i,html){
 return html.replace('this text', 'some new text').replace('or this text', 'and replace this text');
})
fudgey
This does the same thing I mentioned before. It replaces text, destroying DOM objects.
Jacob
How does it destroy DOM objects when it's replacing text? Now if I added `.replace('<span id="my-span">','')` sure that will destroy the span, but you are intentionally doing it in this case.
fudgey
+1  A: 

have you tried something like:

$(document).ready(function(){

  var elems = $('#myDiv *').detach();

  $('#myDiv').text('new texts...').append(elems);

})​

quick demo

edit

or as alex suggested to use .contents():

  $('#myDiv').contents()
    .filter(function(){
       return this.nodeType != 1 && $.trim($(this).text()) != '';        
    })
    .replaceWith("I am the new text");
Reigel
Again, this destroys the spans and replaces them with new ones.
Jacob
@Jacob `.detach()` does not destroy the elements http://api.jquery.com/detach/
Reigel
please see edit
Reigel
Alright, that does make sense.
Jacob
+2  A: 

This seems to work:

$('#my-div').contents()
            .filter(function() { return this.nodeType == 3; })
            .replaceWith('new text or html');

nodeType == 3 is to test for a text node.

Siddhartha Reddy
I was going to write this very thing as the correct solution when I saw yours pop up here. Nice!
Jacob