I am struggling to find a solution to this. My searches usually end with people saying, it's a very complicated matter -- but don't really offer insight in achieving it.
Take for example the following HTML
<p>
This is a test, blah blah,
</p>
<p>
Category: HVAC
</p>
<span>
<br />
Location Address:
<br />
<span>123 Main St</span><i>,</i> New York, NY 10001
</span>
When rendered looks something like this
This is a test, blah blah,
Category: HVAC
Location Address:
123 Main St, New York, NY 10001
If a user selects the phrase "New York", I would like to have a javascript routine that gives me 2 outputs:
Preceding character: ','
Following character: ','
Or, if a user selects the phrase "York", I would like to have a javascript routine that gives me 2 outputs:
Preceding character: 'w'
Following character: ','
In essence, given a users browser selection, I'd like to get the first non-white space character prior to their selection and after their selection.
In simple cases, if the text selection is contained to a single html element; this is seemingly a trivial matter by converting the "containing" textnode into an array of characters and looping to get the desired results.
But when text selections span different HTML elements (like the first input/output example above), I am getting dizzy on figuring it out.
I've tried using libraries like rangy -- but they don't seem to offer much help in solving the multi-range selection example.
I've tried wrapping every "word" with a span (https://stackoverflow.com/a/66380709/14949005), so that I could then use jquery to navigate with prev/next to the element in question -- but the regex in that answer considers "York," a whole word -- therefore leaving me with "N" as the following character.
Update 1
Example of what I tried was requested. This only semi works for the second input/output example above. E.g., select "York", and it will give two characters as the output (but the "following" character will be wrong). And if you select "New York" as a whole, it just fails.
$(document).ready(function () {
var content = $("#content")[0];
var htmlStr = content.innerHTML;
htmlStr = htmlStr.replace(/(?<!(<\/?[^>]*|&[^;]*))([^\s<]+)/g, '$1<span class="word">$2</span>');
content.innerHTML = htmlStr;
$("#add").click(function () {
var firstRange = window.getSelection().getRangeAt(0);
var precedingWord = $(firstRange.startContainer.parentNode).prev(".word")[0].innerText;
var followingWord = $(firstRange.startContainer.parentNode).next(".word")[0].innerText;
alert(precedingWord[precedingWord.length-1]);
alert(followingWord[0]);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="field-controls">
<button id='add'>Run</button>
</div>
Select some text below and press "Run" to see preceeding/following character of selection
<div id="content">
<p>
This is a test, blah blah,
</p>
<p>
Category: HVAC
</p>
<span>
<br />
Location Address:
<br />
<span>123 Main St</span><i>,</i> New York, NY 10001
</span>
</div>
Thank you,