Skip to main content

Dealing with inputs

Most blocks take one or more values as input (also called arguments or parameters). Here is a block that reports whether two values are strictly equal, so unlike Scratch's = block it treats "a" and "A" as different (download):

class StrictEqualityExtension {
getInfo() {
return {
id: 'strictequalityexample',
name: 'Strict Equality',
blocks: [
{
opcode: 'strictlyEquals',
blockType: Scratch.BlockType.BOOLEAN,
text: '[ONE] strictly equals [TWO]',
arguments: {
ONE: {
type: Scratch.ArgumentType.STRING
},
TWO: {
type: Scratch.ArgumentType.STRING,
defaultValue: 'Second value'
}
}
}
]
};
}

strictlyEquals(args) {
return args.ONE === args.TWO;
}
}
Scratch.extensions.register(new StrictEqualityExtension());

Declaring arguments

Add an arguments object to the block. Each key is one argument. The key name can be any format you like (all-caps is a common convention). Each argument commonly sets:

FieldTypeDescription
typeScratch.ArgumentType.*The shape of the input and what the default text box accepts. This is only a hint for the editor; the value your code receives can still be any type.
defaultValuestringOptional. The value pre-filled in the palette. Do not set it on boolean inputs.
menustringTurns the input into a dropdown. Covered below.

Argument types:

ValueAcceptsExample
Scratch.ArgumentType.STRINGAny textapple, 123, true
Scratch.ArgumentType.NUMBERA number123
Scratch.ArgumentType.BOOLEANA boolean input slot; resists dropping non-booleans intrue
Scratch.ArgumentType.COLORA hex color#ff4c4c
Scratch.ArgumentType.ANGLEA direction dial (0 = up, 90 = right, increases clockwise)90
Scratch.ArgumentType.MATRIXA 5x5 on/off grid1110101010...
Scratch.ArgumentType.NOTEA piano note picker60
Scratch.ArgumentType.COSTUMECostume names in the current spritecostume1
Scratch.ArgumentType.SOUNDSound names in the current spriterecording1
Scratch.ArgumentType.IMAGEAn inline image, not an input (see Assorted APIs)N/A

Placing arguments in the block

Bilup cannot guess where each input goes in the label, so you mark it in text with [ARGUMENT_NAME]. Each argument must appear in text exactly once. Order does not matter.

When the block runs, your function receives an object as its first parameter with a property for each argument. It is conventional to call it args, or to destructure it:

// Using args.X
goto(args) {
console.log(args.X, args.Y);
}

// Or destructuring
goto({X, Y}) {
console.log(X, Y);
}

The value of an argument may be a string, number, or boolean regardless of the declared type. The type is a suggestion for the editor, never a guarantee. Your code must convert values itself, for example with Scratch.Cast.

Static menus

To give an input a dropdown of fixed choices, set its type to Scratch.ArgumentType.STRING, add a menu naming the menu, and define that menu in a menus object (download):

class Strings1 {
getInfo() {
return {
id: 'strings1example',
name: 'Encoding',
blocks: [
{
opcode: 'convert',
blockType: Scratch.BlockType.REPORTER,
text: 'convert [TEXT] to [FORMAT]',
arguments: {
TEXT: {
type: Scratch.ArgumentType.STRING,
defaultValue: 'Apple'
},
FORMAT: {
type: Scratch.ArgumentType.STRING,
menu: 'FORMAT_MENU'
}
}
}
],
menus: {
FORMAT_MENU: {
acceptReporters: true,
items: ['uppercase', 'lowercase']
}
}
};
}

convert(args) {
// TEXT could be a number or boolean, so convert to a string
// before calling string methods on it.
if (args.FORMAT === 'uppercase') {
return args.TEXT.toString().toUpperCase();
} else {
return args.TEXT.toString().toLowerCase();
}
}
}
Scratch.extensions.register(new Strings1());

Each menu is an object with:

FieldTypeDescription
itemsarrayStrings, or {text, value} objects (see below). Must not be empty.
acceptReportersbooleanWhether blocks can be dropped into the menu. Almost always set this to true.

There is an important distinction here. A menu with acceptReporters: true is an input: the user can drop any reporter block into it. A menu with acceptReporters: false is a field: it can only ever be one of the fixed strings. You almost always want an input. The only common exception is event hat blocks, which only support field menus.

warning

Switching a menu between a field and an input (changing acceptReporters) is a backward-incompatible change that corrupts existing projects. Decide up front. See Maintaining compatibility.

Setting a menu directly to an array (instead of an object) implicitly makes it a field. Avoid that; always use the object form with acceptReporters: true.

Separate display text and value

Sometimes the label shown in the dropdown should differ from the value your code receives. Use {text, value} objects for those items (download):

menus: {
FORMAT_MENU: {
acceptReporters: true,
items: [
{ text: 'UPPERCASE', value: 'up' },
{ text: 'lowercase', value: 'low' }
]
}
}

The dropdown shows "UPPERCASE", but the block receives "up".

Exercises

  1. Add a block that joins two arguments into one string like Scratch's join block. Cast both to strings so join ((1 + 2)) ((3 + 4)) gives "37", not 10.
  2. Add a boolean block with a number input and a menu of "odd" and "even" that reports whether the number is odd or even, as the menu says.

Next steps

So far blocks finish almost instantly. Next, what if a block needs to wait for something, like a network request?