I am using Rangy Library for highlighting text. When I use the following code, it simply add a span tag with the class note if there are no tags and while I am selecting the whole text in between a span tag it simply assign that class to the existing tag using highlighter.highlightSelection("note");
.
Now my requirement is, rather than highlighting the selected text, i need to highlight the whole text of its parent node. As you can see in the following snippet, I am having a span tag with s-class sentence which is again made of using one or multiple child span tag. Now I want, if user select some text from the child span tags than the parent tag with attribute s-class=sentence should be highlighted. If user is trying to select the text across the multiple parent span tags then all the parent tags affected with this selection should be highlighted.
<p>
<span s-class="sentence">
<span>Contrary to popular belief, Lorem Ipsum is not simply random text. </span>
</span>
<span s-class="sentence">
<span>It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. </span>
</span>
<span s-class="sentence">
<span>Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. </span>
</span>
<span s-class="sentence">
<span>Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. </span>
</span>
<span s-class="sentence">
<span>This book is a treatise on the theory of ethics, very popular during the Renaissance. </span></span>
<span s-class="sentence">
<span>The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet.."</span><span >, comes from a line in section 1.10.32.</span>
</span>
</p>
Use case 1 => User selected the test from first span only "popular belief, Lorem", then the highlighted html should be -
<span s-class="sentence" class="note">
<span>Contrary to popular belief, Lorem Ipsum is not simply random text. </span>
</span>
Use case 2 => If selects from two or more spans(first and second) "random text. It has roots" then the resultant highlighted html should be -
<span s-class="sentence" class="note">
<span>Contrary to popular belief, Lorem Ipsum is not simply random text. </span>
</span>
<span s-class="sentence" class="note">
<span>It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. </span>
</span>
Use case 3 - If user select some text across multiple child elements inside a parent tag with attribute s-class-"senetence" then only that parent tag needs to be highlighted. i.e. user selects "sit amet.., comes" then the resultant HTML should be -
<span s-class="sentence" class="note">
<span>The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet.."</span><span >, comes from a line in section 1.10.32.</span>
</span>
I am converting this HTML from a Word document and then making the sentences so I wants to select all the affected sentences by the selection not only the highlighted text.
Also when I unhighlight it then the selection should be removed from these parents spans.
This should work for you.
var selection = rangy.getSelection();
if (selection.rangeCount > 0) {
var range = selection.getRangeAt(0);
var startNode = $(range.startContainer).closest("span[s-class=sentence]");
var endNode = $(range.endContainer).closest("span[s-class=sentence]");
$(startNode).addClass("selectionstart");
$(endNode).addClass("selectionend");
var rangeSel = $('span').rangeSelector();
if(rangeSel!==undefined && rangeSel.length>0){
$(startNode).addClass('note');
$(endNode).addClass('note');
rangeSel.addClass("note");
}}
//jquery extension method
$.fn.rangeSelector = function (options) {
var settings = $.extend({ startClass: 'selectionstart', endClass: 'selectionend' }, options || {});
var name = 'span';
var startNode = name + '.' + settings.startClass;
var endNode = name + '.' + settings.endClass;
var parentNode = $(startNode).parent().closest("p");
var startIndex = parentNode.find(startNode).index();
var endIndex = parentNode.find(endNode).index();
if ((startIndex === endIndex) || (endIndex === startIndex+1))
return $('<span />');
if (endIndex < 0)
return undefined;
var result = $(startNode).nextUntil(endNode);
return result;
}