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

Keep the cursor position in the Classic Block #12393

Closed
wants to merge 2 commits into from

Conversation

azaozz
Copy link
Contributor

@azaozz azaozz commented Nov 28, 2018

Fixes #10509.

  • On blur store the cursor position and the "raw" content of the Classic Block.
  • Use the "raw" content when refreshing the editor content on componentDidUpdate(). It contains the cursor position "bookmark".
  • Restore the cursor position on focus and before inserting content.

- On blur store the cursor position and the "raw" content of the Classic Block.
- Use the "raw"  content when refreshing the editor content on `componentDidUpdate()`.
- Restore the cursor position on focus and before inserting content.
@azaozz azaozz added the [Block] Classic Affects the Classic Editor Block label Nov 28, 2018
@azaozz azaozz added this to the 4.6 milestone Nov 28, 2018
const editor = window.tinymce.get( `editor-${ clientId }` );
let { contentRaw } = attributes;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

contentRaw is not persisted, we should probably use "local state" for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, sure, that'd work even better :)

Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use some e2e test for the classic block :)

Needed when the first thing the user does after adding a Classic Block is to open a modal that inserts something, like the media modal.
setAttributes( {
contentRaw: editor.getContent( { format: 'raw' } ),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Storing the raw content without any processing seems like a bad idea? Why should this be different from the classic editor?

editor.on( 'init', () => {
// Store the initial "raw" content.
setAttributes( {
contentRaw: editor.getContent( { format: 'raw' } ),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't expect merely initialising the block to change the content. The user didn't do anything.

const editor = window.tinymce.get( `editor-${ clientId }` );
let { contentRaw } = attributes;

// Strip white space before comparing to avoid resetting the editor content when not necessary;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What kind of whitespace is different?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only differences I'm seeing are in some <p>\u00a0</p> and some ; missing/being added to ends of inline style attributes.

@azaozz
Copy link
Contributor Author

azaozz commented Nov 29, 2018

Looking more at this, still can't figure out what the refresh code in componentDidUpdate() is supposed to do:

const { clientId, attributes: { content } } = this.props;
....
if ( prevProps.attributes.content !== content ) {
	editor.setContent( content || '' );
}

Seems at some point it was possible that attributes.contend was changed/updated outside the editor, but that doesn't seem to be the case now. Perhaps this is a "left over" from how undo/redo was working previously?

Even if this is still needed, don't think that looking at prevProps.attributes.content is a good way to determine what's in the editor at that moment. It needs to do editor.getContent().

@iseulde @aduth any chance you could remember what was the purpose of the above code? I know, it's been there for over a year...

@ellatrix
Copy link
Member

To me, this is an interesting thing that happens in master:

  1. Load a classic block with some text. Place the caret somewhere other than the start.
  2. Click the media button in the toolbar.
  3. Select an image.
  4. Close the media modal. Do not insert it!
  5. Place the caret back where it was (somewhere other than the very start).
  6. Click the media button in the toolbar.
  7. The image you selected last time will already be selected. Do not click it again!
  8. Insert the already selected image.
  9. The image is correctly inserted.

This means that clicking the image specifically is causing the focus loss?

@ellatrix
Copy link
Member

Seems at some point it was possible that attributes.contend was changed/updated outside the editor, but that doesn't seem to be the case now.

I think it is still needed for undo/redo. It needs to be possible to set the content from outside the classic block.

Even if this is still needed, don't think that looking at prevProps.attributes.content is a good way to determine what's in the editor at that moment. It needs to do editor.getContent().

Sounds good to me.

@azaozz
Copy link
Contributor Author

azaozz commented Nov 29, 2018

This means that clicking the image specifically is causing the focus loss?

Yes, clicking anywhere outside the editor triggers the blur() and looses the caret position in the editor body <div>.

That is easily fixed by doing the getBookmark(), moveToBookmark(). However these get lost/reset when componentDidUpdate() sometimes.

@azaozz
Copy link
Contributor Author

azaozz commented Nov 29, 2018

I think it is still needed for undo/redo.

I'm probably missing something but can't trigger that... Disabling the revert of the content doesn't seem to break undo/redo.

@ellatrix
Copy link
Member

ellatrix commented Nov 29, 2018

Another interesting thing: even if I remove componentDidUpdate entirely, the problem still exists. Again only happens if you select the image in the media library. Otherwise not.

@azaozz
Copy link
Contributor Author

azaozz commented Nov 29, 2018

even if I remove componentDidUpdate entirely, the problem still exists

Right. It still needs getBookmark(), moveToBookmark() on blur/focus.

@ellatrix
Copy link
Member

Right. It still needs getBookmark(), moveToBookmark() on blur/focus.

Why does this only happen for selecting an image though? What's special about this image?

@azaozz
Copy link
Contributor Author

azaozz commented Nov 29, 2018

Here it happens for any click that focuses something outside the editor body. For example opening the menu, etc.

@azaozz
Copy link
Contributor Author

azaozz commented Nov 29, 2018

Found it :)

The check in componentDidUpdate() is needed only when the global undo/redo buttons are clicked. Not needed/not running for Ctrl/Cmd + z though...

@youknowriad youknowriad modified the milestones: 4.6, 4.7 Nov 29, 2018
@azaozz
Copy link
Contributor Author

azaozz commented Nov 29, 2018

Closing this in favor of #12415.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Classic Affects the Classic Editor Block
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants