-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Editable: implement TinyMCE on the core Editable component #330
Changes from all commits
d7c9bb7
4b7a51a
a6bfbcf
cf04a33
f80239f
97ba143
84f31be
b33ed3a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,7 +18,8 @@ | |
} | ||
}, | ||
"globals": { | ||
"wp": true | ||
"wp": true, | ||
"tinymce": true | ||
}, | ||
"plugins": [ | ||
"react", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,75 @@ | ||
export default function Editable( { value } ) { | ||
return <p>{ value }</p>; | ||
export default class Editable extends wp.element.Component { | ||
constructor() { | ||
super( ...arguments ); | ||
this.onInit = this.onInit.bind( this ); | ||
this.onSetup = this.onSetup.bind( this ); | ||
this.onChange = this.onChange.bind( this ); | ||
this.bindNode = this.bindNode.bind( this ); | ||
} | ||
|
||
componentDidMount() { | ||
this.initialize(); | ||
} | ||
|
||
initialize() { | ||
const config = { | ||
target: this.node, | ||
theme: false, | ||
inline: true, | ||
toolbar: false, | ||
browser_spellcheck: true, | ||
entity_encoding: 'raw', | ||
setup: this.onSetup, | ||
formats: { | ||
strikethrough: { inline: 'del' } | ||
} | ||
}; | ||
|
||
tinymce.init( config ); | ||
} | ||
|
||
onSetup( editor ) { | ||
this.editor = editor; | ||
editor.on( 'init', this.onInit ); | ||
editor.on( 'focusout', this.onChange ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. focusout will when focus is shifted internally within nested contenteditables. Use "blur" instead or possible 'change' since that is called on every undo level add including 'blur' since that adds an undo level. Might be to frequent though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this is a "controlled" TinyMCE (each time the content prop changes, we update the content), I had issues while using |
||
} | ||
|
||
onInit() { | ||
this.editor.setContent( this.props.value ); | ||
} | ||
|
||
onChange() { | ||
if ( ! this.editor.isDirty() ) { | ||
return; | ||
} | ||
const value = this.editor.getContent(); | ||
this.editor.save(); | ||
this.props.onChange( value ); | ||
} | ||
|
||
bindNode( ref ) { | ||
this.node = ref; | ||
} | ||
|
||
updateContent() { | ||
const bookmark = this.editor.selection.getBookmark( 2, true ); | ||
this.editor.setContent( this.props.value ); | ||
this.editor.selection.moveToBookmark( bookmark ); | ||
} | ||
|
||
componentWillUnmount() { | ||
if ( this.editor ) { | ||
this.editor.destroy(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use this.editor.remove(); destroy is more for memory cleanups on unload of the page not really a problem now days on modern browsers. Destroy is called by remove. |
||
} | ||
} | ||
|
||
componentDidUpdate( prevProps ) { | ||
if ( this.props.value !== prevProps.value ) { | ||
this.updateContent(); | ||
} | ||
} | ||
|
||
render() { | ||
return <div ref={ this.bindNode } />; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,12 @@ | ||
const { query, html } = wp.blocks.query; | ||
const { html } = wp.blocks.query; | ||
const Editable = wp.blocks.Editable; | ||
|
||
wp.blocks.registerBlock( 'core/text', { | ||
title: 'Text', | ||
icon: 'text', | ||
|
||
attributes: { | ||
value: query( 'p', html() ) | ||
value: html() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might still be value in specifying There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a good question. If we limit the value to the text within the This is probably what we want, I was thinking we could leave this to a separate PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How does specifying There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is unrelated to The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, sort of. What I was interested in was what is actually saved. If I look at the post content of my current blog, there are a lot of text paragraphs separated by one blank line. There are not actual There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm assuming we're talking about the visual editor. Then yes, in its current form this block saves the content with the But this is far from being the final version of the text block, it's just here to serve as an example of block while we're building the "surroundings", how we parse the content, how we save it back, how we render the editables etc... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it's an example, so I would hope you "do it right". If it saves the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the exact reason why we're trying to build this as a plugin and to tie it to real data (real posts), for now, my answer to this is "I don't know". We'll have to try the editor in the context of real data to figure out these consequences (and fix all the unwanted behaviour). |
||
}, | ||
|
||
edit( attributes, onChange ) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To recreate default
contenteditable
behaviour, we should probably addbrowser_spellcheck: true
.