Skip to content
This repository has been archived by the owner on Feb 6, 2023. It is now read-only.

DraftJS is not actually stateless #527

Open
quangbuule opened this issue Jul 10, 2016 · 9 comments
Open

DraftJS is not actually stateless #527

quangbuule opened this issue Jul 10, 2016 · 9 comments

Comments

@quangbuule
Copy link

When I tried to render DraftJS into an iframe window, for example:

ReactDOM.render(<DraftEditor .../>,
  document
    .getElementById('some_iframe')
    .contentWindow
    .document
    .getElementById('some_inner_element'))

inside the DraftJS functions, there were window, global, document variables, which were global variables, still referenced to the parent window (the window that run the above snippet).
So, global.getSelection, node !== document.documentElement didn't work.

Render components inside iframe is important for isolating CSS especially rem unit.
Looking forward to having a discussion around this. Thank you all!

@sophiebits
Copy link
Contributor

This isn't a huge priority for us at Facebook, but I think we'd probably be willing to take pull requests that fix this.

@quangbuule
Copy link
Author

Thanks @spicyj for your quick response, I'll dive into it or find a way to solve my own problem.

@dnusca
Copy link

dnusca commented Jul 18, 2016

@quangbuule After much debugging it appears I am in the situation as you and could help out if you're still going to dive into it. How many instances of these references to the parent window are there? We could potentially have an iframeID prop and then use contentWindow or contentDocument to point to the right window/document.

@jasonenglish
Copy link

jasonenglish commented Aug 16, 2016

Ran into some issues trying to do the same thing using react-frame-component. One issue I noticed was that while selecting text then hitting the delete key would only delete one character instead of the entire selection.

While digging into this, I noticed that onSelect is never being triggered. The issue seems to be the SelectEventPlugin which references the parent window and causes anything relating to the current selection state to be broken in DraftJS since the event isn't firing.

I think to get rendering into an iframe like this to actually work it may require some substantial changes.

I believe ryanseddon/react-frame-component#40 is also related

Alternative approaches

Option 1: Inject HTML into the iframe

  • Instead of it being rendered into the iframe from the parent. You could inject HTML that includes your component, stylesheets and any dependencies you need like React.
  • Allows you to still directly access the iframe without using postMessage
  • Doesn't require specifying the iframe src or host a file somewhere

Option 2: Load a file into the iframe src

  • Will achieve the same result as Option 1 but requires you specify an iframe src
  • Depending if the iframe src is the same domain or not. It might require you to use postMessage to communicate with the iframe component.

Going to try Option 1 for a project I'm working on. Curious if anyone else has some thoughts on this.

@acusti
Copy link

acusti commented Oct 6, 2016

I have a PR in React that fixes SelectEventPlugin, ReactInputSelection, and ReactDOMSelection for cross-iframe compatibility: facebook/react#7936

It depends on a PR in fbjs to make some of those utilities iframe compatible: facebook/fbjs#188

Next up is a PR specifically for this issue, but it, of course, will depend on those other two PRs. I’m hopeful that the final result will be a version of draft that can be rendered into an iframe (like what react-frame-component does) and still have all events and functionality fully preserved. This will also make it easy to have multiple selections, which makes linking a section of text, for example, much nicer. I made a demo of a textarea where you can link portions of it to demonstrate that use case.

Without the changes in the React + fbjs PRs: http://codepen.io/acusti/pen/EgQxJG?editors=0011
With the changes in the React + fbjs PRs: http://codepen.io/acusti/pen/qaxBby?editors=0011

@acusti
Copy link

acusti commented Nov 5, 2016

I opened a PR, #765, to enable this in Draft.js. Still waiting on the React PR (and on the changes in fbjs to be published in a new release), but seems to me that it’s still valuable to have the Draft.js PR open at the same time. We are currently using an npm-installable built version of our fork in our app as we develop our text editor feature. If anyone out there would also like to try it out, here are the installable strings to include in your package.json:

    "draft-js": "Brandcast/draft-js#f9affa3",
    "fbjs": "Brandcast/fbjs-built#97b8e54",
    "react": "Brandcast/react#9a81d1a",

Alternatively, if you just want to play with a fiddle or codepen or whatever, you can try it out in the browser by including these <script> elements:

    <script src="https://rawgit.com/Brandcast/react/nested-browsing-contexts-2-built/build/react.js"></script>
    <script src="https://rawgit.com/Brandcast/react/nested-browsing-contexts-2-built/build/react-dom.js"></script>
    <script src="https://cdn.jsdelivr.net/immutable.js/latest/immutable.min.js"></script>
    <script src="https://cdn.jsdelivr.net/es6.shim/0.35.1/es6-shim.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.js"></script>
    <script src="https://rawgit.com/Brandcast/draft-js/iframe-compatibility-built/dist/Draft.js"></script>

I would love to get anyone’s feedback or experiences trying out those builds. We have so far had success and everything seems to be working well in our app using them, but our implementation is still very simple and is using a minimal set of Draft.js features.

@gjulivan
Copy link

gjulivan commented Oct 8, 2018

@acusti
I'm curious about your implementation here. I'm currently having the same problem. managed to update the document variables part. but still having issue on select, cut, and paste on draft js.
I'm using draft-js 10.5, react 16 and react portal to render draft-js into another frame
any suggestion of code part that i should be looking at?

@acusti
Copy link

acusti commented Oct 8, 2018

@gjulivan References to the global window and document objects are strewn throughout the codebase, so there are a fair number of changes required to make this work fully (around 120 lines, according to the PR https://github.com/facebook/draft-js/pull/765/files). A lot of the issues are with the way that draft.js currently ensures type safety, which is to check if a variables is an instanceof a window global, such as Node. In editOnSelect.js, for example, there’s an invariant that editorNode.firstChild instanceof HTMLElement before the selection state is updated. But you’ll need to replicate most (if not all) of the changes you see in the PR to make it work fully when rendered via react portal into another frame.

Also, you will need to be on at least react-dom version 16.5.0 to have all of this work (it includes a fix to react-dom selection event handling across nested browsing contexts, e.g. iframes).

@gjulivan
Copy link

gjulivan commented Oct 9, 2018

@acusti Thanks!
It works on my side now.
I was using react-dom 16.4, upgraded to 16.5 and managed to alter the instanceOf validations.
you are really helpful.

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

Successfully merging a pull request may close this issue.

6 participants