Henrik Petterson Henrik Petterson - 7 months ago 18
Javascript Question

jQuery issue when .find() term in variable with more than one match

My aim is to let the user select text with the cursor and output the selection into a different div with the highlighted text in

<span>
tags.

So, I have the selection set like this:

var sel = jQuery.selection();


And then I wrap the selection into
<span>
and output it:

var $title = jQuery(this).parent().find('.title').text();
var $result;
$result = $title.replace(sel, '<span>'+sel+'</span>');

// output result
jQuery(this).parent().find('.output').html($result);


It works fine.

The problem is that if the text contain the same term twice and the user selects the second term, it will find and replace the first term.

For example, random text:

hello world lorem ipsum hello


If user selects the second
hello
, it will wrap the first one.

Is there a solution to apply to solve this type of scenario?

jsFiddle for testing.

Answer

Get the offset from which you can start replacing ...

$('button').click(function() {
  var sel = jQuery.selection();
  var $title = jQuery(this).parent().find('.title').text();
  var $result;
  var highlightFrom = window.getSelection().anchorOffset;


    $result = $title.substr(0,highlightFrom) + $title.substr(highlightFrom, $title.length).replace(sel, '<span>' + sel + '</span>');


  // output result
  jQuery(this).parent().find('.output').text($result);
});

In your sample, highlighfrom gives 24 when selecting second hello.

Updated Fiddle

AnchorOffset is supported by IE9+ and other major browsers. If you need a valid alternative, I refer to Rangy as stated here: AnchorOffset alternative

See here for more info on textselection ranges and browser compatibility

TESTED - Chrome, IE11+, FF