Skip to content
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

Visual Editor: Keep the block at the same position while moving it #463

Merged
merged 2 commits into from
Apr 20, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it have been possible to simply store window.scrollY here and restore it directly in the DidUpdate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, actually we don't want to keep the same scrollY since the block is moving, we want the block to show in the same position.

}
}

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