Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inability to type next to or past custom Embed blot (with contenteditable=false) #1172

Closed
danielschwartz opened this issue Dec 8, 2016 · 23 comments

Comments

@danielschwartz
Copy link

I am trying to create a custom Embed blot that will allow our users to mention other users (a la GitHub), however treat the entire username as a single entity (hence why I am using Embed and not Inline) so that if a user backspaces in front of it, it deletes the entire user name and not just a single character of it.

While I am able to correctly create the UserMention embed in a Quill document, it causes a multitude of problems with cursor positioning, selection states, and the ability to type, especially if the UserMention embed is at the end of a document.

Steps for Reproduction

  1. Visit http://codepen.io/anon/pen/dOKqEN
  2. Try to move cursor past UserMention embed by using both arrow keys and clicking past it (two different errors occur)

Expected behavior:
User should be able to type content before or after UserMention embed blot

Actual behavior:
If moving cursor by touching arrow keys, cursor will get stuck when trying to move next to or past UserMention blot. Cursor will also sometimes disappear. Rarely, it's possible to actually have two cursors visible at once.

Additionally on Quill@v1.1.6: Try to move the cursor past the UserMention blot will cause the editor window to scroll jump well past the content

Platforms:
Latest Chrome OSX

Version:
1.1.6 (also occurs on 1.1.5)

@cutteroid
Copy link

cutteroid commented Dec 9, 2016

Its not a quilljs bug, its browsers failure. All current browsers having different issues handling contenteditable="false" nodes inside of contenteditable="true" container.

In our project we developed similar functionality (custom blocks and nodes which users cannot edit inside of quilljs) and those cursor and selection problems driven me nuts.

Some kind of solution we used - tracking of cursor position. If cursor found in bugged area (in general: before non-editable which is first element in line, after non-editable which is last element in line, between two adjacent non-editables) insert there quilljs cursor blot or another zero-width filler node.

@danielschwartz
Copy link
Author

@cutteroid thanks for pointing me in the right direction. Good to know that I may have to solve these issues myself and then back port them into Quill.

Any chance you have an example of how you've handled issues like the one i'm describing? Still wrapping my head around the beast that is contenteditable and any examples would be much appreciated.

@cutteroid
Copy link

@danielschwartz

example
Beware! It is a big pile of shitcode written with "it's only a prototype. will rewrite it later" in mind :)

@danielschwartz
Copy link
Author

@cutteroid good to know :). I'm sure it will be useful either way. Really appreciate you helping shed some light on all these selection issues!

@ivanalejandro0
Copy link

@danielschwartz I've encountered the same issue, hopefully, there's a workaround :)

Basically, the problem is that when you add text right after (and sometimes right before) a blot, you are not editing the block next to the blot but the blot itself (which you marked as readonly).

e.g.

Where "it seems" the cursor is:
<div>Here is my <span contenteditable=false>read only blot</span>|</div>

Where the cursor actually is:
<div>Here is my <span contenteditable=false>read only blot|</span></div>

I couldn't get the contenteditable=false approach working, it turned out to be a bit difficult to handle in some cases, and, most important for my use case, it produces different behaviors on different platforms.

What I had to do to workaround this problem is to leverage the update function of the blot and handle prepends (typing right before the blot), appends (typing right after the blot), and text replacements (like using spell suggestions on the phone or Ctrl+Backspace deleting words) with different code.

Basically, instead of using a non-editable Blot I created a sort of immutable one.

Here you have a working example: http://codepen.io/ivanalejandro0/pen/LbyNYW , it is a big portion of the code I'm using which includes handling of several edge cases. I hope this is useful for you.

@jhchen jhchen added the triage label Dec 22, 2016
@Wattos
Copy link

Wattos commented Jan 28, 2017

@cutteroid I have also ran into the issue. In the past (with CKEditor) I have just inserted a zero width space after the blob (​) to fix the issues. This actually worked quite well!

Do you think it would be possible to insert a zero width space ​ if the cursor is exactly after or before the blob?

@thienanle
Copy link

@Wattos how were you able to insert a zero width space after a blob?

@jhchen
Copy link
Member

jhchen commented Jul 17, 2017

This has been fixed in 1.3.0.

@jhchen jhchen closed this as completed Jul 17, 2017
@rywall
Copy link

rywall commented Jul 19, 2017

@jhchen Are you sure this is fixed? I updated the example to Quill 1.3.0 and it still exhibits the same behaviour. I can't use the arrow keys to move past the EmbedBlot and then start typing.

https://codepen.io/anon/pen/MoMrva

@BrockReece
Copy link

I too am using 1.3.0 and am still experiencing this issue.

I don't know if this is of use to anyone but the workaround that I am using is adding an additional space after the embed and then setting the current selection to be after that space.

const range = editor.getSelection();
editor.insertEmbed(range.index, 'shortcode', `{{ $${val} }}`);
editor.insertText(range.index + 1, ' ');
editor.setSelection(range.index + 2, Quill.sources.SILENT);

@jhchen
Copy link
Member

jhchen commented Jul 21, 2017

It is fixed with a new InlineEmbed blot but the default export is still Embed: https://github.com/quilljs/quill/blob/develop/blots/embed.js. I'll switch this over but in the meantime if you build Quill you can import InlineEmbed instead.

To observe the fixed behavior take a look at formula on the homepage of https://quilljs.com. It used to use the space workaround like @BrockReece suggested but should not be necessary anymore.

@kay999
Copy link

kay999 commented Aug 2, 2017

Is there a way to use InlineEmbed with the npm module now?

@jhchen
Copy link
Member

jhchen commented Aug 7, 2017

InlineEmbed will be converted to the default Embed as soon as 1.3.1 is released (commit is already in develop).

@brianbest
Copy link

Hey, @jhchen I'm facing a similar problem here in 1.3.2. I tried running the example code that @danielschwartz provided running the latest version of Quill and I noticed that it's also showing the same issue as described in the ticket. Would you have any words of wisdom of how the example could be fixed?

Here's my fork running on 1.3.2
https://codepen.io/brianbest/pen/mBEGQV

@jhchen
Copy link
Member

jhchen commented Sep 21, 2017

The setting contenteditable to false needs to be removed in create(). The native embed already has sets the contents to be contenteditable to false and this additional call is defeating the cursor workaround the fix added.

@brianbest
Copy link

Boom! That's great thank you @jhchen !

@petahbred
Copy link

@ivanalejandro0 I appreciate the example. Any idea how you would go about replicating your example for ^1.3.5, it doesn't seem to work with the latest version.

@ivanalejandro0
Copy link

@petahbred yeah, I've forked my previous example into a new one that works with the current latest quill version (1.3.6 as today).
https://codepen.io/ivanalejandro0/pen/GdOBjQ

Some caveats:

  • it works differently than the previous one, there's no blot to text conversion since that was part of the workaround of the blot not being immutable previously.
  • the code is much shorter since there's no longer need to handle blot mutations thanks to the new non editable blot and the "guards" around it that handles changes.
  • there's a workaround on the update() function to handle an android bug using gboard (I think it could be Can't delete embed blots on android #1985)

@minwe
Copy link

minwe commented Jun 26, 2019

@danielschwartz

example
Beware! It is a big pile of shitcode written with "it's only a prototype. will rewrite it later" in mind :)

@cutteroid Excuse me? What is zEditor.fixCaret()?

@smellyshovel
Copy link

@ivanalejandro0 thank you very much for sharing!

@Filipeue
Copy link

Filipeue commented Oct 12, 2020

Why is this issue closed? It is not resolved, besides workaround created by @ivanalejandro0
Even the the example on quill homepage (video blot) doesn't work properly... placing cursor before video and deleting will remove video. @jhchen

@jialulu0829
Copy link

The setting contenteditable to false needs to be removed in create(). The native embed already has sets the contents to be contenteditable to false and this additional call is defeating the cursor workaround the fix added.

Hi,@jhchen I followed what you said and made modifications based on the code of @brianbest. Indeed, the cursor displayed normally and could be entered, but when I entered a word after Blots, the first letter would appear twice, for example:
屏幕快照 2024-11-06 下午5 24 08
Didn't anyone else encounter this problem?

@jialulu0829
Copy link

#1904 same issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests