1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-22 15:02:51 +02:00

Add handler "onBeforeChange" (#219)

* Add handler "onReceiveState"

* Change onReceiveChange to onBeforeChange and call it before onChange as well

* Dont'call props.onBeforeChange since it's added to CorePlugin

* Update documentation for onBeforeChange
This commit is contained in:
Samy Pessé
2016-08-04 22:11:23 +02:00
committed by Ian Storm Taylor
parent 2d63957246
commit f25c5d9a64
3 changed files with 44 additions and 11 deletions

View File

@@ -23,7 +23,7 @@ When the editor needs to resolve a plugin-related handler, it will loop through
- [`renderNode`](#rendernode) - [`renderNode`](#rendernode)
- [Other Properties](#other-properties) - [Other Properties](#other-properties)
- [`onChange`](#onchange) - [`onChange`](#onchange)
- [`onBeforeChange`](#onbeforechange)
## Conventions ## Conventions
@@ -293,3 +293,10 @@ The `onChange` handler isn't a native browser event handler. Instead, it is invo
Unlike the native event handlers, results from the `onChange` handler **are cummulative**! This means that every plugin in the stack that defines an `onChange` handler will have its handler resolved for every change the editor makes; the editor will not return early after the first plugin's handler is called. Unlike the native event handlers, results from the `onChange` handler **are cummulative**! This means that every plugin in the stack that defines an `onChange` handler will have its handler resolved for every change the editor makes; the editor will not return early after the first plugin's handler is called.
This allows you to stack up changes across the entire plugin stack. This allows you to stack up changes across the entire plugin stack.
### `onBeforeChange`
`Function onBeforeChange(state: State) => State || Void`
The `onBeforeChange` handler isn't a native browser event handler. Instead, it is invoked whenever the editor receives a new state and before propagating a new state to `onChange`. Returning a new state will update the editor's state before rendering, continuing down the plugin stack.
Like `onChange`, `onBeforeChange` is cummulative.

View File

@@ -51,6 +51,7 @@ class Editor extends React.Component {
static propTypes = { static propTypes = {
className: React.PropTypes.string, className: React.PropTypes.string,
onBeforeChange: React.PropTypes.func,
onChange: React.PropTypes.func.isRequired, onChange: React.PropTypes.func.isRequired,
onDocumentChange: React.PropTypes.func, onDocumentChange: React.PropTypes.func,
onSelectionChange: React.PropTypes.func, onSelectionChange: React.PropTypes.func,
@@ -90,7 +91,7 @@ class Editor extends React.Component {
this.tmp = {} this.tmp = {}
this.state = {} this.state = {}
this.state.plugins = this.resolvePlugins(props) this.state.plugins = this.resolvePlugins(props)
this.state.state = props.state this.state.state = this.onBeforeChange(props.state)
// Mix in the event handlers. // Mix in the event handlers.
for (const method of EVENT_HANDLERS) { for (const method of EVENT_HANDLERS) {
@@ -107,7 +108,7 @@ class Editor extends React.Component {
*/ */
componentWillReceiveProps = (props) => { componentWillReceiveProps = (props) => {
this.state.state = props.state this.state.state = this.onBeforeChange(props.state)
if (props.plugins != this.props.plugins) { if (props.plugins != this.props.plugins) {
this.setState({ plugins: this.resolvePlugins(props) }) this.setState({ plugins: this.resolvePlugins(props) })
@@ -159,6 +160,8 @@ class Editor extends React.Component {
onChange = (state) => { onChange = (state) => {
if (state == this.state.state) return if (state == this.state.state) return
state = this.onBeforeChange(state)
for (const plugin of this.state.plugins) { for (const plugin of this.state.plugins) {
if (!plugin.onChange) continue if (!plugin.onChange) continue
const newState = plugin.onChange(state, this) const newState = plugin.onChange(state, this)
@@ -179,6 +182,26 @@ class Editor extends React.Component {
} }
} }
/**
* When the editor receives a new 'state'
*
* @param {State} state
* @return {State} newState
*/
onBeforeChange = (state) => {
if (state == this.state.state) return
for (const plugin of this.state.plugins) {
if (!plugin.onBeforeChange) continue
const newState = plugin.onBeforeChange(state, this)
if (newState == null) continue
state = newState
}
return state
}
/** /**
* When an event by `name` fires, pass it through the plugins, and update the * When an event by `name` fires, pass it through the plugins, and update the
* state if one of them chooses to. * state if one of them chooses to.

View File

@@ -21,6 +21,7 @@ const debug = Debug('slate:core')
* @property {Element} placeholder * @property {Element} placeholder
* @property {String} placeholderClassName * @property {String} placeholderClassName
* @property {Object} placeholderStyle * @property {Object} placeholderStyle
* @property {Function} onBeforeChange
* @return {Object} * @return {Object}
*/ */
@@ -28,7 +29,8 @@ function Plugin(options = {}) {
const { const {
placeholder, placeholder,
placeholderClassName, placeholderClassName,
placeholderStyle placeholderStyle,
onBeforeChange
} = options } = options
/** /**
@@ -612,6 +614,7 @@ function Plugin(options = {}) {
*/ */
return { return {
onBeforeChange,
onBeforeInput, onBeforeInput,
onBlur, onBlur,
onCopy, onCopy,