Blockly has two ways of defining blocks: JSON objects, which use key-value pairs, and JavaScript functions, which call Blockly's API. The JSON format is preferred because it simplifies localization and is easier to read and write. However, it cannot be used to directly define advanced features such as mutators or validators. These must be written in JavaScript, usually as extensions.
Use JSON or JavaScript
This block:
can be defined in JSON or JavaScript as follows.
JSON
Blockly.common.defineBlocksWithJsonArray([{
"type": "string_length",
"message0": 'length of %1',
"args0": [
{
"type": "input_value",
"name": "VALUE",
"check": "String"
}
],
"output": "Number",
"colour": 160,
"tooltip": "Returns number of letters in the provided text.",
"helpUrl": "http://www.w3schools.com/jsref/jsref_length_string.asp"
}]);
defineBlocksWithJsonArray
converts each JSON object into a block
definition object
with an init
function. It stores these objects in Blockly.Blocks
.
JavaScript
Blockly.Blocks['string_length'] = {
init: function() {
this.appendValueInput('VALUE')
.setCheck('String')
.appendField('length of');
this.setOutput(true, 'Number');
this.setColour(160);
this.setTooltip('Returns number of letters in the provided text.');
this.setHelpUrl('http://www.w3schools.com/jsref/jsref_length_string.asp');
}
};
Because block definition
objects are
mixed in to block objects, the keyword this
refers to the actual block
being created.
Both methods result in a block definition object being stored in
Blockly.Blocks
with a key of the block type name (string_length
). The block
definition object has a single method (init
), which defines the block's shape.
Mix JSON and JavaScript
The JSON format primarily supports defining the look and feel of a block. It cannot directly define some features, such as validators and mutators, which require you to define a function. To solve this problem, define as much of your block with JSON as possible, and use JavaScript for the rest.
The following example creates a block definition with an init
function, which
uses jsonInit
to load a JSON object and the JavaScript API to define a dynamic
tooltip.
JavaScript
// Define the block structure in JSON.
var mathChangeJson = {
"message0": "change %1 by %2",
"args0": [
{"type": "field_variable", "name": "VAR", "variable": "item", "variableTypes": [""]},
{"type": "input_value", "name": "DELTA", "check": "Number"}
],
"previousStatement": null,
"nextStatement": null,
"colour": 230
};
Blockly.Blocks['math_change'] = {
init: function() {
// Use jsonInit to load the JSON block structure.
this.jsonInit(mathChangeJson);
// Use JavaScript to define a tooltip function.
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
return 'Add a number to variable "%1".'.replace('%1',
thisBlock.getFieldValue('VAR'));
});
}
};
Block definition API
This section summarizes the objects and functions used to define custom blocks.
Blockly.Blocks
Blockly.Blocks
is an object
that stores block definitions. Its keys are block type names and its values are
block definition objects. Use Blockly.Blocks
when defining blocks with
JavaScript:
Blockly.Blocks['my_block'] = {
init: function() {/* ... */},
onchange: function() {/* ... */},
// ...
}
A common error is to assume Blockly.Blocks
stores blocks and try something
like the following. This fails because Blockly.Blocks
stores block
definitions, not blocks.
// Fails with "Blockly.Blocks.my_block.setColour is not a function".
Blockly.Blocks['my_block'].setColour(150);
defineBlocksWithJsonArray
defineBlocksWithJsonArray
accepts an array of JSON objects, creates block definitions from them, and adds
them to Blockly.Blocks
.
Blockly.common.defineBlocksWithJsonArray([
{
type: 'my_block1',
// ...
}
{
type: 'my_block3',
// ...
}
{
type: 'my_block2',
// ...
}
]);
createBlockDefinitionsFromJsonArray and defineBlocks
createBlockDefinitionsFromJsonArray
accepts an array of JSON objects and returns an object that maps block type
names to block definitions. This is generally used with defineBlocks
, which
adds the block definitions to Blockly.Blocks
.
const myBlockDefinitions = Blockly.createBlockDefinitionsFromJsonArray([
{
type: 'my_block1',
// ...
}
{
type: 'my_block3',
// ...
}
{
type: 'my_block2',
// ...
}
]);
Blockly.common.defineBlocks(myBlockDefinitions);
Block.jsonInit
jsonInit
accepts a JSON object and calls the corresponding methods on Block
. For
example, a JSON object with the key-value pair colour: 150
results in a call
to this.setColour(150)
. Use jsonInit
in an init
function to load a JSON
object.
var myJson = {
// ...
};
Blockly.Blocks['my_block'] = {
init: function() {
this.jsonInit(myJson);
// The rest of the init function.
}
};