[MUSIC]
Hello! My name is Abby Schmiedt and I am a software engineer at Google where I work on
the Blockly team. Over the past couple of years we have talked a lot about moving away from
a model where developers fork Blockly and directly modify parts of core.
One of the questions that generally arises when we talk about this is
“How am I going to create this awesome new feature without modifying core?”. In this talk I am going
to go through some different ways developers can customize Blockly using our provided APIs.
I won’t get through all of them but I am planning to point out some resources and common patterns
that will hopefully give you a starting place when creating your next awesome feature.
First up we are going to talk about plugins. Plugins are a great first place to look to
see if the feature you want has already been created. If you want to browse the
plugins I would recommend heading over to the github.io site for samples. There is a link
to it in the connected slides. Each plugin page has a playground where you can play around with
the plugin as well as a link to a readme where you can find more information on how you can customize
each plugin. If you would like to modify a plugin in a way that is not currently available feel free
to ask us about it on the forum or add an issue about it on the blockly samples repository.
Next up we are talking about inject options. This is probably the most straightforward way to
configure Blockly. These are a set of options that you can change when you first create the
blockly workspace. The ‘Injection Options’ are pretty wel documented so I am going to
skim over these a bit but there is a link to the documentation in these slides.
If you prefer a more hands on approach to testing out the options you can go
to the advanced playground and see these options updated in real time.
Next up is injecting a class. This is definitely a more heavyweight way to customize Blockly but it
also provids you with a lot of freedom. We offer a subset of classes that can be overridden or
completely replaced. The list of these classes can be found on the Using Blockly APIs page.
If the class you want to change is in this list you can either extend from our base class
or completely substitute in your own class that implements the corresponding interface.
If you end up extending the base class you can use anything that is public or protected in
that class. When subclassing we highly recommend that you try your hardest to not copy and paste
large chunks of code from the base class into your class. Doing so will make it more
difficult to maintain in the future. When this is not possible feel free to leave us
an issue or a forum post describing what you are trying to do and why it is not working.
Once you have created your class, you can simply add it to the inject options and you are all set.
Where we were previously creating our class we will instead use your class.
If you are planning on using JSON.stringify to save your injection options you can
register your class and use the name you register it under instead.
Ok, next up we are going to be talking about registries.
Registries comes up quite a bit in our documentation when looking at how to
customize Blockly so I wanted to spend some time talking about the different ways we use them.
We generally use registries for two reasons. The first being what we just
talked about which is to be able to go from a class or object to a string that
can be used in definition that you as the developer are creating. For example,
you can register custom fields so that they can be used in your json block definitions. Similarly,
you can register toolbox items so that they can be used in either a json or xml toolbox definition
and you can register injected classes so they can be used in the inject options.
The key here being that when you register items that fall in this category it is up to you to use
them. We won’t do anything internally with these unless you use them in some kind of definition.
The second way we use registries is that we take some collection of objects that
you have provided us with and we use that information internally to make decisions.
For example, the context menu registry takes in an object and then uses the properties
on the object to make decisions about when we should show your context menu item,
where it should be placed in the menu, and what action should be run when a user clicks on the
item. The key here is that all you have to do for this to work is register your item.
Now that we know a bit more about registries, I’m going to dive into a few concrete examples.
First up we are going to be taking a look at the context menu API.
The context menu is displayed when a user right clicks on a block or on a workspace.
The context menu registry lets you add and remove custom context menu items.
All you have to do in order to add a new context menu item is create an object with
all the necessary properties and register it. More information on the properties required can
be found in the context menu registry documentation linked on this slide. We
offer a default set of context menu items that can be removed by unregistering them.
The keyboard shortcut registry is very similar to the context menu registry. It allows developers
to run an action when certain keys have been pressed. The difference here is that once you
have registered your shortcut you also need to create a serialized key with information about any
modifier keys that should be used with the primary key code. Once you have a serialized key you can
add that key mapping into the registry. Multiple key mappings can be added for each shortcut.
Shifting away from registries a bit, the other way developers can customize
Blockly is by setting functions directly on a class or namespace.
The most recent example of this is the new tooltip API that Maribeth added in version 8 of Blockly.
Developers can change the look of the tooltip that shows up when a block is moused over
by creating a function that takes in the div where the tooltip will be rendered
and the element that is being moused over and then passing that function to setCustomTooltip.
Next up is events! I think events are often overlooked as a way to customize Blockly,
but you can actually do quite a lot by listening to events. Events are pretty well documented
on our developer page, but if you would rather play around with them you can go
to the advanced playground, open the actions section and click the ‘Log events’ button.
This will log any events emitted to the console. Just a reminder that the flyout
is actually a different workspace, so if you would like to see what events
are emitted in the flyout you have to check the ‘Log flyout events’ button.
I am adding this section mostly for completeness. Hopefully it is not a
surprise that Blockly lets you create custom blocks, generators and fields. All of these
are pretty well documented so I am just going to add some links that might be helpful to look at.
I will also note that the blockly developer tools can be a bit difficult to get used to,
but once you do they are very helpful for figuring out what blocks will look like.
I have left out quite a few APIs that are available for the sake of time, so I will
leave you with this. If you have looked through the documentation and are still having issues feel
free to ask on the developer forum. Our team or other active members on the forum can either point
you to a good place to start or let you know that you should create an issue for what you are
looking for. And finally, sometimes there is not a great way to create the feature you want on top of
Blockly. If that is the case, again let us know. It is not always appropriate for us to create
your exact feature in core or samples, but if we know what you are trying to accomplish we can try
to create an API that will at least allow you to do what you want without having to fork Blockly.
Thank you!