Skip to content

Commit

Permalink
Clone switcher controls into each block
Browse files Browse the repository at this point in the history
- Allows on-hover reveal of switcher to happen reliably with CSS

- Requires refactoring of a few event-binding functions in order for
  them to operate on blocks rather than on a singleton node.

- Reliance on the `selectedBlock` global is diminished. The drawback is
a more hybrid code base, where some logic expects `selectedBlock` and
some doesn't need it. The advantage is that less mutating state needs to
be managed (setting `selectedBlock` can be delayed up until the point it
is necessary for a given operation).

- A couple of TypeErrors may pop up in the console. I suspect there are
some interactions where the target block isn't defined. Needs to be
addressed.
  • Loading branch information
mcsf committed Feb 17, 2017
1 parent 6f0cf64 commit b6cde3c
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 35 deletions.
73 changes: 47 additions & 26 deletions blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ var config = {

var editor = queryFirst( '.editor' );
var switcher = queryFirst( '.block-switcher' );
var switcherButtons = query( '.block-switcher .type svg' );
var switcherMenu = queryFirst( '.switch-block__menu' );
var blockControls = queryFirst( '.block-controls' );
var inlineControls = queryFirst( '.inline-controls' );
Expand Down Expand Up @@ -73,13 +72,33 @@ insertBlockMenu.addEventListener( 'click', function( event ) {
}, false );
window.addEventListener( 'mouseup', onSelectText, false );

cloneSwitcher();
attachBlockHandlers();
attachControlActions();
attachTypeSwitcherActions();

/**
* Core logic
*/
function cloneSwitcher() {
getBlocks().forEach( function( block ) {
var container = document.createElement( 'div' );
var blockSwitcher = switcher.cloneNode( true );

var blockType = getTagType( block.nodeName );
query( '.type svg', blockSwitcher ).forEach( function ( typeButton ) {
typeButton.style.display = 'none';
} );
var switcherQuery = '.type-icon-' + blockType;
queryFirst( switcherQuery, blockSwitcher ).style.display = 'block';

container.className = 'block-container';
editor.insertBefore( container, block );
container.appendChild( blockSwitcher );
container.appendChild( block );
attachControlActions( block );
} );
}

function attachBlockHandlers() {
getBlocks().forEach( function( block ) {
bind( 'click', block, selectBlock );
Expand Down Expand Up @@ -111,18 +130,8 @@ function clearBlocks() {
}

function showControls( node ) {
// toggle block-specific switcher
switcherButtons.forEach( function( element ) {
element.style.display = 'none';
} );
var blockType = getTagType( node.nodeName );
var switcherQuery = '.type-icon-' + blockType;
queryFirst( switcherQuery ).style.display = 'block';

// reposition switcher
var position = node.getBoundingClientRect();
switcher.style.opacity = 1;
switcher.style.top = ( position.top + 18 + window.scrollY ) + 'px';

// show/hide block-specific block controls
var kinds = getTypeKinds( blockType );
Expand All @@ -138,7 +147,6 @@ function showControls( node ) {
}

function hideControls() {
switcher.style.opacity = 0;
switcherMenu.style.display = 'none';
blockControls.style.display = 'none';
}
Expand Down Expand Up @@ -170,8 +178,14 @@ function onSelectText( event ) {
}
}

function attachControlActions() {
Array.from( switcher.childNodes ).forEach( function( node ) {
function attachControlActions( block ) {
var buttons = query( '.block-switcher svg', block.parentNode );
buttons.forEach( function( button ) {
bind( 'click', button, switchType );
} );

var blockSwitcher = queryFirst( '.block-switcher', block.parentNode );
Array.from( blockSwitcher.childNodes ).forEach( function( node ) {
if ( 'svg' !== node.nodeName ) {
return;
}
Expand All @@ -185,9 +199,15 @@ function attachControlActions() {
if ( getter ) {
node.addEventListener( 'click', function( event ) {
event.stopPropagation();
swapNodes( selectedBlock, getter( selectedBlock ) );
clearBlocks();
block.classList.add( 'is-selected' );
selectedBlock = block;
swapNodes(
selectedBlock.parentNode,
getter( selectedBlock.parentNode )
);
attachBlockHandlers();
reselect();
attachControlActions( queryFirst( '.is-selected' ) );
}, false );
}
} );
Expand All @@ -199,10 +219,6 @@ function attachControlActions() {
}

function attachTypeSwitcherActions() {
switcherButtons.forEach( function( button ) {
button.addEventListener( 'click', showSwitcherMenu, false );
} );

Object.keys( config.typeToTag ).forEach( function( type ) {
var selector = '.switch-block__block .type-icon-' + type;
var button = queryFirst( selector );
Expand All @@ -228,10 +244,6 @@ function attachTypeSwitcherActions() {
} );
}

function reselect() {
queryFirst( '.is-selected' ).click();
}

function swapNodes( a, b ) {
if ( ! ( a && b ) ) {
return false;
Expand Down Expand Up @@ -284,12 +296,21 @@ function hideMenu() {
function showSwitcherMenu( event ) {
event.stopPropagation();

var position = switcher.getBoundingClientRect();
var position = queryFirst( '.block-container:hover .block-switcher' )
.getBoundingClientRect();
switcherMenu.style.top = ( position.top + 42 + window.scrollY ) + 'px';
switcherMenu.style.left = ( position.left - 32 + window.scrollX ) + 'px';
switcherMenu.style.display = 'block';
}

function switchType( event ) {
var block = event.target
.closest( '.block-container' )
.childNodes[1];
selectedBlock = block;
showSwitcherMenu( event );
}

function setImageState( classes, event ) {
event.stopPropagation();
selectedBlock.className = 'is-selected ' + classes;
Expand Down
29 changes: 20 additions & 9 deletions style.css
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,20 @@ img {
/* replaces some block margins */
}

h1:hover,
h2:hover,
h3:hover,
h4:hover,
h5:hover,
h6:hover,
p:hover,
blockquote:hover,
img:hover {
.block-container {
margin-left: -50px;
padding-left: 50px;
}

.block-container:hover h1,
.block-container:hover h2,
.block-container:hover h3,
.block-container:hover h4,
.block-container:hover h5,
.block-container:hover h6,
.block-container:hover p,
.block-container:hover blockquote,
.block-container:hover img {
box-shadow: inset 0px 0px 0px 2px #e0e5e9;
}

Expand Down Expand Up @@ -253,6 +258,12 @@ img.is-selected {
transform: translateZ( 0 );
}

.block-container:hover .block-switcher,
.block-container:hover .switch-block__menu {
display: block;
opacity: 1;
}

.block-controls button {
background: #191e23;
color: #fff;
Expand Down

0 comments on commit b6cde3c

Please sign in to comment.