Let's say I want to have an AtomicText
blot that is similar to the default Link
blot but is immutable and can only be removed as a whole. More specifically:
AtomicText
.AtomicText
.AtomicText
leads to the deletion of the whole AtomicText
.AtomicText
is not possible once it has been created. Neither via keyboard events nor via copy and paste.My idea was to make AtomicText
extend from the Embed
blot. In that case, the whole AtomicText
blot is deleted when the cursor is right to its last character and backspace is pressed. But other operations do not work as expected. I assume I need to override some of the Blot
methods to achieve the correct behavior but I am a bit at loss here.
Another idea is to listen to text-change
events, determine if the cursor is inside an AtomicText
blot and act accordingly. E.g., when pressing backspace, find the start and end position of the current AtomicText
blot and remove all characters between these indexes. This seems to be a fragile approach.
Any pointers would be appreciated.
Similar questions/requests are the following:
I my experience setting contenteditable
false is problematic. If you position the AtomicText
blot at the end of the document you will not be able to append to it. Additionally, moving the cursor over the AtomicText
positioned at the end will blur the editor.
I experienced a similar issue with a footnote blot. It's a sup
tag that contains [\d+]
and we don't want editors to modify the footnote but we do want them to be able to seamlessly move the cursor through them.
I have experimented with two other options in addition to the text-change
listener mentioned by the OP. The first option is to attempt to position the cursor (via setSelection
) in front or behind using selection-change
event listeners. I found this to be problematic because it's possible to sneak characters in before the selection change event fires. I'm also not a fan of this approach because it causes the cursor to jump across the footnote. YMMV
Another option is to intercept keyboard input. You can add a keyboard listener (I used KeyboardJS) in a module that's initialized with quill. If the current selection is "inside" of your atomic text you can stop the input from proceeding to quill using e.preventDefault()
. With this approach you'll also have to provide custom keyboard handlers in your quill configuration to override tab, enter, and possibly delete. Tabs are more of a challenge because there's a default tab handler provided by quill that takes precedence unless you override it. Within the custom handler you'll have to detect if the context
is within your AtomicText
. The context
object will contain contain a format
map that contains atomictext
(your blot name) if it's in the context of AtomicText
.
Note that if the user positions the cursor adjacent to your AtomicText
, then from quill's perspective that's in the context of AtomicText
. Our solution to that problem for input is to insert a zero width non breaking space, then allow the keyboard input to proceed. That "breaks" the cursor out of the AtomicText
blot allowing insertion to proceed as expected. We then strip those characters out of the resulting HTML before saving the text.
Hope this helps.
In the blot create(value) function, add this:
node.setAttribute('contenteditable', false);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With