Skip to content

Commit

Permalink
Visual Editor: Keep the block at the same position while moving it (#463
Browse files Browse the repository at this point in the history
)
  • Loading branch information
youknowriad authored Apr 20, 2017
1 parent 285bab6 commit 3bba830
Showing 1 changed file with 89 additions and 53 deletions.
142 changes: 89 additions & 53 deletions editor/modes/visual-editor/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,31 @@ import Toolbar from 'components/toolbar';
import BlockMover from 'components/block-mover';
import BlockSwitcher from 'components/block-switcher';

function VisualEditorBlock( props ) {
const { block } = props;
const settings = wp.blocks.getBlockSettings( block.blockType );

let BlockEdit;
if ( settings ) {
BlockEdit = settings.edit || settings.save;
class VisualEditorBlock extends wp.element.Component {
constructor() {
super( ...arguments );
this.bindBlockNode = this.bindBlockNode.bind( this );
this.setAttributes = this.setAttributes.bind( this );
this.maybeDeselect = this.maybeDeselect.bind( this );
this.previousOffset = null;
}

if ( ! BlockEdit ) {
return null;
bindBlockNode( node ) {
this.node = node;
}

const { isHovered } = props;
const isSelected = props.isSelected;
const className = classnames( 'editor-visual-editor__block', {
'is-selected': isSelected,
'is-hovered': isHovered
} );

const { onChange, onSelect, onDeselect, onMouseEnter, onMouseLeave, onInsertAfter } = props;
componentWillReceiveProps( newProps ) {
if (
this.props.order !== newProps.order &&
this.props.isSelected &&
newProps.isSelected
) {
this.previousOffset = this.node.getBoundingClientRect().top;
}
}

function setAttributes( attributes ) {
setAttributes( attributes ) {
const { block, onChange } = this.props;
onChange( {
attributes: {
...block.attributes,
Expand All @@ -42,53 +44,87 @@ function VisualEditorBlock( props ) {
} );
}

function maybeDeselect( event ) {
maybeDeselect( event ) {
// Annoyingly React does not support focusOut and we're forced to check
// related target to ensure it's not a child when blur fires.
if ( ! event.currentTarget.contains( event.relatedTarget ) ) {
onDeselect();
this.props.onDeselect();
}
}

// Disable reason: Each block can receive focus but must be able to contain
// block children. Tab keyboard navigation enabled by tabIndex assignment.
componentDidUpdate() {
if ( this.previousOffset ) {
window.scrollTo(
window.scrollX,
window.scrollY + this.node.getBoundingClientRect().top - this.previousOffset
);
this.previousOffset = null;
}
}

render() {
const { block } = this.props;
const settings = wp.blocks.getBlockSettings( block.blockType );

let BlockEdit;
if ( settings ) {
BlockEdit = settings.edit || settings.save;
}

if ( ! BlockEdit ) {
return null;
}

const { isHovered, isSelected } = this.props;
const className = classnames( 'editor-visual-editor__block', {
'is-selected': isSelected,
'is-hovered': isHovered
} );

const { onSelect, onDeselect, onMouseEnter, onMouseLeave, onInsertAfter } = this.props;

/* eslint-disable jsx-a11y/no-static-element-interactions */
return (
<div
tabIndex="0"
onFocus={ onSelect }
onBlur={ maybeDeselect }
onKeyDown={ onDeselect }
onMouseEnter={ onMouseEnter }
onMouseLeave={ onMouseLeave }
className={ className }
>
{ ( isSelected || isHovered ) && <BlockMover uid={ block.uid } /> }
<div className="editor-visual-editor__block-controls">
{ isSelected && <BlockSwitcher uid={ block.uid } /> }
{ isSelected && settings.controls ? (
<Toolbar
controls={ settings.controls.map( ( control ) => ( {
...control,
onClick: () => control.onClick( block.attributes, setAttributes ),
isActive: () => control.isActive( block.attributes )
} ) ) } />
) : null }
// Disable reason: Each block can receive focus but must be able to contain
// block children. Tab keyboard navigation enabled by tabIndex assignment.

/* eslint-disable jsx-a11y/no-static-element-interactions */
return (
<div
ref={ this.bindBlockNode }
tabIndex="0"
onFocus={ onSelect }
onBlur={ this.maybeDeselect }
onKeyDown={ onDeselect }
onMouseEnter={ onMouseEnter }
onMouseLeave={ onMouseLeave }
className={ className }
>
{ ( isSelected || isHovered ) && <BlockMover uid={ block.uid } /> }
<div className="editor-visual-editor__block-controls">
{ isSelected && <BlockSwitcher uid={ block.uid } /> }
{ isSelected && settings.controls ? (
<Toolbar
controls={ settings.controls.map( ( control ) => ( {
...control,
onClick: () => control.onClick( block.attributes, this.setAttributes ),
isActive: () => control.isActive( block.attributes )
} ) ) } />
) : null }
</div>
<BlockEdit
isSelected={ isSelected }
attributes={ block.attributes }
setAttributes={ this.setAttributes }
insertBlockAfter={ onInsertAfter }
/>
</div>
<BlockEdit
isSelected={ isSelected }
attributes={ block.attributes }
setAttributes={ setAttributes }
insertBlockAfter={ onInsertAfter }
/>
</div>
);
/* eslint-enable jsx-a11y/no-static-element-interactions */
);
/* eslint-enable jsx-a11y/no-static-element-interactions */
}
}

export default connect(
( state, ownProps ) => ( {
order: state.blocks.order.indexOf( ownProps.uid ),
block: state.blocks.byUid[ ownProps.uid ],
isSelected: state.selectedBlock === ownProps.uid,
isHovered: state.hoveredBlock === ownProps.uid
Expand Down

0 comments on commit 3bba830

Please sign in to comment.