From a7bec0367961040fce38ba89f1e5bcf9446df462 Mon Sep 17 00:00:00 2001 From: iseulde Date: Wed, 10 May 2017 19:05:09 +0200 Subject: [PATCH] Add Editable placeholders --- blocks/editable/index.js | 30 +++++++++++++++++++++++++++--- blocks/editable/style.scss | 15 +++++++++++++++ blocks/editable/tinymce.js | 13 +++++++++++-- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/blocks/editable/index.js b/blocks/editable/index.js index 0cde867ff9871..443df10c21a99 100644 --- a/blocks/editable/index.js +++ b/blocks/editable/index.js @@ -62,7 +62,7 @@ function createElement( type, props, ...children ) { } export default class Editable extends wp.element.Component { - constructor() { + constructor( props ) { super( ...arguments ); this.onInit = this.onInit.bind( this ); @@ -73,10 +73,13 @@ export default class Editable extends wp.element.Component { this.onNodeChange = this.onNodeChange.bind( this ); this.onKeyDown = this.onKeyDown.bind( this ); this.changeFormats = this.changeFormats.bind( this ); + this.onSelectionChange = this.onSelectionChange.bind( this ); + this.state = { formats: {}, alignment: null, - bookmark: null + bookmark: null, + empty: ! props.value || ! props.value.length }; } @@ -88,6 +91,7 @@ export default class Editable extends wp.element.Component { editor.on( 'focusin', this.onFocus ); editor.on( 'nodechange', this.onNodeChange ); editor.on( 'keydown', this.onKeyDown ); + editor.on( 'selectionChange', this.onSelectionChange ); } onInit() { @@ -103,6 +107,23 @@ export default class Editable extends wp.element.Component { this.props.onFocus(); } + isActive() { + return document.activeElement === this.editor.getBody(); + } + + onSelectionChange() { + // We must check this because selectionChange is a global event. + if ( ! this.isActive() ) { + return; + } + + const content = this.getContent(); + + this.setState( { + empty: ! content || ! content.length + } ); + } + onChange() { if ( ! this.editor.isDirty() ) { return; @@ -349,7 +370,8 @@ export default class Editable extends wp.element.Component { showAlignments = false, inlineToolbar = false, inline, - formattingControls + formattingControls, + placeholder } = this.props; // Generating a key that includes `tagName` ensures that if the tag @@ -397,6 +419,8 @@ export default class Editable extends wp.element.Component { settings={ { forced_root_block: inline ? false : 'p' } } + isEmpty={ this.state.empty } + placeholder={ placeholder } key={ key } /> ); diff --git a/blocks/editable/style.scss b/blocks/editable/style.scss index 706d697f6c3e7..42c2583ff5087 100644 --- a/blocks/editable/style.scss +++ b/blocks/editable/style.scss @@ -40,6 +40,16 @@ background: $light-gray-400; } + &[data-is-empty="true"] { + position: relative; + } + + &[data-is-empty="true"]:before { + content: attr( data-placeholder ); + opacity: 0.5; + pointer-events: none; + position: absolute; + } } .block-editable__inline-toolbar { @@ -57,6 +67,11 @@ figcaption.blocks-editable__tinymce { color: $dark-gray-100; text-align: center; font-size: $default-font-size; + + &:before { + left: 50%; + transform: translateX( -50% ); + } } diff --git a/blocks/editable/tinymce.js b/blocks/editable/tinymce.js index d718f7a5abbc1..531f215fb6c46 100644 --- a/blocks/editable/tinymce.js +++ b/blocks/editable/tinymce.js @@ -11,6 +11,14 @@ export default class TinyMCE extends wp.element.Component { return false; } + componentWillReceiveProps( nextProps ) { + const isEmpty = String( nextProps.isEmpty ); + + if ( this.editorNode.getAttribute( 'data-is-empty' ) !== isEmpty ) { + this.editorNode.setAttribute( 'data-is-empty', isEmpty ); + } + } + componentWillUnmount() { if ( ! this.editor ) { return; @@ -47,7 +55,7 @@ export default class TinyMCE extends wp.element.Component { } render() { - const { tagName = 'div', style, defaultValue } = this.props; + const { tagName = 'div', style, defaultValue, placeholder } = this.props; // If a default value is provided, render it into the DOM even before // TinyMCE finishes initializing. This avoids a short delay by allowing @@ -62,7 +70,8 @@ export default class TinyMCE extends wp.element.Component { contentEditable: true, suppressContentEditableWarning: true, className: 'blocks-editable__tinymce', - style + style, + 'data-placeholder': placeholder }, children ); } }