4

This question builds on an answer provided in How to wrap word into span on user click in javascript.

In my example, the user can double-click on any word to wrap it in a span element, but b/c this is based on splitting on whitespace, it won't work if the word is followed by punctuation.

HTML:

<div class="color-coding">
  <span class="orange color-coding">Hello world this is some text.</span>
  <br>
  <span class="orange color-coding">Here is some more!</span>
</div>

JS:

jQuery(document).ready(function($) {

$('.color-coding').dblclick(function(e) {

var range = window.getSelection() || document.getSelection() || document.selection.createRange();
var sword = $.trim(range.toString());
if(sword.length)
{

  var newWord = "<span class='highlight'>"+sword+"</span>";

  $(this).each(function(){
      $(this).html(function( _, html ) {
    return html.split(/\s+/).map(function( word ) {
      return word === sword ? newWord : word;
    }).join(' ');
  });
  });
}
range.collapse();
e.stopPropagation();
});

});

I could add punctuation detection for the split, but that would of course remove the punctuation, and I need to retain it, so using the following won't meet my needs:

html.split(/\s+|[.,-\/#!$%\^&\*;:{}=\-_`~()]/)

Fiddle: http://jsfiddle.net/b11nxk92/3/

Community
  • 1
  • 1
allenbell_nc
  • 73
  • 1
  • 8

1 Answers1

0

execCommand

Perfect solution for evergreen browsers:

if(sword.length) {
    this.setAttribute('contenteditable','true');
    document.execCommand("insertHTML", false, "<span class='highlight'>"+sword+"</span>");
    this.removeAttribute('contenteditable');
}

This solution, toggles the container to editable mode, then trigger a command to insert the new html code. See: https://msdn.microsoft.com/en-us/library/hh801231(v=vs.85).aspx#inserthtml and https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand

Fiddle: http://jsfiddle.net/b11nxk92/6/

RegExp

Also, I love RegExp so I made this solution.

if (sword.length) {

    $(this).each(function(){
        $(this).html(function( _, html ) {
            return html.replace(
                new RegExp("([^\\w]|^)("+sword+")([^\\w]|$)","g"),
                "$1<span class='highlight'>$2</span>$3"
            );
        });
    });
}

Instead of using split and then join the regular expression selects three elements (a non word character or the begining) + (our word) + (a non word character or the end) then using $ you choose where to keep it.

Fiddle: http://jsfiddle.net/b11nxk92/4/

Gatsbimantico
  • 1,822
  • 15
  • 32