instructure-react/react-tinymce

Bug: Editor-Cursor jumps to top after enter key

Closed this issue · 8 comments

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
After using "setup" or "init_instance_callback" in the tinymce config (together with react) the editor-cursor jumps to the top of the editor. The cursor jumps are happening after every enter. (See gif film here)

Edit: The bug only occurs if the editor is used with inline=true.

Code which works

export default function Editor(props) {
    return (
        <TinyMCE
            config={{
                ...config.tinymce,
                language: getEditorLanguage()
                }
            }}
            content={props.children || props.placeholder}
            onChange={props.onChange}
            ref={(tiny) => this.tiny = tiny } />
    );
}

Code which breaks the editor
The strange behavior starts as soon as we use setup: (editor) => {... }. If I remove the setup with the console.log the editor is back to normal.

export default function Editor(props) {
    return (
        <TinyMCE
            config={{
                ...config.tinymce,
                language: getEditorLanguage(),
                setup: (editor) => {
                    console.log('test');
                }
            }}
            content={props.children || props.placeholder}
            onChange={props.onChange}
            ref={(tiny) => this.tiny = tiny } />
    );
}

The browser console shows also a error after using the enter key:

tinymce.js:41290 Uncaught DOMException: Failed to execute 'setEndAfter' on 'Range': the given Node has no parent.
    at handleEnterKey (http://localhost:8000/webpack:/~/tinymce/tinymce.js:41290:1)
    at Editor.<anonymous> (http://localhost:8000/webpack:/~/tinymce/tinymce.js:41324:1)
    at Dispatcher.fire (http://localhost:8000/webpack:/~/tinymce/tinymce.js:30842:1)
    at Editor.fire (http://localhost:8000/webpack:/~/tinymce/tinymce.js:31082:1)
    at DOMUtils.delegate (http://localhost:8000/webpack:/~/tinymce/tinymce.js:37928:1)
    at executeHandlers (http://localhost:8000/webpack:/~/tinymce/tinymce.js:1181:1)
    at HTMLDivElement.defaultNativeHandler (http://localhost:8000/webpack:/~/tinymce/tinymce.js:1208:1)

What is the expected behavior?
Editor should not jump to the top and the buttons should still be shown and working.

We just wanted to add two custom buttons. The Buttons are actually shown and work properly, but as mentioned before the editor-cursor starts to jump around. Is there maybe a workaround for this already?

export default function Editor(props) {
    return (
        <TinyMCE
            config={{
                ...config.tinymce,
                language: getEditorLanguage(),
                setup: (editor) => {
                    editor.addButton('linkfile', {
                        icon: 'newdocument',
                        onClick: props.onFileLinkAdd,
                        tooltip: 'Insert/edit file link'
                    });
                    editor.addButton('image', {
                        icon: 'image',
                        onclick: props.onImageAdd,
                        tooltip: 'Insert Image'
                    });
                }
            }}
            content={props.children || props.placeholder}
            onChange={props.onChange}
            ref={(tiny) => this.tiny = tiny} />
    );
}

Which versions of TinyMCE, and which browser / OS are affected by this issue? Did this work in previous versions of TinyMCE?
react-tinymce: 0.6.0
tinymce: 4.6.4 and 4.6.5 -> Same problem with both versions.
tinymce-i18n: 17.7.8

Google Chrome: Version 59.0.3071.115 (Official Build)
Mozilla Firefox: 55.0.1
Linux: Ubuntu 16.04 LTS

Similar issues:
Has someone seen the same behavior occure? The only other similar problem I found was this one on Stackoverflow:
WIth Angular 2

I have the same problem,the cursor always jump to top when writing

I solve the problem by delete the isEquel(this.props.config, nextprops.config) in componentWillReceiveProps, and replace the config with id in componentShouldUpdate(),

shouldComponentUpdate: function shouldComponentUpdate(nextProps) { return !(0, _lodashIsEqual2['default'])(this.props.id, nextProps.id); }

I found the config always change when content has changed, which make the 'shouldUpdate' always be true, once component update, "editor.selection.collapse(false)" will not work.
hope have a better answer for this problem.

I worked around this by preventing content updates for my project's editor:

  • Added local state 'initialContent' to Editor component that is set in the constructor.
  • onChange saves the current content to the db
  • TinyMCE's content is set to initialContent and is therefore not re-rendered onChange. This prevents cursor jumping.

I worked around this by declaring a component method called editorSetup and then pointing to it in the config, e.g.:

<TinyMCE
    className={styles.contents}
    content={this.props.section.contents}
    config={{
        statusbar: false,
        inline: true,
        setup: this.setupEditor
    }}
    onChange={event => {
        this.props.updateSectionContents(event.target.getContent())
    }}
>

Not using an anonymous onChange handler seems to do the trick.

jnnck commented

Stumbled upon this issue and fixed it by changing value to initialValue on the component.

if you using tinymce-react as a controlled component, you should use the onEditorChange event instead of the onChange event.

I've encountered this but only when the character ’ character. It's being used instead of the single quote for copied text such as "I’ve".

I had this same issue, I fixed it by having two variables. One for InitialValue which is set in a useEffect on component load, and another variable which tracks the editor state updated using onEditorChange={(newValue, editor) => {setEditorState(newValue)}}.