Draft.js + Meteor + iframe causes node instanceof Element to return false #1640
Description
Do you want to request a feature or report a bug?
Bug
What is the current behavior?
When creating a React application using Meteor and DraftJs, trying to render the Editor and make any change will cause the checks for node instanceof Element
and node instanceof HTMLElement
to return false
and prevent the use of draft.js.
Since Meteor compiles scripts and import them in the current window, draft.js Element
is the global Element
, however, the obtained node by ReactDOM.findNode
was created using the iframe's Element
constructor. Instanceof implementation suggest using this line rather than accessible Element
directly.
myNode instanceof myNode.ownerDocument.defaultView.SVGElement
This can be seen there for example : https://github.com/facebook/draft-js/blob/788595984da7c1e00d1071ea82b063ff87140be4/src/component/contents/DraftEditorTextNode.react.js#L84
This is consistent across the tested browser and is probably caused by the fact that draft.js uses the global Element
, which is loaded as the global window Element
when the script is first imported, rather than the current window Element
.
This was also tested using a standard iFrame with injecting HTML, an iFrame with portals and react-frame-component
.
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. You can use this jsfiddle to get started: https://jsfiddle.net/stopachka/m6z0xn4r/.
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import Frame from 'react-frame-component';
import {
convertToRaw,
CompositeDecorator,
ContentState,
Entity,
Editor,
EditorState,
EntityInstance,
RichUtils,
} from 'draft-js';
class PageHome extends Component {
constructor(props) {
super(props);
this.state = {
editorState: EditorState.createEmpty()
};
}
onChange = (editorState) => {
this.setState({editorState});
}
render() {
return (
<div className="container" style={{padding:10}}>
<Frame>
<Editor editorState={this.state.editorState} onChange={this.onChange}/>
</Frame>
</div>
);
}
}
When doing this, the following error is caused in the console when writing in the editor :
What is the expected behavior?
Draft.js should probably not rely on the Element global or the window/document globals for its code. In this case, draft.js should behave like usual when added inside an iframe.
Maybe replace this with an implementation similar to lodash's isElement could also fix this issue, but it has been stated before that iframes are unlikely to be supported in #527. This is also specific to meteor's compiling, but may cause problem for other js compiled and minifiers.
Which versions of Draft.js, and which browser / OS are affected by this issue? Did this work in previous versions of Draft.js?
Tested in version 0.10.5,
Tested with Chrome, Firefox and Microsoft Edge, all latest versions.
I had not tested it with earlier version of draft-js as NPM always install the latest version.
I also tried to implement to solution proposed in PR #765, but it seems the selection is not registered.