Wouter
Wouter

Reputation: 430

jQuery: Find text and replace with HTML

I try to find and replace text (using jQuery). Actually I'm trying to add a span element around the text. I should also be able to remove the span again without losing the text inside.

For example, let's say I have the following situation to start with:

<span>This is a span element</span>

And I want to be able to do this dynamically using jQuery/JavaScript:

<span>This is a <span class="marked">span</span> element</span>

I should also be able to remove the span.marked and get back to the first result.

The problem however is that I want to do this on all text inside a container with multiple children and subchildren and so on.

The code I got so far will do the following and that is not what I want:

<<span class="marked">span</span>>This is a <span class="marked">span</<span class="marked">span</span> element</span>

I want to do this for ALL text on the page, not just the first it finds.

EDIT: my code so far for doing this:

var re = new RegExp(word, 'g');
$('.container').html($('.container').html().replace(re, '<span class="marked">' + word + '</span>'));

word is a string with the text to wrap spans around.

Upvotes: 8

Views: 40894

Answers (7)

Invincible
Invincible

Reputation: 1460

$('.container p').each(function() {
    var text = $(this).text();
    $(this).html(text.replace('word', '<strong><span class="accordion">word </span></strong>')); 
});

Upvotes: 6

Tim Down
Tim Down

Reputation: 324507

Don't use a regular expression. Use DOM traversal, which will be much more reliable, faster and less destructive (event handlers are not destroyed, for example).

See https://stackoverflow.com/a/10618517/96100 for a simple example.

Alternatively, you could use the following:

http://james.padolsey.com/javascript/replacing-text-in-the-dom-solved/

This doesn't cover removing the spans afterwards but that is a reasonably simple matter. Something like the following (untested):

function replaceWithOwnChildren(el){
    var parent = el.parentNode;
    while (el.hasChildNodes()) {
        parent.insertBefore(el.firstChild, el);
    }
    parent.removeChild(el);
}

// Create a non-live standard array of spans
var spans = [].slice.call(document.getElementsByTagName("span"), 0);
for (var i = 0, len = spans.length; i < len; ++i) {
    if (spans[i].className == "marked") {
        replaceWithOwnChildren(spans[i]);
    }
}

// Glue together any adjacent text nodes
document.normalize();

Upvotes: 2

Andrey
Andrey

Reputation: 161

var mark = function(word){
    return function(){
        this.innerHTML = this.innerHTML.replace(word,'' + word + '');
    }
};
$('span').each(mark('span'));

Upvotes: 1

PavKR
PavKR

Reputation: 1621

To wrap a search string in html you can use something like this:

$('span:contains("word")').html().replace('word', '<span class="marked">word</span>');

and to remove it, you can use something like this:

$('span:contains("word")').html().replace('<span class="marked">word</span>', 'word');

Yes this is a pretty crude way of doing it but it should work.

EDIT: as pointed out by @user3558931, the word needs to be a variable.

To wrap a search string in html you can use something like this:

$('span:contains("' + str + '")').html().replace(str, '<span class="marked">' + str + '</span>');

and to remove it, you can use something like this:

$('span:contains("' + str + '")').html().replace('<span class="marked">' + str + '</span>', str);

EDIT: A glitch in the above code, see the fixed code in this fiddle: http://jsfiddle.net/thePav/7TNk6/21/

Upvotes: 11

PeterKA
PeterKA

Reputation: 24638

I believe the regular expression needs to be adjusted so it does not pick <span or any other HTML tag for that matter. I would like to suggest the RegExp:

var re = new RegExp('[^<\\/](' + word + ')', 'g');

And the replacement:

$('.container').each(function() {
    $(this).html( $(this).html().replace( re, ' <span class="marked">$1</span>' ) );
});

And can be reversed by using the code (Click button in demo below):

$('button.undo').on( 'click', function() {
    $('.container').find( 'span.marked' ).each(function() {
        $(this).replaceWith( word );
    });
});

JS FIDDLE DEMO

OTHER DEMO

Upvotes: 1

ndugger
ndugger

Reputation: 7531

var span = document.getElementsByTagName("span")[0];
span.innerHTML = span.innerHTML.replace(/span/g, "<span class=\"marked\">span</span>");

http://jsfiddle.net/7TNk6/1/

Upvotes: 0

Jurijs Kastanovs
Jurijs Kastanovs

Reputation: 685

Try using following:

$('.container').forEach(function(){ 
    $(this).html().... 
})

If that is your problem that is. Otherwise, please clarify, what exactly isn't working as it is supposed to?

Upvotes: 0

Related Questions