'How can I select text between anchors and highlight them as such?

I have some HTML that looks roughly like this:

<div>
    <p>Herp derpsum sherper herpy derpus jerpy berps cerp terpus.
        Derpy merpus <a name="a1start" type="start"></a>pee derpler berps! Perp
        sherper herp terp herpy derpler.</p>

        <p>Sherper merp herpler herp pee. Derpler terpus, mer re berp
            der perp se?<a name="a2start" type="start"></a> Ze ter derps tee! Herpsum derp
            sherper ler merp derperker <a name="a3start" type="start"></a>jerpy derpler
            herderder zerpus.</p>
</div>
<div>
    <p>Derp sherper perper tee. Derperker
        zerpus ner cerp terpus herpy sherpus sherp. Perp derp pee serp herp
        zerpus herpem herderder derpler berp! Merpus derpy <a name="a1end" type="end"></a>
        herpler sherp derps perper derperker derp dee der. Merpus der
        derps, <a name="a2end" type="end"></a>derpus herpderpsmer! Derp merp er sherpus dee perp herpy derpsum
        perper pee. Herpler derpsum me sherlamer ler derpler derpy. Cerp de
        perper derpy. Le herderder herpler re ter. Serp ze derperker re. Terp
        berps terpus ter, er perp derpsum. </p>
<a name="a3end" type="end"></a>
</div>

In other words, anchors used to mark starts and ends of highlighted areas. They are irrespective of their locations in <div> or other containers. The highlights are overlapping, thus a1start corresponds to a1end.

I'm trying to figure out a way to highlight them, going from start anchors to end anchors, and ignoring all the HTML in between. So, one highlight from a1start to a1end. Another, overlapping highlight from a2start to a2end, and so on.

Note again that these are overlapping, so I can't just use spans, because then how would a given </span> know that it's the end of, e.g., a2 rather than a closer one at a1?

In other words, think of this structure:

<highlightA>
Here is something highlighted in A.
<hightlightB>
Here is something highlighted in A and B. 
</hightlightA>
Here is something only highlighted in B. 
</hightlightB> 
Here is something not highlighted.

I would usually just transform these <a> tags to <span> and </span>, and then highlight them with CSS: span { background-color: yellow }. But that would produce overlapping tag sets, no? Which is illegal in the HTML/XML world?

So I need to use JavaScript to identify these markers, figure out which ones match, and highlight those spans of text, without trying to edit the HTML. In other words, I need to overlay some highlighting on top of the page, without messing with this markup.

I'm a JavaScript beginner, so go easy on me, please.

Edit: Here's a Codepen I put together which illustrates this problm a little better, and tries to implement the (non-working) solution below. It uses different highlight colors to show how the overlapping highlights aren't working.



Solution 1:[1]

The Class Applier Module of the Rangy Library solves exactly this kind of problem.

demo

Solution 2:[2]

You are correct in the fact that in order to solve your issue, your closing tag needs to match the opening tag. I have been looking around, and certainly, I don't think you can add attributes to the closing tag to make a pair with the opening one. So, why not make your own tag?

I present to you this very simple code

The code is purely just HTML and CSS as you will see here.

<test1>Lorem ipsum dolor sit amet, <test2>Nam at quam euismod, </test2>commodo nibh vitae,</test1>

I think there might need some JS to work on other machines depending on this guide. However, I don't need to do that one for this to work (you can check the JS tab in the codepen). I think you would want to do this if you are planning to use some functions provided by the browser for the original tag (look for extending original tag in the guide).

I'm not so good with CSS and color blending too so I have skipped that part, but I think you can work on that issue on your own. In my code, the test2 color will override the test1 completely.

That's all. Feel free to comment if you need anything else explained :D

Solution 3:[3]

This works in Firefox, and possibly other browsers (I haven't tested).

It's beautifully simple, requiring only a single css rule applied to a class added to your 'start' anchors.

In the working snippet I've added a class attribute named "open" to just the start anchors, and a corresponding style rule to css.

The reason why this doesn't break the document tree is explained as I understand it, below.

a.open {
  background: yellow;
}
<div>
    <p>Herp derpsum sherper herpy derpus jerpy berps cerp terpus.
        Derpy merpus <a name="a1" type="start" class="open"/>pee derpler berps! Perp
        sherper herp terp herpy derpler.</p>

        <p>Sherper merp herpler herp pee. Derpler terpus, mer re berp
            der perp se?<a name="a2" type"end"/> Ze ter derps tee! Herpsum derp
            sherper ler merp derperker <a name="a3" type="start" class="open"/>jerpy derpler
            herderder zerpus.</p>
</div>
<div>
    <p>Derp sherper perper tee. Derperker
        zerpus ner cerp terpus herpy sherpus sherp. Perp derp pee serp herp
        zerpus herpem herderder derpler berp! Merpus derpy <a name="a4" type="end"/>
        herpler sherp derps perper derperker derp dee der. Merpus der
        derps, derpus herpderpsmer! Derp merp er sherpus dee perp herpy derpsum
        perper pee. Herpler derpsum me sherlamer ler derpler derpy. Cerp de
        perper derpy. Le herderder herpler re ter. Serp ze derperker re. Terp
        berps terpus ter, er perp derpsum. </p>
</div>

I discovered it by examining the document tree interpreted from your html in the browsers developer tools. It turns out (in Firefox at least) the browser adds discrete closing tags </a> to any self-closing versions (.../>) written in the html document. Moreover, as it doesn't know where the self-closing anchor is due to end, it adds an end tag before any other html elements that would 'break' it and, cruicially, applies a duplicate opening anchor of the same name to the next html element, immediately after it's opening tag and closing it again before any further tags that would break it. Thus, the browser is duplicating the last self-closing anchor to every part of the tree until a new anchor replaces it.

This allows you to add a class to just the anchors where you want a style to begin (it will end automatically when an anchor without that class is encountered - so only put them in anchors 1, 3, etc.)

In case this doesn't work for users of other browsers, here's a screen shot of the result in Firefox.

screen shot showing output in Firefox

If your browser doesn't make the same interpretation, I'd urge you to examine the document tree in browser tools to determine how the self-closing anchor is applied and got from there.

After the fundamental changes to the question, I reworked the principle described here with minor modifications to achieve overlapping styles across element boundaries, determined by the anchors as per the question. Screen shot of result:

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Knight Industries
Solution 2 Tree Nguyen
Solution 3