adding a badge without modifying the ability to select text

I work with an annotation tool. We’ve had a user request to display badges next to the annotated text. The answer on this previous discussion was not quite sufficient.

Background

Originally, a style-only solution worked for us when we were underlining our marked up ranges. However, now that we need to add something inline (at the end of the TextMarker), the splitting of the spans while highlighting creates more elements than we want to style. Example for the input string of Bilbo Baggins is a hobbit in a book by J.R.R. Tolkien when the user has highlighted book by J.R.R. and we have annotated Bilbo Baggins and J.R.R. Tolkien:

<pre class=" CodeMirror-line " role="presentation">
    <span role="presentation" style="padding-right: 0.1px;">
        <span class="person">Bilbo Baggins</span>
          is a hobbit in a 
        <span class=" CodeMirror-selectedtext">book by </span>
        <span class="person CodeMirror-selectedtext">J.R.R. </span>
        <span class="person">Tolkien</span>.
    </span>
</pre>

Here we wish to only style elements with Bilbo Baggins and Tolkien with an :after css rule. We can not use .person because it would select J.R.R. We also can not use .person:not(.CodeMirror-selectedtext) because the case also exists where a user highlights one of the people completely. Sibling based rules have not worked either because multiple marked up regions can share the same parent. I’ve come to the conclusion that this is not possible with style alone.

addWidget

addWidget is almost sufficient. The problem with this approach is that custom HtmlElements that are inserted can obstruct the other text. For the same reasons that a style-only approach above hasn’t worked, I don’t think it would be easy to create the space for the badge.

markText

Using markText with the replacedWith option also is almost sufficient. We insert an element that looks something like this:

<span class="person">Bilbo Baggins<span class="badge">Human</span></span>

And CodeMirror renders this:

<pre class=" CodeMirror-line " role="presentation">
    <span role="presentation" style="padding-right: 0.1px;">
        <span class="CodeMirror-widget" role="presentation">
            <span class="person">Bilbo Baggins
                <span class="badge">Person</span>
            </span>
        </span> is a hobbit in a book by  
        <span class="CodeMirror-widget" role="presentation">
            <span class="person">J.R.R. Tolkien
                <span class="badge">Person</span>
            </span>
        </span>.
    </span>
</pre>

The problem with this approach is that the text inside the CodeMirror widget becomes unselectable. We still need the user to be able to select any range of text, widget or not, because our application renders a menu with available actions determined by their selection.

Do you know of any tweaks to the above partial solutions that could work? Thanks in advance.

I don’t understand all that well what you want to do here, but does using both markText to style the text and setBookmark to put a widget after it not work?

1 Like

That does, thank you!