Skip to content

Instantly share code, notes, and snippets.

@babette-landmesser
Created March 21, 2020 17:49
Show Gist options
  • Save babette-landmesser/a604ea8ad4b57dc40a0a51c680cbeab8 to your computer and use it in GitHub Desktop.
Save babette-landmesser/a604ea8ad4b57dc40a0a51c680cbeab8 to your computer and use it in GitHub Desktop.
/**
* BLOCK: media-text-teaser
*
* Registering a basic block with Gutenberg.
* Simple block, renders and saves the same content without any interactivity.
*/
import React from 'react';
import { Toolbar } from '@wordpress/components';
// Import CSS.
import './editor.scss';
import './style.scss';
import pullLeft from './assets/pull-left';
import pullRight from './assets/pull-right';
const { __, _x } = wp.i18n; // Import __() from wp.i18n
const { registerBlockType } = wp.blocks; // Import registerBlockType() from wp.blocks
const { MediaUpload, PlainText, MediaPlaceholder, InnerBlocks, BlockControls } = wp.blockEditor;
const TEMPLATE = [
[
'core/paragraph',
{
placeholder: _x( 'Content…', 'content placeholder' ),
},
],
];
/**
* Register: a Gutenberg Block.
*
* Registers a new block provided a unique name and an object defining its
* behavior. Once registered, the block is made editor as an option to any
* editor interface where blocks are implemented.
*
* @link https://wordpress.org/gutenberg/handbook/block-api/
* @param {string} name Block name.
* @param {Object} settings Block settings.
* @return {?WPBlock} The block, if it has been successfully
* registered; otherwise `undefined`.
*/
registerBlockType( 'media-text-teaser', {
// Block name. Block names must be string that contains a namespace prefix. Example: my-plugin/my-custom-block.
title: __( 'Media Text Teaser' ), // Block title.
icon: 'shield', // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/.
category: 'common', // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed.
keywords: [
__( 'media' ),
__( 'text' ),
],
attributes: {
title: {
type: 'string',
source: 'text',
selector: '.teaser__title'
},
imageAlt: {
attribute: 'alt',
selector: '.teaser__image'
},
imageUrl: {
attribute: 'src',
selector: '.teaser__image'
},
mediaPosition: {
type: 'string',
default: 'left',
},
},
/**
* The edit function describes the structure of your block in the context of the editor.
* This represents what the editor will render when the block is used.
*
* The "edit" property must be a valid function.
*
* @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/
*
* @param {Object} props Props.
* @returns {Mixed} JSX Component.
*/
edit: ( {attributes, className, setAttributes} ) => {
const toggleImagePlaceholder = (openEvent) => {
if(attributes.imageUrl) {
return (
<img
src={ attributes.imageUrl }
onClick={ openEvent }
className="image"
/>
);
}
else {
return (
<MediaPlaceholder
onSelect = { media => { setAttributes({ imageAlt: media.alt, imageUrl: media.url }); } }
allowedTypes = { [ 'image' ] }
multiple = { false }
labels = { { title: 'Bildupload' } }
>
</MediaPlaceholder>
);
}
};
const toolbarControls = [
{
icon: pullLeft,
title: __( 'Show media on left' ),
isActive: attributes.mediaPosition === 'left',
onClick: () => setAttributes( { mediaPosition: 'left' } ),
},
{
icon: pullRight,
title: __( 'Show media on right' ),
isActive: attributes.mediaPosition === 'right',
onClick: () => setAttributes( { mediaPosition: 'right' } ),
},
];
className += ' is-image-' + attributes.mediaPosition;
return (
<React.Fragment>
<BlockControls>
<Toolbar controls={ toolbarControls } />
</BlockControls>
<div className={className}>
<PlainText
onChange={ content => setAttributes({ title: content }) }
value={ attributes.title }
placeholder={ __( 'Teaser Title') }
className="heading"
/>
<div className="col__2 col--image">
<MediaUpload
onSelect={ media => { setAttributes({ imageAlt: media.alt, imageUrl: media.url }); } }
type="image"
value={ attributes.imageID }
render={ ({ open }) => toggleImagePlaceholder(open) }
/>
</div>
<div className="col__2 col--text">
<InnerBlocks template={ TEMPLATE } />
</div>
</div>
</React.Fragment>
);
},
/**
* The save function defines the way in which the different attributes should be combined
* into the final markup, which is then serialized by Gutenberg into post_content.
*
* The "save" property must be specified and must be a valid function.
*
* @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/
*
* @param {Object} props Props.
* @returns {Mixed} JSX Frontend HTML.
*/
save: ({ attributes }) => {
const cardImage = (src, alt) => {
if(!src) return null;
if(alt) {
return (
<img
className="teaser__image"
src={ src }
alt={ alt }
/>
);
}
// No alt set
return (
<img
className="teaser__image"
src={ src }
alt=""
/>
);
};
const className = 'teaser is-' + attributes.mediaPosition;
return (
<div className={ className }>
<h3 className="teaser__title">{ attributes.title }</h3>
<div className="col__2">
{ cardImage(attributes.imageUrl, attributes.imageAlt) }
</div>
<div className="col__2">
<InnerBlocks.Content />
</div>
</div>
);
},
} );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment