views:

70

answers:

4

How to select a part of string?

My code (or example):

<div>some text</div>

$(function(){
    $('div').each(function(){
        $(this).text($(this).html().replace(/text/, '<span style="color: none">$1<\/span>'));
    });
});

I tried this method, but in this case is selected all context too:

$(function(){
    $('div:contains("text")').css('color','red');
});

I try to get like this:

<div><span style="color: red">text</span></div>
+1  A: 

What are you actually trying to do? What you're doing at the moment is taking the HTML of each matching DIV, wrapping a span around the word "text" if it appears (literally the word "text") and then setting that as the text of the element (and so you'll see the HTML markup on the page).

If you really want to do something with the actual word "text", you probably meant to use html rather than text in your first function call:

$('div').each(function(){
    $(this).html($(this).html().replace(/text/, '<span style="color: none">$1<\/span>'));
         // ^-- here
}

But if you're trying to wrap a span around the text of the div, you can use wrap to do that:

$('div').wrap('<span style="color: none"/>');

Like this: http://jsbin.com/ucopo3 (in that example, I've used "color: blue" rather than "color: none", but you get the idea).

T.J. Crowder
Crowder, you got a silver badge in jQuery but you are still not using the callback function as an argument for html() and similar methods?
Šime Vidas
@Šime Vidas: :-) That first snippet was meant to be a minimum-changes one to point out where the function change was. My primary point was the `wrap` thing anyway, but apparently he wanted the `replace` for something.
T.J. Crowder
+2  A: 
$('div').each(function () {
    $(this).html(function (i, v) {
        return v.replace(/foo/g, '<span style="color: red">$&<\/span>');
    });
});
Šime Vidas
What if an atttribute value contains the string "foo"?
Tim Down
A: 
$(function(){
    $('div:contains("text")').each(function() {
        $(this).html($(this).html().replace(/(text)/g, '<span style="color:red;">\$1</span>'));
    });
});

I've updated your fiddle: http://jsfiddle.net/nMzTw/15/

Peter Kruithof
A: 

The general practice of interacting with the DOM as strings of HTML using innerHTML has many serious drawbacks:

  • Event handlers are removed or replaced
  • Opens the possibility of script inject attacks
  • Doesn't work in XHTML

It also encourages lazy thinking. In this particular instance, you're matching against the string "text" within the HTML with the assumption that any occurrence of the string must be within a text node. This is patently not a valid assumption: the string could appear in a title or alt attribute, for example.

Use DOM methods instead. This will get round all the problems. The following will use only DOM methods to surround every match for regex in every text node that is a descendant of a <div> element:

$(function() {
    var regex = /text/;

    function getTextNodes(node) {
        if (node.nodeType == 3) {
            return [node];
        } else {
            var textNodes = [];
            for (var n = node.firstChild; n; n = n.nextSibling) {
                textNodes = textNodes.concat(getTextNodes(n));
            }
            return textNodes;
        }
    }

    $('div').each(function() {
        $.each(getTextNodes(this), function() {
            var textNode = this, parent = this.parentNode;
            var result, span, matchedTextNode, matchLength;
            while ( textNode && (result = regex.exec(textNode.data)) ) {
                matchedTextNode = textNode.splitText(result.index);
                matchLength = result[0].length;
                textNode = (matchedTextNode.length > matchLength) ?
                    matchedTextNode.splitText(matchLength) : null;
                span = document.createElement("span");
                span.style.color = "red";
                span.appendChild(matchedTextNode);
                parent.insertBefore(span, textNode);
            }
        });
    });
});
Tim Down
Why will innerHTML not work in XHTML?
mplungjan
@mplungjan: I should have been clearer. It won't work with XHTML served as "application/xhtml+xml" (which is the only way a page gets parsed as XML anyway).
Tim Down