0

I have a contenteditable div. I am trying to hunt for the word "design" and wrap it in a span element.

HTML:

<div id="text"></div>

JavaScript:

$("#text").prop("contenteditable", true);
var string = $("#text")[0].innerHTML;
$("#text").innerHTML = string.replace("design", "<span>design</span>");

This doesn't work. My first guess would be that its because the script runs once, so by the time I type "design" it doesn't catch it. So, I tried putting it in a setInterval, but that didn't work either. JSFiddle

Any help would be much appreciated.

Jace Cotton
  • 2,004
  • 1
  • 21
  • 38
  • 1
    possible duplicate of [Wrap certain word with using jquery](http://stackoverflow.com/questions/13259872/wrap-certain-word-with-span-using-jquery) – Mina Gabriel Jan 30 '14 at 19:42
  • You are going to have trouble with this (cursor jumping, wrapping the same text multiple times, etc). It's certainly possible, but seems like more than can or should be tackled in a single StackOverflow question. – gilly3 Jan 30 '14 at 19:46

2 Answers2

2
$("#text").prop("contenteditable", true).keypress(function(e){
    $(this).html(function(i,html){return html.replace(/<span>design</span>/g,"design").replace(/design/g, "<span>design</span>")});
});

I didn't test, but hopefully it'll work.

Scimonster
  • 32,893
  • 9
  • 77
  • 89
  • Thank you, this worked. The only thing is, once I type "design", the caret goes back to the end. I'll figure that out some other way. Thanks again! – Jace Cotton Jan 30 '14 at 19:46
  • Yeah, that's an unfortunate side-effect of replacing the HTML content. Don't forget to mark as accepted. ;) – Scimonster Jan 30 '14 at 19:48
  • this will wrap the word design many MANY times, every time a key is pressed, AND it matches "design", "designs", "designed", etc and breaks it into pieces. – ohmusama Jan 30 '14 at 19:48
  • @Scimonster Will do. It makes me wait 6 minutes. – Jace Cotton Jan 30 '14 at 19:48
  • @ohmusama I fixed the first problem, but not quite sure if the second should be fixed, or how to write the proper regex. – Scimonster Jan 30 '14 at 19:52
  • `replace(/(^|\s+)(design)(\s+|$)/ig, "$2")` ensures it will either start with the beginning of the string or white space, followed by design followed by whitespace or the end of the string, both case insensitive and global replacement (the /i and /g) – ohmusama Jan 30 '14 at 19:55
  • @ohmusama Hmm, complex. :P Is there any reason for putting `design` in parentheses? – Scimonster Jan 30 '14 at 19:56
  • If you really feel it's worth it, you can put it into the answer. – Scimonster Jan 30 '14 at 19:57
  • The design in parenthesis allows you to use the `$2` replacement capture. This means that If he wants to replace more than just design, he only needs to replace the specified word in one location. – ohmusama Jan 30 '14 at 20:50
  • @ohmusama Thank you as well for your help and useful input. Really appreciate it. – Jace Cotton Jan 31 '14 at 15:22
1

You can do it like this

$('#text').prop("contenteditable", true).on('keyup change',function(){
    var $el = $(this);
    $el.find('span').contents().unwrap(); // remove existing spans around "design"
    $el.html(function(i,v){ 
       return v.replace(/\bdesign\b/gi, "<span>design</span>") // wrap design with spans
    });
    setEndOfContenteditable(this); // reset the cursor to the end
});

FIDDLE

the setEndOfContenteditable function was taken from this SO Answer - it sets the cursor back to the end of the text https://stackoverflow.com/a/3866442/1385672

Community
  • 1
  • 1
wirey00
  • 33,517
  • 7
  • 54
  • 65