0

I have some javascript code that replaces certain words with a span tag to highlight them with a background color in a tinyMCE element:

var oldContent = 'some sample text',
    newContent = oldContent.replace(/sample|text/g, '<span style="background-color: #ddd;">$&</span>');

The problem is that the text needs to be updated as the user types so the words get replaced over and over with every keystroke ending up in something like this:

<span style="background-color: #ddd;"><span style="background-color: #ddd;"><span style="background-color: #ddd;">sample</span></span></span>

Is there any way to ignore words already wrapped with the span tags? I tried matching for words with whitespace on the sides instead like / sample | text / but it matches the whitespace as well not just the word and if one of the words is last in the content in won't match it unless you end it with a space.

Javier Villanueva
  • 3,526
  • 12
  • 45
  • 74
  • Add the code you have tried. – Shaunak D Jun 04 '14 at 10:41
  • Either change your replace function to check for text that isn't enclosed in your html tags or remove the highlights before adding new ones (using classes for your spans will make both processes easier). – gpgekko Jun 04 '14 at 10:43
  • put `newContent` in dom – Govind Singh Jun 04 '14 at 10:46
  • I though about removing the tags but the problem is that there could be other span tags in there so I can remove the `` part which is kind of unique but iI can't just remove the closing `` because there could be others being used. – Javier Villanueva Jun 04 '14 at 10:47

3 Answers3

0

Your function works correct, the problem was in way that you output result.

var oldContent = 'some sample text',
newContent = oldContent.replace(/sample|text/g, '<span style="background-color: #ddd;">$&    </span>');
$("div").html(newContent);

just look at fiddle - all works well

raskalbass
  • 741
  • 4
  • 18
0

You should use something like jQuery.replaceWith() and replace your TextNodes which are not in spans instead of replacing the innerHTML of the div.

Another possible solution to remove all highlight HTML from the innerHTML, so you will end up with plain text which you can easily replace with your highlight code.

inf3rno
  • 20,735
  • 9
  • 97
  • 171
  • The problem is that the element is a tinyMCE instance (sorry should have said that earlier, just fixed edited the question) so stripping the html will also remove all formatting from the text. – Javier Villanueva Jun 04 '14 at 14:15
  • Did you try to find a tinyMCE plugin which can do the job? – inf3rno Jun 04 '14 at 14:33
  • http://stackoverflow.com/questions/8372284/how-to-highlight-a-given-text-in-tinymce this is a similar question – inf3rno Jun 04 '14 at 14:34
0

Javier, this situation sounds very similar to Match (or replace) a pattern except in situations s1, s2, s3 etc.

With all the disclaimers about using regex to parse html, here is a simple way to do it.

Here's our simple regex:

<span.*?</span>|(sample|text)

The left side of the alternation matches complete <span... </span> tags. We will ignore these matches. The right side matches and captures sample or text to Group 1, and we know they are the right ones because they were not matched by the expression on the left.

This skeleton program shows how to use the regex (see the results at the bottom of the online demo):

<script>
var subject = '<span>dont touch this sample</span> sample text';
var regex = /<span.*?<\/span>|(sample|text)/g;
replaced = subject.replace(regex, function(m, group1) {
    if (group1 == "" ) return m;
    else return "&lt;mybeautifulspan&gt;" + group1 + "&lt;/myspan&gt;";
});
document.write("<br>*** Replacements ***<br>");
document.write(replaced);
</script>

Reference

How to match (or replace) a pattern except in situations s1, s2, s3...

Community
  • 1
  • 1
zx81
  • 38,175
  • 8
  • 76
  • 97