Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find a string of text in an element and wrap some span tags round it

I want to find a string of text in an element and wrap some span tags round it. E.g.

From:

<h2>We have cows on our farm</h2>

To:

<h2>We have <span class='smallcaps'>cows</span> on our farm</h2>

I've tried:

$("h2:contains('cow')").each(function() {
 $(this).text().wrap("<span class='smallcaps'></span>");
});

But that only wraps the whole containing h2 tag.

like image 352
Seb Avatar asked Apr 18 '13 18:04

Seb


4 Answers

$("h2:contains('cow')").html(function(_, html) {
   return html.replace(/(cow)/g, '<span class="smallcaps">$1</span>');
});

http://jsfiddle.net/w5ze6/1/

like image 178
undefined Avatar answered Oct 20 '22 06:10

undefined


Another approach, split by keyword and join with the updated html.

$("h2:contains('cow')").html(function(_, html) {
   return html.split('cow').join("<span class='smallcaps'>cow</span>");
});

Note: I haven't tested this, but I'm assuming this would perform worse than doing a replace, but figure I would include anyways for informative purposes

like image 25
Justin Bicknell Avatar answered Oct 20 '22 07:10

Justin Bicknell


Here is a variation on @undefined's answer, which loops through an array of items:

var barnyardArray = [
    'cow',
    'horse',
    'chicken',
    'hog',
    'goat',
    'goose',
    'duck',
    'llama'
];

$.each(barnyardArray, function (index, value) {
    $("p:contains(" + value + ")").html(function (_, html) {
        var regex = new RegExp(value, 'g');
        return html.replace(regex, '<span class="smallcaps">' + value + '</span>');
    });
});
like image 4
J7stin Avatar answered Oct 20 '22 07:10

J7stin


You usually want to match some arbitrary text in a case insensitive way. Sometimes, search queries contain characters that are special regex metacharacters and must be escaped before compiling the pattern.

Use a solution like

var words = ["cows", "c++", "$var$"];
$("h2").html(function(_, html) {
   return html.replace(new RegExp(words.map(function(x) { 
       return x.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')
     }).join('|'), "gi"), '<span class="smallcaps">$&</span>')
});
span { color: red}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h2>We have cows on our farm</h2>
<h2>C++ Apps $var$</h2>

Note that here, a regex will look like /cows|c\+\+|\$var\$/gi, where + and $, special regex metacharacters, are escaped, and the alternatives are ORed with the | alternation operator.

Also, note that there is no need of any outer parentheses as the default group is Group 0 that holds the whole match, and the backreference to Group 0 in JavaScript regex is $&. Thus, the replacement is always done with the search word in the exact case as it was found in text.

Note that in case you need to match whole words only, you would need special boundaries, either \b (if the search words always consist of letters, digits or _) or (\W|^) / (?!\w) (if there can be special characters):

var words = ["cows", "c++", "$var$"];
$("h2").html(function(_, html) {
   return html.replace(new RegExp("(\\W|^)(" + words.map(function(x) { 
       return x.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')
     }).join('|') + ")(?!\\w)", "gi"), '$1<span class="smallcaps">$2</span>')
});
span { color: red}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h2>We have cows in our farm cowshed</h2>
<h2>C++ Apps $var$ in $var$moretext</h2>
like image 2
Wiktor Stribiżew Avatar answered Oct 20 '22 07:10

Wiktor Stribiżew