diff --git a/tinymce-single/blocks.js b/tinymce-single/blocks.js new file mode 100644 index 0000000000000..7c7ff5f9d0af2 --- /dev/null +++ b/tinymce-single/blocks.js @@ -0,0 +1,44 @@ +( function( wp ) { + var _blocks, _controls; + + _blocks = {}; + _controls = {}; + + wp.blocks = { + registerBlock: function( settings ) { + // Note, elements should probably only be registered by core. + // Maybe for each block, we should offer to extend the settings (add buttons). + + if ( settings.elements ) { + settings.elements.forEach( function( element ) { + _blocks[ 'element:' + element ] = settings; + _blocks[ 'element:' + element ]._id = 'element:' + element; + } ); + } else if ( settings.namespace && settings.name ) { + _blocks[ settings.namespace + ':' + settings.name ] = settings; + _blocks[ settings.namespace + ':' + settings.name ]._id = settings.namespace + ':' + settings.name; + } + }, + registerControl: function( name, settings ) { + _controls[ name ] = settings; + }, + getBlockSettings: function( name ) { + return _blocks[ name ]; + }, + getControlSettings: function( name ) { + return _controls[ name ]; + }, + getBlockSettingsByElement: function( element ) { + var blockType = element.getAttribute( 'data-wp-block-type' ); + var nodeName = element.nodeName.toLowerCase(); + + return this.getBlockSettings( blockType || 'element:' + nodeName ); + }, + getBlocks: function() { + return _blocks; + }, + getControls: function() { + return _controls; + } + }; +} )( window.wp = window.wp || {} ); diff --git a/tinymce-single/blocks/core/gallery/register.js b/tinymce-single/blocks/core/gallery/register.js index 6242ac067851e..065fcce7f258e 100644 --- a/tinymce-single/blocks/core/gallery/register.js +++ b/tinymce-single/blocks/core/gallery/register.js @@ -1,10 +1,10 @@ -window.wp.blocks.register( { +window.wp.blocks.registerBlock( { name: 'gallery', namespace: 'core', type: 'image', keywords: [], icon: 'gridicons-image-multiple', - buttons: [ + controls: [ 'block-align-left', 'block-align-center', 'block-align-right', diff --git a/tinymce-single/blocks/core/image/register.js b/tinymce-single/blocks/core/image/register.js index d7cd32061f8ef..3503225b3e5ec 100644 --- a/tinymce-single/blocks/core/image/register.js +++ b/tinymce-single/blocks/core/image/register.js @@ -1,9 +1,9 @@ -window.wp.blocks.register( { +window.wp.blocks.registerBlock( { name: 'image', namespace: 'core', type: 'image', icon: 'gridicons-image', - buttons: [ + controls: [ 'block-align-left', 'block-align-center', 'block-align-right', diff --git a/tinymce-single/blocks/elements/blockquote/register.js b/tinymce-single/blocks/elements/blockquote/register.js index d088bd1b1a995..90d2babf23b7d 100644 --- a/tinymce-single/blocks/elements/blockquote/register.js +++ b/tinymce-single/blocks/elements/blockquote/register.js @@ -1,8 +1,8 @@ -window.wp.blocks.register( { +window.wp.blocks.registerBlock( { elements: [ 'blockquote' ], type: 'text', icon: 'gridicons-quote', - buttons: [ + controls: [ { classes: 'remove-formatting', icon: 'gridicons-quote', diff --git a/tinymce-single/blocks/elements/headings/register.js b/tinymce-single/blocks/elements/headings/register.js index b450c0a8ecfda..46cc3706bcea2 100644 --- a/tinymce-single/blocks/elements/headings/register.js +++ b/tinymce-single/blocks/elements/headings/register.js @@ -1,9 +1,9 @@ -( function( register ) { - function getButtons() { - var buttons = []; +( function( wp ) { + function getControls() { + var controls = []; '123456'.split( '' ).forEach( function( level ) { - buttons.push( { + controls.push( { icon: 'gridicons-heading', text: level, stateSelector: 'h' + level, @@ -13,7 +13,7 @@ } ); } ); - buttons.push( { + controls.push( { classes: 'remove-formatting', icon: 'gridicons-heading', onClick: function( editor, element ) { @@ -21,15 +21,15 @@ } } ); - buttons.push( 'text-align-center' ); + controls.push( 'text-align-left', 'text-align-center', 'text-align-right' ); - return buttons; + return controls; } - register( { + wp.blocks.registerBlock( { elements: [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ], type: 'text', icon: 'gridicons-heading', - buttons: getButtons() + controls: getControls() } ); -} )( window.wp.blocks.register ); +} )( window.wp ); diff --git a/tinymce-single/blocks/elements/horizontal-rule/register.js b/tinymce-single/blocks/elements/horizontal-rule/register.js index 9ff1cb5a4e81a..04ec1167b5e9e 100644 --- a/tinymce-single/blocks/elements/horizontal-rule/register.js +++ b/tinymce-single/blocks/elements/horizontal-rule/register.js @@ -1,10 +1,7 @@ -window.wp.blocks.register( { +window.wp.blocks.registerBlock( { elements: [ 'hr' ], type: 'separator', icon: 'gridicons-minus', - buttons: [ - - ], insert: function( editor, element ) { element.parentNode.replaceChild( document.createElement( 'hr' ), element ); } diff --git a/tinymce-single/blocks/elements/lists/register.js b/tinymce-single/blocks/elements/lists/register.js index 83747d8fcd1b2..aefce1b7e5e73 100644 --- a/tinymce-single/blocks/elements/lists/register.js +++ b/tinymce-single/blocks/elements/lists/register.js @@ -1,8 +1,8 @@ -window.wp.blocks.register( { +window.wp.blocks.registerBlock( { elements: [ 'ul', 'ol' ], type: 'text', icon: 'gridicons-list-unordered', - buttons: [ + controls: [ { icon: 'gridicons-list-unordered', stateSelector: 'ul', diff --git a/tinymce-single/blocks/elements/paragraph/register.js b/tinymce-single/blocks/elements/paragraph/register.js index a1a380cb17014..e4cba94e96a31 100644 --- a/tinymce-single/blocks/elements/paragraph/register.js +++ b/tinymce-single/blocks/elements/paragraph/register.js @@ -1,8 +1,8 @@ -window.wp.blocks.register( { +window.wp.blocks.registerBlock( { elements: [ 'p' ], type: 'text', icon: 'gridicons-posts', - buttons: [ + controls: [ { icon: 'gridicons-heading', onClick: function( editor ) { @@ -27,6 +27,8 @@ window.wp.blocks.register( { editor.formatter.apply( 'pre' ); } }, - 'text-align-center' + 'text-align-left', + 'text-align-center', + 'text-align-right' ] } ); diff --git a/tinymce-single/blocks/elements/preformatted/register.js b/tinymce-single/blocks/elements/preformatted/register.js index d6726e95b8523..342f4f4bb4719 100644 --- a/tinymce-single/blocks/elements/preformatted/register.js +++ b/tinymce-single/blocks/elements/preformatted/register.js @@ -1,8 +1,8 @@ -window.wp.blocks.register( { +window.wp.blocks.registerBlock( { elements: [ 'pre' ], type: 'text', icon: 'gridicons-code', - buttons: [ + controls: [ { icon: 'gridicons-cog' }, diff --git a/tinymce-single/blocks/index.js b/tinymce-single/blocks/index.js deleted file mode 100644 index 3babaea67f334..0000000000000 --- a/tinymce-single/blocks/index.js +++ /dev/null @@ -1,32 +0,0 @@ -( function( wp ) { - var _settings = {}; - - wp.blocks = { - register: function( settings ) { - // Note, elements should probably only be registered by core. - // Maybe for each block, we should offer to extend the settings (add buttons). - - if ( settings.elements ) { - settings.elements.forEach( function( element ) { - _settings[ 'element:' + element ] = settings; - _settings[ 'element:' + element ]._id = 'element:' + element; - } ); - } else if ( settings.namespace && settings.name ) { - _settings[ settings.namespace + ':' + settings.name ] = settings; - _settings[ settings.namespace + ':' + settings.name ]._id = settings.namespace + ':' + settings.name; - } - }, - getSettings: function( id ) { - return _settings[ id ]; - }, - getSettingsByElement: function( element ) { - var blockType = element.getAttribute( 'data-wp-block-type' ); - var nodeName = element.nodeName.toLowerCase(); - - return this.getSettings( blockType || 'element:' + nodeName ); - }, - getAllSettings: function() { - return _settings; - } - }; -} )( window.wp = window.wp || {} ); diff --git a/tinymce-single/blocks/my-awesome-plugin/youtube/register.js b/tinymce-single/blocks/my-awesome-plugin/youtube/register.js index 7e994a853c023..50339d14f1059 100644 --- a/tinymce-single/blocks/my-awesome-plugin/youtube/register.js +++ b/tinymce-single/blocks/my-awesome-plugin/youtube/register.js @@ -1,10 +1,10 @@ -window.wp.blocks.register( { +window.wp.blocks.registerBlock( { name: 'youtube', namespace: 'my-awesome-plugin', type: 'video', keywords: [], icon: 'gridicons-video', - buttons: [ + controls: [ 'block-align-left', 'block-align-center', 'block-align-right', diff --git a/tinymce-single/controls/align.js b/tinymce-single/controls/align.js new file mode 100644 index 0000000000000..bc533c11faf47 --- /dev/null +++ b/tinymce-single/controls/align.js @@ -0,0 +1,45 @@ +( function( wp, $ ) { + var RX_ALIGN_CLASSNAME = /^(text-align-|align)([\w-]+)/; + + function createOnClick( classNamePrefix, position ) { + return function( node ) { + return $( node ) + .removeClass( function( i, className ) { + return RX_ALIGN_CLASSNAME.test( className ) ? className : ''; + } ) + .addClass( classNamePrefix + position ); + }; + } + + function createIsActive( classNamePrefix, position ) { + return function( node ) { + var classNames = node.className.split( ' ' ), + i, className, match; + + for ( i = 0; i < classNames.length; i++ ) { + className = classNames[ i ]; + match = className.match( RX_ALIGN_CLASSNAME ); + + if ( match && classNamePrefix === match[ 1 ] ) { + return position === match[ 2 ]; + } + } + + return 'left' === position; + }; + } + + [ 'left', 'center', 'right' ].forEach( function( position ) { + wp.blocks.registerControl( 'text-align-' + position, { + icon: 'gridicons-align-' + position, + onClick: createOnClick( 'text-align-', position ), + isActive: createIsActive( 'text-align-', position ) + } ); + + wp.blocks.registerControl( 'block-align-' + position, { + icon: 'gridicons-align-image-' + position, + onClick: createOnClick( 'align', position ), + isActive: createIsActive( 'align', position ) + } ); + } ); +} )( window.wp = window.wp || {}, window.jQuery ); diff --git a/tinymce-single/index.html b/tinymce-single/index.html index 03d4a84dcadc5..ec847c8c1e06e 100644 --- a/tinymce-single/index.html +++ b/tinymce-single/index.html @@ -64,7 +64,11 @@

NASA discovers system of seven Earth-sized planets

- + + + + + @@ -74,8 +78,7 @@

NASA discovers system of seven Earth-sized planets

- - + diff --git a/tinymce-single/tinymce/block.js b/tinymce-single/tinymce/block.js index 477c7c6fa916e..713122b6f949b 100644 --- a/tinymce-single/tinymce/block.js +++ b/tinymce-single/tinymce/block.js @@ -1,73 +1,51 @@ -( function( tinymce, wp ) { +( function( tinymce, wp, _ ) { tinymce.PluginManager.add( 'block', function( editor ) { + var element; // Set focussed block. Global variable for now. Top-level node for now. editor.on( 'nodechange', function( event ) { - window.element = event.parents[ event.parents.length - 1 ]; + element = window.element = event.parents[ event.parents.length - 1 ]; } ); - // Global buttons. + // Global controls - tinymce.each( [ 'left', 'center', 'right' ], function( position ) { - editor.addButton( 'text-align-' + position, { - icon: 'gridicons-align-' + position, - cmd: 'text-align-' + position, - onClick: function() { - tinymce.each( [ 'left', 'center', 'right' ], function( position ) { - editor.$( element ).removeClass( 'text-align-' + position ); - } ); - - if ( position !== 'left' && ! this.active() ) { - editor.$( element ).addClass( 'text-align-' + position ); - } - - editor.nodeChanged(); - }, - onPostRender: function() { - var button = this; + function isNodeEligibleForControl( node, name ) { + var block; - editor.on( 'nodechange', function( event ) { - $element = editor.$( element ); + if ( ! node ) { + return false; + } - if ( position === 'left' ) { - button.active( ! ( - $element.hasClass( 'text-align-center' ) || $element.hasClass( 'text-align-right' ) - ) ); - } else { - button.active( $element.hasClass( 'text-align-' + position ) ); - } - } ); - } - } ); + block = wp.blocks.getBlockSettingsByElement( node ); + return block && _.includes( block.controls, name ); + } - editor.addButton( 'block-align-' + position, { - icon: 'gridicons-align-image-' + position, - cmd: 'block-align-' + position, - onClick: function() { - tinymce.each( [ 'left', 'center', 'right' ], function( position ) { - editor.$( element ).removeClass( 'align' + position ); - } ); + _.forEach( wp.blocks.getControls(), function( control, name ) { + var settings = { + icon: control.icon + }; - editor.$( element ).addClass( 'align' + position ); + if ( control.onClick ) { + settings.onClick = function() { + control.onClick( element ); editor.nodeChanged(); - }, - onPostRender: function() { - var button = this; + }; + } - editor.on( 'nodechange', function( event ) { - $element = editor.$( element ); + if ( control.isActive ) { + settings.onPostRender = function() { + var button = this; - if ( position === 'center' ) { - button.active( ! ( - $element.hasClass( 'alignleft' ) || $element.hasClass( 'alignright' ) - ) ); - } else { - button.active( $element.hasClass( 'align' + position ) ); + editor.on( 'nodechange', function() { + if ( isNodeEligibleForControl( element, name ) ) { + button.active( control.isActive( element ) ); } } ); - } - } ); + }; + } + + editor.addButton( name, settings ); } ); function addfigcaption() { @@ -135,7 +113,7 @@ editor.on( 'nodechange', function( event ) { var element = event.parents[ event.parents.length - 1 ]; - var settings = wp.blocks.getSettingsByElement( element ); + var settings = wp.blocks.getBlockSettingsByElement( element ); if ( settings ) { button.icon( settings.icon ); @@ -229,7 +207,7 @@ blockToolbar.$el.addClass( 'block-toolbar' ); function getInsertButtons() { - var allSettings = wp.blocks.getAllSettings(); + var allSettings = wp.blocks.getBlocks(); var buttons = []; var key; @@ -386,7 +364,8 @@ } function showBlockUI( focus ) { - var settings = wp.blocks.getSettingsByElement( element ); + var settings = wp.blocks.getBlockSettingsByElement( element ), + controls; if ( ! hasBlockUI ) { tinymce.$( editor.getBody() ).addClass( 'has-block-ui' ); @@ -403,7 +382,9 @@ if ( settings ) { if ( ! blockToolbars[ settings._id ] ) { - blockToolbars[ settings._id ] = editor.wp._createToolbar( settings.buttons ); + controls = settings.controls || []; + + blockToolbars[ settings._id ] = editor.wp._createToolbar( controls ); blockToolbars[ settings._id ].reposition = function () { if (!element) return @@ -665,4 +646,4 @@ } ); } ); } ); -} )( window.tinymce, window.wp ); +} )( window.tinymce, window.wp, window._ );