Search code examples
jquerydomselectionrangy

Rangy calculate deserialized positions after adding content to the DOM above the rangy highlightable div


I have a div containing other div elements and text elements.

I use Rangy Highlighter to highlight text in the base div. I use highlighter.highlightSelection("classApplier1") to highlight the selected text.

After ending the web session I store the changes applied to the div using

  var serializedValue = highlighter.serialize("classApplier1");

After I open a new web session (or by pressing refresh), I use

highlighter.deserialize(serializedValue);

to obtain the highlights again.

This works like a charm if the html source does not change between different web sessions. Since the base div is integrated in another web page and does not have a page by itself a lot of elements can be added above (or maybe below) the base div in the html source. This leads to the deserialize method not working anymore or it basically shifts the highlights, because it works with positions that change relative to where in the html source the highlight takes place.

An example for a serialized highlight value looks like this

"type:textContent|3942$3949$8$classApplier1$"

I need to be able to change thoose stored values (here 3942 and 3949) based on the position of the base div.(which might change between web session if webpage gets updated for example).

How do I get the base div position in the html source in the same way rangy does it and how should i compute the new position values based on that new position


Solution

  • This is a very old question but i got an upvote today so I am answering as i think I solved it.

    The problem I had is that I had a text in the html and I needed to find the first index of that text. This is the approach I took:

    1- Once I arrived in a page, I highlighted the whole div that contains my text(the base div). I serialized it and in the serialized string say

    "type:textContent|1400$3949$8$classApplier1$"
    

    contained the base number (which is 1400). So basically the first character in my text is the character 1400 in the html. So 1400 become my base integer.

    2- To store a serialized string i always removed 1400 from it(from the start and the end) and then stored it.

    So in my database if I am highlighting the first 30 characters. I would get as a deserialized string :

    "type:textContent|1400$1430$8$classApplier1$"
    

    I would store (first:0 , last:30)

    3- Upon retrieving the stored numbers (from say a database) in a new html source, I calculated the base number of the new html (say now its 1450 because i added another javascript file reference) and finally added the base number to the retrieved stored numbers(also to the first and last number)

    "type:textContent|1450$1480$8$classApplier1$"
    

    The highlighting and "dehighlighting" of the whole div in the first step happens so fast that it is not visible to the user.