# Blocks

"Block" is the abstract term used to describe units of markup that, composed
together, form the content or layout of a webpage. The idea combines concepts
of what in WordPress today we achieve with shortcodes, custom HTML, and embed
discovery into a single consistent API and user experience.

For more context, refer to
[_What Are Little Blocks Made Of?_](https://make.wordpress.org/design/2017/01/25/what-are-little-blocks-made-of/)
from the
[Make WordPress Design](https://make.wordpress.org/design/)
blog.

The following documentation outlines steps you as a developer will need to
follow to add your own custom blocks to WordPress's editor interfaces.

## Getting Started

If you're not already accustomed to working with JavaScript in your WordPress
plugins, you may first want to reference the guide on
[_Including CSS & JavaScript_](https://developer.wordpress.org/themes/basics/including-css-javascript/)
in the Theme Handbook.

At a minimum, you will need to enqueue scripts for your block as part of a
`enqueue_block_editor_assets` action callback, with a dependency on the
`wp-blocks` and `wp-element` script handles:

```php
<?php
// myplugin.php

function myplugin_enqueue_block_editor_assets() {
	wp_enqueue_script(
		'myplugin-block',
		plugins_url( 'block.js', __FILE__ ),
		array( 'wp-blocks', 'wp-element' )
	);
}
add_action( 'enqueue_block_editor_assets', 'myplugin_enqueue_block_editor_assets' );
```

The `enqueue_block_editor_assets` hook is only run in the Gutenberg editor
context when the editor is ready to receive additional scripts and stylesheets.
There is also an `enqueue_block_assets` hook which is run under __both__ the
editor and front-end contexts.  This should be used to enqueue stylesheets
common to the front-end and the editor.  (The rules can be overridden in the
editor-specific stylesheet if necessary.)

The following sections will describe what you'll need to include in `block.js`
to describe the behavior of your custom block.

Note that all JavaScript code samples in this document are enclosed in a
function that is evaluated immediately afterwards.  We recommend using either
ES6 modules
[as used in this project](https://wordpress.org/gutenberg/handbook/reference/coding-guidelines/#imports)
(documentation on setting up a plugin with Webpack + ES6 modules coming soon)
or these
["immediately-invoked function expressions"](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression)
as used in this document.  Both of these methods ensure that your plugin's
variables will not pollute the global `window` object, which could cause
incompatibilities with WordPress core or with other plugins.

## Example

Let's imagine you wanted to define a block to show a randomly generated image
in a post's content using
[lorempixel.com](http://lorempixel.com/).
The service provides a choice of category and you'd like to offer this as an
option when editing the post.

Take a step back and consider the ideal workflow for adding a new random image:

- Insert the block.  It should be shown in some empty state, with an option to choose a category in a select dropdown.
- Upon confirming my selection, a preview of the image should be shown next to the dropdown.

At this point, you might realize that while you'd want some controls to be
shown when editing content, the markup included in the published post might not
appear the same (your visitors should not see a dropdown field when reading
your content).

This leads to the first requirement of describing a block:

__You will need to provide implementations both for what's to be shown in an
editor and what's to be saved with the published content__.

To eliminate redundant effort here, share common behaviors by splitting your
code up into
[components](../element).

Now that we've considered user interaction, you should think about the
underlying values that determine the markup generated by your block. In our
example, the output is affected only when the category changes. Put another
way: __the output of a block is a function of its attributes__.

The category, a simple string, is the only thing we require to be able to
generate the image we want to include in the published content. We call these
underlying values of a block instance its __attributes__.

With these concepts in mind, let's explore an implementation of our random
image block:

```php
<?php
// random-image.php

function random_image_enqueue_block_editor_assets() {
	wp_enqueue_script(
		'random-image-block',
		plugins_url( 'block.js', __FILE__ ),
		array( 'wp-blocks', 'wp-element' )
	);
}
add_action( 'enqueue_block_editor_assets', 'random_image_enqueue_block_editor_assets' );
```

```js
// block.js
( function( blocks, element ) {
	var el = element.createElement,
		source = blocks.source;

	function RandomImage( props ) {
		var src = 'http://lorempixel.com/400/200/' + props.category;

		return el( 'img', {
			src: src,
			alt: props.category
		} );
	}

	blocks.registerBlockType( 'myplugin/random-image', {
		title: 'Random Image',

		icon: 'format-image',

		category: 'common',

		attributes: {
			category: {
				type: 'string',
				source: 'attribute',
				attribute: 'alt',
				selector: 'img',
			}
		},

		edit: function( props ) {
			var category = props.attributes.category,
				children;

			function setCategory( event ) {
				var selected = event.target.querySelector( 'option:checked' );
				props.setAttributes( { category: selected.value } );
				event.preventDefault();
			}

			children = [];
			if ( category ) {
				children.push( RandomImage( { category: category } ) );
			}

			children.push(
				el( 'select', { value: category, onChange: setCategory },
					el( 'option', null, '- Select -' ),
					el( 'option', { value: 'sports' }, 'Sports' ),
					el( 'option', { value: 'animals' }, 'Animals' ),
					el( 'option', { value: 'nature' }, 'Nature' )
				)
			);

			return el( 'form', { onSubmit: setCategory }, children );
		},

		save: function( props ) {
			return RandomImage( { category: props.attributes.category } );
		}
	} );
} )(
	window.wp.blocks,
	window.wp.element
);
```

_[(Example in ES2015+, JSX)](https://gist.github.com/aduth/fb1cc9a2296110a62b96383e4b2e8a7c)_

Let's briefly review a few items you might observe in the implementation:

- When registering a new block, you must prefix its name with a namespace for
  your plugin. This helps prevent conflicts when more than one plugin registers
  a block with the same name.
- You will use `createElement` to describe the structure of your block's
  markup. See the [Element documentation](../element/README.md) for more
  information.
- Extracting `RandomImage` to a separate function allows us to reuse it in both
  the editor-specific interface and the published content.
- The `edit` function should handle any case where an attribute is unset, as in
  the case of the block being newly inserted.
- We only change the attributes of a block by calling the `setAttributes`
  helper. Never assign a value on the attributes object directly.
- React provides conveniences for working with `select` element with
  [`value` and `onChange` props](https://facebook.github.io/react/docs/forms.html#the-select-tag).

By concerning yourself only with describing the markup of a block given its
attributes, you need not worry about maintaining the state of the page, or how
your block interacts in the context of the surrounding editor.

But how does the markup become an object of attributes? We need a pattern for
encoding the values into the published post's markup, and then retrieving them
the next time the post is edited. This is the motivation for the block's
`attributes` property. The shape of this object matches that of the attributes
object we'd like to receive, where each value is a
[__source__](http://github.com/aduth/hpq)
which tries to find the desired value from the markup of the block.

In the random image block above, we've given the `alt` attribute of the image a
secondary responsibility of tracking the selected category. There are a few
other ways we could have achieved this, but the category value happens to work
well as an `alt` descriptor. In the `attributes` property, we define an object
with a key of `category` whose value tries to find this `alt` attribute of the
markup. If it's successful, the category's value in our `edit` and `save`
functions will be assigned. In the case of a new block or invalid markup, this
value would be `undefined`, so we adjust our return value accordingly.

## API

### `wp.blocks.registerBlockType( name: string, typeDefinition: Object )`

Registers a new block provided a unique name and an object defining its
behavior. Once registered, the block is made available as an option to any
editor interface where blocks are implemented.

- `title: string` - A human-readable
  [localized](https://codex.wordpress.org/I18n_for_WordPress_Developers#Handling_JavaScript_files)
  label for the block. Shown in the block inserter.
- `icon: string | WPElement | Function` - Slug of the
  [Dashicon](https://developer.wordpress.org/resource/dashicons/#awards)
  to be shown in the control's button, or an element (or function returning an
  element) if you choose to render your own SVG.
- `attributes: Object | Function` - An object of attribute schemas, where the
  keys of the object define the shape of attributes, and each value an object
  schema describing the `type`, `default` (optional), and
  [`source`](https://wordpress.org/gutenberg/handbook/block-api/attributes/)
  (optional) of the attribute. If `source` is omitted, the attribute is
  serialized into the block's comment delimiters. Alternatively, define
  `attributes` as a function which returns the attributes object.
- `category: string` - Slug of the block's category. The category is used to
  organize the blocks in the block inserter.
- `edit( { attributes: Object, setAttributes: Function } ): WPElement` -
  Returns an element describing the markup of a block to be shown in the
  editor. A block can update its own state in response to events using the
  `setAttributes` function, passing an object of properties to be applied as a
  partial update.
- `save( { attributes: Object } ): WPElement` - Returns an element describing
  the markup of a block to be saved in the published content. This function is
  called before save and when switching to an editor's HTML view.
- `keywords` - An optional array of keywords used to filter the block list.

### `wp.blocks.getBlockType( name: string )`

Returns type definitions associated with a registered block.

### `wp.blocks.getControlSettings( name: string )`

Returns settings associated with a registered control.

## Components

Because many blocks share the same complex behaviors, the following components
are made available to simplify implementations of your block's `edit` function.

### `BlockControls`

When returned by your block's `edit` implementation, renders a toolbar of icon
buttons. This is useful for block-level modifications to be made available when
a block is selected. For example, if your block supports alignment, you may
want to display alignment options in the selected block's toolbar.

Example:

```js
( function( blocks, element ) {
	var el = element.createElement,
		BlockControls = blocks.BlockControls,
		AlignmentToolbar = blocks.AlignmentToolbar;

	function edit( props ) {
		return [
			// Controls: (only visible when block is selected)
			el( BlockControls, { key: 'controls' },
				el( AlignmentToolbar, {
					value: props.align,
					onChange: function( nextAlign ) {
						props.setAttributes( { align: nextAlign } )
					}
				} )
			),

			// Block content: (with alignment as attribute)
			el( 'p', { key: 'text', style: { textAlign: props.align } },
				'Hello World!'
			),
		];
	}
} )(
	window.wp.blocks,
	window.wp.element
);
```

Note in this example that we render `AlignmentToolbar` as a child of the
`BlockControls` element. This is another pre-configured component you can use
to simplify block text alignment.

Alternatively, you can create your own toolbar controls by passing an array of
`controls` as a prop to the `BlockControls` component. Each control should be
an object with the following properties:

- `icon: string` - Slug of the Dashicon to be shown in the control's toolbar button
- `title: string` - A human-readable localized text to be shown as the tooltip label of the control's button
- `subscript: ?string` - Optional text to be shown adjacent the button icon as subscript (for example, heading levels)
- `isActive: ?boolean` - Whether the control should be considered active / selected. Defaults to `false`.

To create divisions between sets of controls within the same `BlockControls`
element, passing `controls` instead as a nested array (array of arrays of
objects). A divider will be shown between each set of controls.

### `RichText`

Render a rich
[`contenteditable` input](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Editable_content),
providing users the option to add emphasis to content or links to content. It
behaves similarly to a
[controlled component](https://facebook.github.io/react/docs/forms.html#controlled-components),
except that `onChange` is triggered less frequently than would be expected from
a traditional `input` field, usually when the user exits the field.

The following properties (non-exhaustive list) are made available:

- `value: string` - Markup value of the field. Only valid markup is
  allowed, as determined by `inline` value and available controls.
- `onChange: Function` - Callback handler when the value of the field changes,
  passing the new value as its only argument.
- `placeholder: string` - A text hint to be shown to the user when the field
  value is empty, similar to the
  [`input` and `textarea` attribute of the same name](https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/HTML5_updates#The_placeholder_attribute).
- `multiline: String` - A tag name to use for the tag that should be inserted
  when Enter is pressed.  For example: `li` in a list block, and `p` for a
	block that can contain multiple paragraphs.  The default is that only inline
	elements are allowed to be used in inserted into the text, effectively
  disabling the behavior of the "Enter" key.

Example:

```js
( function( blocks, element ) {
	var el = element.createElement,
		RichText = blocks.RichText;

	function edit( props ) {
		function onChange( value ) {
			props.setAttributes( { text: value } );
		}

		return el( RichText, {
			value: props.attributes.text,
			onChange: onChange
		} );
	}

	// blocks.registerBlockType( ..., { edit: edit, ... } );
} )(
	window.wp.blocks,
	window.wp.element
);
```
