I am building a web interface for annotating texts. The user should select a portion of the text (using the mouse) and write some side notes about it. When I save the annotation, I need to keep the offsets of the selected text. Note that the text is taken from a TXT file that may include spaces, tabulations, newlines, etc.
Now I put the text into a <pre>
tag and call the Selection object in JS to get the offsets. By using a <pre>
container, I have perfect correspondence between the offsets of the selection and the offsets in the TXT file.
Now I need to add some formatting information on this text (for instance, highlight the portions of text already annotated by other users): if I add some <span>
s with the background color, I mess the information about the selection and the offsets.
Any idea on how to deal with this problem?
$(document).ready(function() {
$("#button").click(function() {
const selection = window.getSelection()
let selectedText = selection.toString()
let startOffset = selection.anchorOffset
let endOffset = selection.focusOffset
console.log(selectedText, startOffset, endOffset)
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<pre id="file-content">This is my text.
I can have spaces and newlines.
Bye!</pre>
<button id="button">
Click me
</button>
This is an interesting problem, since the methods offered by window.getSelection API return selection offset from the innermost tag, we must find a hacky solution.
I suggest having 2 pre tags which the text contents are the same inside. first one is used only as a container which user can select the text from. and second will contain all the span tags used for styling and annotation and etc..
<div style="width:300px; height:300px; position:relative">
<!-- This pre tag is used only for keeping the text as plain portion of text -->
<pre id="userSelection" style="position:absolute;margin:0;top:0;color:rgba(0,0,0,0);">
lorem ipsum, dolor sit amet consectetur adipisicing elit.Sint praesentium, ad repellat fuga consequuntur aut a laboriosam! Deserunt, fugiat aperiam, omnis esse vel, aliquid itaque in tempore sequi voluptatibus consequuntur.
</pre>
<!-- Using this tag you can style the elements-->
<pre style="margin:0;z-index:0;user-select: none;">
lorem ipsum, dolor sit amet consectetur <span style="color:red;">adipisicing</span> elit.Sint praesentium, ad repellat fuga consequuntur aut a laboriosam! Deserunt, fugiat aperiam, omnis esse vel, aliquid itaque in tempore sequi voluptatibus consequuntur.
</pre>
<button onclick="handleClick()">Click here</button>
</div>
If you check the provided code above, second tag in this example contains the span for the word adipisicing
, your JavaScript example will return adipisicing 56 67
which is the correct result.