Table of contents

The first plugin

We'll build the Simple Image plugin that will allow us to add images to our articles. You can view the final result of the plugin.

At first, we need to create some files where we will develop and test our new Tool. Create a folder with these three files:

/simple-image ├╴ simple-image.js ├╴ simple-image.css └╴ example.html

In example.html we will test our plugin, so let's add some markup and connect Editor.js there:

<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script> <script src="simple-image.js"></script> <link href="simple-image.css" rel="stylesheet"/> <div id="editorjs"></div> <script> const editor = new EditorJS({ autofocus: true }); </script>

If you open this page in a browser, you'll see an empty Editor with the only internal Paragraph Tool available. Now we a ready to start creating our own plugin.

Ok, let's get started with creating a JavaScript class for our Tool in simple-image.js file.

class SimpleImage { }

We need at least of two methods to create a Block Tool for Editor.js — render and save.

The render method will create a UI of a Block that will be appended when our Tool will be selected from the Toolbox. The second method, save will extract the Block's data from that UI.

Our UI will be quite simple: just an input in which users will paste an image URL. So let's implement a render method:

class SimpleImage { render(){ return document.createElement('input'); } }

Then we need to provide a save method for extracting a Block data from the UI:

class SimpleImage { render(){ return document.createElement('input'); } save(blockContent){ return { url: blockContent.value } } }

On saving, Editor.js will pass Block's content to the save method and we should implement the logic of which data we should save by our Tool. Block content is the Element returned by render with actual state of that.

So in our case, we just need to get input's value and return our Tool's data object:

{ url: '//pasted-image-url.png' }

We will add a «caption» and other fields to our Block later.

Our Block Plugin is almost done. To make that appear at the Toolbox, we should provide an icon and a title with a static getter toolbox.

class SimpleImage { static get toolbox() { return { title: 'Image', icon: '<svg width="17" height="15" viewBox="0 0 336 276" xmlns="http://www.w3.org/2000/svg"><path d="M291 150V79c0-19-15-34-34-34H79c-19 0-34 15-34 34v42l67-44 81 72 56-29 42 30zm0 52l-43-30-56 30-81-67-66 39v23c0 19 15 34 34 34h178c17 0 31-13 34-29zM79 0h178c44 0 79 35 79 79v118c0 44-35 79-79 79H79c-44 0-79-35-79-79V79C0 35 35 0 79 0z"/></svg>' }; } render(){ return document.createElement('input'); } save(blockContent){ return { url: blockContent.value } } }

Our Tool is ready. It's time to connect it with the Editor.

Let's add a tools property to the configuration object at the example.html.

<script> const editor = new EditorJS({ autofocus: true, tools: { image: SimpleImage } }); </script>

Open example.html in a browser: if everything is fine, you will see a Plus Button of a Toolbox. Press Tab or click on the Plus Button and our Tool will be there.

Our new Tool is ready to use. Icon and title got from the toolbox getter.
Our new Tool is ready to use. Icon and title got from the toolbox getter.

After you select an Image Tool, the render will be called and returned input will be placed as a new Block. You can add some CSS classes to it and place styles at simple-image.css file.

To the final test, we need to check how saving method works. Add a Save-button and output-zone to the example.html

<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script> <script src="simple-image.js"></script> <link href="simple-image.css" rel="stylesheet"/> <div id="editorjs"></div> <button id="save-button">Save</button> <pre id="output"></pre> <script> const editor = new EditorJS({ autofocus: true, tools: { image: SimpleImage } }); const saveButton = document.getElementById('save-button'); const output = document.getElementById('output'); saveButton.addEventListener('click', () => { editor.save().then( savedData => { output.innerHTML = JSON.stringify(savedData, null, 4); }) }) </script>

Now everything is ready. You can add Image Block at Editor, paste image URL and click on the Save button. In output zone you will see saved Editor.js data:

{ "time": 1552744582955, "blocks": [ { "type": "image", "data": { "url": "https://cdn.pixabay.com/photo/2017/09/01/21/53/blue-2705642_1280.jpg" } } ], "version": "2.11.10" }

We've created some preparation stuff for our playground, but actually all you need to create a Block Tool plugin is the simplest save and render methods. If you want to put your Tool in Toolbox, static getter toolbox with the icon and the title allows you to do that. 

In the next chapter, we'll learn how to show previously saved data of our tool.