There are two ways to obtain a character (and its corresponding position) within the text of an element under the mouse cursor. The first method involves enclosing each character in a <span>
or another element, and adding a click event handler to the <span>
element. The second method utilizes the functionalities of the Range
object, which is supported only by pure JavaScript. Personally, I prefer the first approach due to its efficiency. Using the Range
method necessitates looping each time a click occurs, potentially leading to performance issues when dealing with large texts. For creating a virtual caret, you can generate an inline-block element and visually represent the caret using techniques like borders with linear-gradient backgrounds or even a transparent PNG image. By adjusting margins (both negative for left and right), you can bring text closer together on both sides. Below is the detailed code:
HTML:
<div class='inter-letters'>Click on one of the characters ...</div>
CSS:
.v-caret {
width:.5em;
height:1em;
border-top:1px solid currentColor;
border-bottom:1px solid currentColor;
background:linear-gradient(to right, transparent .23em, currentColor .25em, transparent .27em);
display:inline-block;
vertical-align:middle;
margin:0 -.2em;
display:none;
}
.inter-letters {
font-size:30px;
color:green;
}
JS:
$('.inter-letters').on('click','span.letter', function(){
virtualCaret.css('display','inline-block');
$(this).after(virtualCaret);
}).html(function(i,oldhtml){
return oldhtml.replace(/./g,"<span class='letter'>$&</span>");
});
var virtualCaret = $('<div>').addClass('v-caret').appendTo('.inter-letters');
//clicking outside the div should hide the virtual caret
$(document).click(function(e){
if(!$('.inter-letters').has(e.target).length) {
virtualCaret.css('display','none');
}
});