0

As in the attached image, my goal is to select a text, for instance "Among the Helvetii" and find which element among those of class nMarker was before the selection.

Code with paragraphs and markers

In other words, I’d like to select "Among the Helvetii" and find somehow the element of class nMarker, which has data-marker equal to 1.

Unfortunately I have not a single chance to use jQuery prevAll, prev, closest, etc. as the DOM is unknown, so I can’t count of parents, ancestors, etc. as the marker is placed after a number of words, following an algorithm (it is a requirement I can’t change).

What I achieved so far was to implement this cose, which works if the selection is in the same element where the marker is. But I’d like a solution working without knowing the DOM structure, as I said.

var sel = window.getSelection ? window.getSelection() : document.selection.createRange();
if(sel.getRangeAt){ // That’s for Firefox
    var range = sel.getRangeAt(0);
    var newNode = document.createElement("span");
    newNode.setAttribute('class', 'justSelected');
    range.surroundContents(newNode);

    $(".justSelected").prevAll(".nMarker").data( "marker")
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Fabio Ricci
  • 395
  • 1
  • 4
  • 16
  • At a stab, to give you something to consider: after checking in the current node, loop `$(this).parents()` nodes, run a `.find(".nMarker").last()` on each of those parent, if found then break otherwise continue – freedomn-m Oct 29 '20 at 15:45
  • Is this marker always going to be on the same “ancestor level” as the marked text? What I mean by that, your marked text in the example is in a paragraph, and the marker you are looking for, is inside of a _sibling_ paragraph – or could it be in other, arbitrary locations? Could stuff like `

    …marked text…

    ` or `

    …marked text…

    ` also occur?
    – CBroe Oct 30 '20 at 07:57
  • @CBroe no, the problem is exactly this one. Markers could be anywhere. Unfortunately I have to deal with non standard ePubs, so they can be wherever, so yes, it can occur what you say. Below I posted a possible answer abandoning the HTML/jQuery approach. But it works only if the selection is unique in the html (chapter) file. – Fabio Ricci Oct 30 '20 at 08:28
  • I guess you should start with something like this, https://stackoverflow.com/a/1335347/1427878, to get the element that the current selection is in. Once you have that, it becomes a matter of DOM traversal (loop through previous siblings, check in there, if no marker found, move up to the next common parent element, repeat the process …) – CBroe Oct 30 '20 at 08:34
  • What do you mean by *"cose"* in *"implement this cose"*? – Peter Mortensen Sep 10 '21 at 09:57

1 Answers1

0

With a non-jQuery approach I managed it like this:

var body = $("body").text();
var toFind = window.getSelection().toString();
var strRegEx = '{:(?:(?!{:).)*?'+toFind; 
var res = body.match(strRegEx);
console.log(res);
var regExp = /\{:([^)]+)\:}/;
var matches = regExp.exec(res[0]);
alert(matches[1]);

Anyway this doesn't answer completely the question (I wanted to get the data-marker attribute) but now I get the same number. This works, however, only if the selection is unique in the whole text.

Fabio Ricci
  • 395
  • 1
  • 4
  • 16