# 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.

## Installation

Install the module

```bash
npm install @wordpress/bocks --save
```

_This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for ES2015+ such as lower versions of IE then using [core-js](https://github.com/zloirock/core-js) or [@babel/polyfill](https://babeljs.io/docs/en/next/babel-polyfill) will add support for these methods. Learn more about it in [Babel docs](https://babeljs.io/docs/en/next/caveats)._

## 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 | Object` - 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.
  An object can also be passed, in this case, icon, as specified above, should be included in the src property.
  Besides src the object can contain background and foreground colors, this colors will appear with the icon
  when they are applicable e.g.: in the inserter.
- `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.


<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p>
