Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
description: How to create a custom category.
---

import Image from '@site/src/components/Image';

# Customizing a Blockly toolbox

## 3. Make a custom category

### Define and register a custom category

To start, create a file named `custom_category.js` in the `src` directory.

Then, add an `import` statement to `index.js` for this new file:

```js
import './custom_category.js';
```

In order to create a custom category, you will create a new category that extends
the default `Blockly.ToolboxCategory` class. Add the following code to your `custom_category.js` file:

```js
import * as Blockly from 'blockly';

class CustomCategory extends Blockly.ToolboxCategory {
/**
* Constructor for a custom category.
* @override
*/
constructor(categoryDef, toolbox, opt_parent) {
super(categoryDef, toolbox, opt_parent);
}
}
```

After defining your category you need to tell Blockly that it exists.
Register your category by adding the below code to the end of `custom_category.js`:

```js
Blockly.registry.register(
Blockly.registry.Type.TOOLBOX_ITEM,
Blockly.ToolboxCategory.registrationName,
CustomCategory,
true,
);
```

By registering our `CustomCategory` with `Blockly.ToolboxCategory.registrationName`
we are *overriding* the default category in Blockly. Because we are overriding a
toolbox item instead of adding a new one, we must pass in `true` as the last
argument. If this flag is `false`, `Blockly.registry.register` will throw
an error because we are overriding an existing class.

### The result

To test, save your files, then find the browser page that has the sample app.
You may also need to refresh the page. Your toolbox should look the same as it did before.

<Image
src="/images/codelabs/custom-toolbox/base_toolbox.png"
alt="The default toolbox. A list of categories with a strip of a different colour to the left of each category."
className="codelabImage"
/>

However, if you run the below commands in your console you will see that
your toolbox is now using the `CustomCategory` class.

```js
var toolbox = Blockly.common.getMainWorkspace().getToolbox();
toolbox.getToolboxItems()[0];
```

Although nothing has visually changed yet, this codelab will use the `CustomCategory` class
to change the appearance of the categories.
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,52 @@ import Image from '@site/src/components/Image';

# Customizing a Blockly toolbox

## 5. Add an icon to your category
## 6. Add an icon to your category

We are going to add an icon to our "Logic" category by adding an icon library to
our `index.html` file, and setting the appropriate CSS class on our category definition.

To start, we are going to grab an icon library and add it to `index.html`:
To start, we are going to grab an icon library and paste it to `index.html`, inside
the `<head>` element:

```
```html
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
```

We are going to add a cog icon from this library to the "Logic" category.
To do this, we will add the appropriate CSS classes to our category definition.
For a JSON toolbox definition like the one in `toolbox.js`, you'll use a `cssconfig` object.

In `index.html` scroll down to your toolbox definition and change the below line:
In `toolbox.js` scroll in to your toolbox definition and change the category with
the name "Logic":

```xml
<category name="Logic" categorystyle="logic_category">
```js
{
kind: 'category',
name: 'Logic',
categorystyle: 'logic_category',
contents: [ /* ...existing blocks ... */ ],
},
```

to be:

```xml
<category css-icon="customIcon fa fa-cog" name="Logic" categorystyle="logic_category">
```js
{
kind: 'category',
name: 'Logic',
categorystyle: 'logic_category',
cssconfig: { icon: 'customIcon fa fa-cog' },
contents: [ /* ...existing blocks... */ ],
},
```

All the classes used to create a category can be set similar to how we set the
icon class above. See the [Blockly toolbox documentation](/guides/configure/toolboxes/appearance#category-css) for more information.

### Add some CSS

If you open `index.html` you will notice that the gear icon is positioned
If you open the running app you will notice that the gear icon is positioned
incorrectly and is a bit difficult to see. We will use the `customIcon` class to
change the color of the icon and use the `blocklyTreeRowContentContainer` class
to position the icon above the text.
Expand All @@ -62,7 +76,7 @@ In your `toolbox_style.css` file add:

### Update setSelected

If you open `index.html` and click on the "Logic" category you will notice
If you open the running app and click on the "Logic" category you will notice
that the white icon now blends into the white background.

In order to fix this, we are going to update our `setSelected` method to set the
Expand All @@ -86,6 +100,8 @@ Your `setSelected` method should look similar to below:
```js
/** @override */
setSelected(isSelected){
super.setSelected(isSelected);

// We do not store the label span on the category, so use getElementsByClassName.
var labelDom = this.rowDiv_.getElementsByClassName('blocklyToolboxCategoryLabel')[0];
if (isSelected) {
Expand All @@ -101,15 +117,12 @@ Your `setSelected` method should look similar to below:
labelDom.style.color = 'white';
this.iconDom_.style.color = 'white';
}
// This is used for accessibility purposes.
Blockly.utils.aria.setState(/** @type {!Element} */ (this.htmlDiv_),
Blockly.utils.aria.State.SELECTED, isSelected);
}
```

### The result

If you open your `index.html` file, you should see a white gear above your "Logic"
If you open the running app, you should see a white gear above your "Logic"
label, and it should change to blue when the category has been selected.

<Image
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Image from '@site/src/components/Image';

# Customizing a Blockly toolbox

## 7. Adding a custom toolbox item
## 8. Adding a custom toolbox item

In the previous sections we modified the toolbox by extending the base category class.
In this section we will make a completely new toolbox item and add it to our toolbox.
Expand All @@ -15,18 +15,19 @@ For this example, we are going to create a toolbox label.

### Setup

In the same directory as `index.html` create a new file named `toolbox_label.js`.
In the same directory as `index.js` create a new file named `toolbox_label.js`.

Include this file in `index.html`:
Import this file in `index.js`:

```html
<script src="toolbox_label.js"></script>
```js
import './toolbox_label.js';
```

Create a class in `toolbox_label.js` that extends `Blockly.ToolboxItem`
and register it.
Create a class in `toolbox_label.js` that extends `Blockly.ToolboxItem` and register it.

```js
import * as Blockly from 'blockly';

class ToolboxLabel extends Blockly.ToolboxItem {
constructor(toolboxItemDef, parentToolbox) {
super(toolboxItemDef, parentToolbox);
Expand All @@ -43,21 +44,28 @@ Blockly.registry.register(
By registering this toolbox item with the name "toolboxlabel" we can now use this
name in our toolbox definition to add our custom item to the toolbox.

Navigate to `index.html`, and scroll down to the toolbox definition. Add a
`<toolboxlabel>` element as the first item in your toolbox definition:
Navigate to `toolbox.js`, and add a `toolboxlabel` as the first item in the list
of toolbox contents:

```xml
<toolboxlabel></toolboxlabel>
```js
{
kind: 'toolboxlabel',
}
```

Your toolbox definition should now look something like:

```xml
<xml xmlns="https://developers.google.com/blockly/xml" id="toolbox-categories" style="display: none">
<toolboxlabel></toolboxlabel>
<category css-icon="customIcon fa fa-cog" name="Logic" categorystyle="logic_category">
...
</xml>
```js
export const toolbox = {
kind: 'categoryToolbox',
contents: [
{
kind: 'toolboxlabel',
},
{ kind: 'category', name: 'Logic', /* etc */ },
// ...
]
}
```

### Initialize the toolbox item
Expand Down Expand Up @@ -91,11 +99,11 @@ Next, we are going to return this element:
}
```

If you open the `index.html` file you should see a label above your first category.
If you refresh the app page you should see a label above your first category.

<Image
src="/images/codelabs/custom-toolbox/toolbox_label.png"
alt="The toolbox with a label at the top."
alt='The toolbox with a label at the top that says "Label."'
className="codelabImage"
/>

Expand All @@ -106,11 +114,18 @@ label with the text "Label".
To make it possible to create different labels with different text and colour we
are going to add `name` and `colour` attributes to our toolbox definition.

Open `index.html` and navigate to the toolbox definition. Change your
`toolboxlabel` element to look like the below line:
Open `toolbox.js`. Add a `name` and `colour` to your toolbox label

```xml
<toolboxlabel name="Custom Toolbox" colour="darkslategrey"></toolboxlabel>
```js
contents: [
{
kind: 'toolboxlabel',
name: 'Custom Toolbox',
colour: 'darkslategrey',
},
{ kind: 'category', name: 'Logic', /* etc */ },
// ...
]
```

These values will get passed in to our `ToolboxLabel` class through the `toolboxItemDef`.
Expand All @@ -132,7 +147,7 @@ this.label.textContent = 'Label';
All attributes on our toolbox definition get added to the `toolboxItemDef_`.
`this.toolboxItemDef_` is set in the `Blockly.ToolboxItem` constructor.

Open your `index.html` in a browser to see the updated label.
Refresh your app in a browser to see the updated label.

<Image
src="/images/codelabs/custom-toolbox/custom_label.png"
Expand All @@ -145,21 +160,27 @@ Open your `index.html` in a browser to see the updated label.
Similar to how we added `colour` and `name` above, we are going to add a custom
class to our label.

Navigate to your toolbox definition in `index.html` and modify it to look
like the below line.
Navigate to your toolbox definition in `toolbox.js` and add the `cssconfig`.

```xml
<toolboxlabel name="Custom Toolbox" colour="darkslategrey" css-label="customLabel"></toolboxlabel>
```js
contents: [
{
kind: 'toolboxlabel',
name: 'Custom Toolbox',
colour: 'darkslategrey',
cssconfig: { label: 'customLabel' },
},
{ kind: 'category', name: 'Logic', /* etc */ },
// ...
]
```

Any item that begins with `css-` will be added to a `cssconfig` object stored on
the `toolboxItemDef`.
This gets added to a `cssconfig` object stored on the `toolboxItemDef`.

To use this value navigate to `toolbox_label.js` and add the following lines to
your `init` method.

```js
// Any attributes that begin with css- will get added to a cssconfig object.
const cssConfig = this.toolboxItemDef_['cssconfig'];
// Add the class.
if (cssConfig) {
Expand All @@ -178,11 +199,11 @@ the below CSS to make the label bold.

### The result

If you open `index.html` you should now see a bold dark gray label at the
If you refresh your app you should now see a bold dark gray label at the
top of your toolbox.

<Image
src="/images/codelabs/custom-toolbox/final_toolbox.png"
alt="A toolbox with colored background and the blockly label above the category text."
alt="The toolbox with a label that is now bolded."
className="codelabImage"
/>
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Image from '@site/src/components/Image';

# Customizing a Blockly toolbox

## 6. Change the category HTML
## 7. Change the category HTML

If you only need to change the CSS, like we did in the previous section, then using the cssConfig is a great choice.
However, if you need to change the html, maybe to add text, an image, or anything else, you can override
Expand All @@ -16,29 +16,27 @@ to our category by overriding the `createIconDom_` method.
### Change the element for our icon

By default, the `createIconDom_` method adds a `<span>` element for the category
icon. We can override this to return an `<img>` element.
icon. Note that you can override this to create other types of elements, if needed.

Add the following methods to `custom_category.js`:
Add the following method to `custom_category.js`:

```js
/** @override */
createIconDom_() {
const img = document.createElement('img');
img.src = './logo_only.svg';
img.alt = 'Lamp';
img.width='15';
img.height='15';
return img;
const icon = document.createElement('span');
icon.textContent = '🧰';
return icon;
}
```

### The result

If you open `index.html` you should now see the blockly logo on top of all your
categories
If you refresh the running app, you should now see the toolbox emoji on top of all your categories.
Keep in mind, this method of changing the HTML changed it for *all* categories.
This means that you have effectively removed the custom gear icon that was previously on your "Logic" category.

<Image
src="/images/codelabs/custom-toolbox/image_toolbox.png"
alt="A toolbox with the blockly logo on top of the category label."
alt="A toolbox with a toolbox emoji on top of the category label."
className="codelabImage"
/>
Loading