ブロックの定義では、テキスト、色、形状、他のブロックと接続できるブロックなど、ブロックの外観と動作を記述します。
JSON 形式と JavaScript API の比較
Blockly では、JSON オブジェクトと JavaScript 関数の 2 つの方法でブロックを定義できます。JSON 形式は、単語の順序が異なる言語向けに開発する際のローカライズ プロセスを簡素化するように設計されています。ブロックを定義する場合は、JSON 形式を使用することをおすすめします。
ただし、JSON 形式では、ミューテータやバリデータなどの高度な機能を直接定義することはできません。これらは、通常は拡張機能として、JavaScript で記述する必要があります。
Blockly の元の JavaScript 実装を使用しているアプリは、下位レベルの Blockly API 関数呼び出しに直接ブロック定義を書き込むこともできます。以下に JavaScript の例を示します。
JSON
Blockly.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"
}]);
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');
}
};
init
関数は、ブロックのシェイプを作成します。この関数のコンテキストでは、キーワード this
は作成される実際のブロックです。
どちらの例も同じ「string_length」ブロックを読み込みます。
ウェブの場合、JSON 形式は initJson
関数を使用して読み込まれます。これにより、Blockly のウェブページで 2 つの形式を混在させることもできます。可能な限り、JSON を使用してブロックを定義し、JSON でサポートされていないブロック定義の一部にのみ JavaScript を使用することをおすすめします。
以下に、主に JSON を使用して定義されるブロックの例を示します。ただし、JavaScript API を使用して拡張し、動的ツールチップを提供します。
JavaScript
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() {
this.jsonInit(mathChangeJson);
// 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'));
});
}
};
ブロックの色
ブロックのプライマリ カラーは、JSON colour
プロパティまたは block.setColour(..)
関数で定義するか、テーマを使用してブロック スタイルを定義します。
JSON
{
// ...,
"colour": 160,
}
JavaScript
init: function() {
// ...
this.setColour(160);
}
詳しくは、ブロックの色のガイドをご覧ください。
ステートメント接続
nextStatement
コネクタと previousStatement
コネクタを使用して、ブロックのシーケンスを作成できます。Blockly の標準レイアウトでは、このような接続は上下に並んでおり、ブロックは垂直方向に積み重ねられています。
以前のコネクタがあるブロックに出力コネクタを含めることはできません。その逆も同様です。ステートメント ブロックという用語は、値を出力しないブロックを指します。ステートメント ブロックには通常、前の接続と次の接続の両方があります。
nextStatement
接続と previousStatement
接続は入力できますが、この機能は標準ブロックでは使用されません。
次の接続
ブロックの下部にポイントを作成することで、他のステートメントをその下に積み重ねることができます。次の接続があるが、前の接続がないブロックは通常、イベントを表し、帽子を使用してレンダリングするように構成できます。
JSON
型指定なし:
{
...,
"nextStatement": null,
}
タイプ(低頻度):
{
"nextStatement": "Action",
...
}
JavaScript
型指定なし:
this.setNextStatement(true); // false implies no next connector, the default
入力あり(低頻度):
this.setNextStatement(true, 'Action');
以前の接続
ブロックの上部にノッチを作成し、ステートメントのスタックとして接続できるようにします。
以前に接続したブロックを出力接続にすることはできません。
JSON
型指定なし:
{
...,
"previousStatement": null,
}
タイプ(低頻度):
{
"previousStatement": "Action",
...
}
JavaScript
型指定なし:
this.setPreviousStatement(true); // false implies no previous connector, the default
入力あり(低頻度):
this.setPreviousStatement(true, 'Action');
ブロック出力
ブロックの場合は、出力が 1 つで、前端にオスのジグソー コネクタとして表示されます。出力は値の入力に接続。通常、出力があるブロックは「値ブロック」と呼ばれます。
JSON
型指定なし:
{
// ...,
"output": null,
}
入力済み:
{
// ...,
"output": "Number",
}
JavaScript
型指定なし:
init: function() {
// ...
this.setOutput(true);
}
入力済み:
init: function() {
// ...
this.setOutput(true, 'Number');
}
出力コネクタのあるブロックに、前のステートメントのノッチを含めることはできません。
ブロック入力
ブロックには 1 つ以上の入力があり、各入力にはフィールドのシーケンスがあり、接続で終わる場合があります。組み込み入力にはいくつかのタイプがあります。
- 値入力: 値ブロックの出力接続に接続します。
math_arithmetic
ブロック(加算、減算)は、2 つの値入力があるブロックの例です。 - ステートメント入力: ステートメント ブロックの以前の接続に接続します。while ループのネストされたセクションは、ステートメント入力の例です。
- ダミー入力: ブロック接続がありません。外部値入力を使用するようにブロックが構成されている場合、改行のように機能します。
- 最終行入力: ブロック接続を持たず、常に改行のように機能します。
カスタム入力を作成して、カスタム レンダリングをサポートすることもできます。
JSON 形式と JavaScript API では、入力の記述に若干異なるモデルを使用します。
JSON の入力とフィールド
JSON 定義のブロックは、補間されたメッセージ文字列(message0
、message1
、...)のシーケンスとして構造化されます。各補間トークン(%1
、%2
、...)は、一致する JSON argsN
配列のフィールドまたは入力終点です(これにより、入力コネクタがメッセージ内でレンダリングされます)。この形式は、国際化を容易にするためのものです。
JSON
{
"message0": "set %1 to %2",
"args0": [
{
"type": "field_variable",
"name": "VAR",
"variable": "item",
"variableTypes": [""]
},
{
"type": "input_value",
"name": "VALUE"
}
]
}
補間トークンは、args0
配列と完全に一致している必要があります。重複や省略があってはなりません。トークンは任意の順序で存在できるため、さまざまな言語でブロックのレイアウトを変更できます。
補間トークンの両側のテキストが空白文字で区切られます。
%
文字を使用するテキスト(パーセンテージを参照する場合など)では、補間トークンと解釈されないように %%
を使用する必要があります。
ブロックの形状は、引数の順序と引数の型によって決まります。これらの文字列のいずれかを変更すると、ブロックのレイアウトが完全に変わる可能性があります。これは、英語とは語順が異なる言語では特に重要です。架空の言語について考えてみましょう。ここでは、"set %1 to %2"
(上記の例で使用されている)を逆にして "put %2 in %1"
と記述します。この 1 つの文字列を変更し、JSON の残りの部分はそのままにすると、次のブロックになります。
Blockly がフィールドの順序を自動的に変更し、ダミー入力を作成して、外部入力から内部入力に切り替えました。
Blockly はまた、メッセージ文字列内の改行文字(\n
)を自動的に終了行入力に置き換えます。
JSON
{
"message0": "set %1\nto %2",
"args0": [
{
"type": "field_variable",
"name": "VAR",
"variable": "item",
"variableTypes": [""]
},
{
"type": "input_value",
"name": "VALUE"
}
]
}
Args
各メッセージ文字列は、同じ番号の args
配列とペアになります。たとえば、message0
は args0
と併用します。補間トークン(%1
、%2
、...)は args
配列のアイテムを参照します。すべてのオブジェクトには type
文字列があります。残りのパラメータは型によって異なります。
独自のカスタム フィールドとカスタム入力を定義して、引数として渡すこともできます。
すべてのオブジェクトに alt
フィールドが存在する場合があります。Blockly がオブジェクトの type
を認識しない場合は、代わりに alt
オブジェクトが使用されます。たとえば、field_time
という新しいフィールドが Blockly に追加されている場合、このフィールドを使用するブロックでは alt
を使用して古いバージョンの Blockly に対する field_input
フォールバックを定義できます。
JSON
{
"message0": "sound alarm at %1",
"args0": [
{
"type": "field_time",
"name": "TEMPO",
"hour": 9,
"minutes": 0,
"alt":
{
"type": "field_input",
"name": "TEMPOTEXT",
"text": "9:00"
}
}
]
}
alt
オブジェクトには独自の alt
オブジェクトを含めることができるため、チェーン化が可能になります。最終的に、Blockly が(alt
オブジェクトを試行した後に)args0
配列にオブジェクトを作成できない場合、そのオブジェクトは単にスキップされます。
message
文字列が入力に含まれないテキストやフィールドで終わる場合、ダミー入力が自動的にブロックの最後に追加されます。したがって、ブロックの最後の入力がダミー入力であれば、args
配列から除外でき、message
に補間する必要はありません。テーリング ダミー入力を自動的に追加することで、翻訳者は JSON の残りの部分を変更せずに message
を変更できます。前述の "set %1 to %2"
(ダミー入力なし)と "put %2 in %1"
(ダミー入力を追加)の例を参照してください。
implicitAlign0
まれに、自動的に作成された後置ダミー入力を "RIGHT"
または "CENTRE"
に合わせる必要があります。指定しない場合のデフォルトは "LEFT"
です。
以下の例では、message0
は "send email to %1 subject %2 secure %3"
であり、Blockly は 3 行目にダミー入力を自動的に追加します。implicitAlign0
を "RIGHT"
に設定すると、この行は強制的に右揃えになります。このアライメントは、メッセージ内の改行文字('\n'
)を置き換える最終行入力など、JSON ブロック定義で明示的に定義されていないすべての入力に適用されます。非推奨のプロパティ lastDummyAlign0
もあり、implicitAlign0
と同じ動作になります。
RTL(アラビア語とヘブライ語)のブロックを設計する際は、左右が逆になります。
したがって、"RIGHT"
はフィールドを左に揃えます。
message1
、args1
、implicitAlign1
一部のブロックは、必然的に 2 つ以上の別々の部分に分割されます。次の 2 つの行がある繰り返しブロックについて考えてみましょう。
このブロックについて 1 つのメッセージで記述する場合、message0
プロパティは "repeat %1 times %2 do %3"
になります。この文字列は翻訳者には扱いにくく、%2
置換の意味を説明するのは困難です。%2
ダミー入力も、一部の言語では望ましくない場合もあります。また、2 番目の行のテキストを共有したいブロックが複数存在する場合があります。JSON では、複数の message プロパティと args プロパティを使用するほうがよいでしょう。
JSON
{
"type": "controls_repeat_ext",
"message0": "repeat %1 times",
"args0": [
{"type": "input_value", "name": "TIMES", "check": "Number"}
],
"message1": "do %1",
"args1": [
{"type": "input_statement", "name": "DO"}
],
"previousStatement": null,
"nextStatement": null,
"colour": 120
}
JSON 形式では、message
、args
、implicitAlign
プロパティを任意の数だけ定義できます。0 から始まり、順次増分します。ブロック ファクトリではメッセージを複数の部分に分割することはできませんが、手動で行うのは簡単です。
JavaScript の入力とフィールド
JavaScript API には、入力タイプごとに append
メソッドが含まれています。
JavaScript
this.appendEndRowInput()
.appendField('for each')
.appendField('item')
.appendField(new Blockly.FieldVariable());
this.appendValueInput('LIST')
.setCheck('Array')
.setAlign(Blockly.inputs.Align.RIGHT)
.appendField('in list');
this.appendStatementInput('DO')
.appendField('do');
this.appendDummyInput()
.appendField('end');
各追加のメソッドには、コード生成ツールで使用される識別子文字列を指定できます。ダミー入力と最終行入力で参照が必要になることはほとんどなく、識別子は通常設定されません。
JavaScript API には、カスタム入力を追加するための汎用の appendInput
メソッドも含まれています。この場合、識別子をカスタム入力のコンストラクタに直接渡す必要があります。
JavaScript
this.appendInput(new MyCustomInput('INPUT_NAME'))
.appendField('an example label')
すべての appendInput
メソッド(汎用メソッドと非汎用メソッドの両方)は、入力オブジェクトを返すため、メソッド チェーンを使用してさらに構成できます。入力の構成に使用する組み込みメソッドは 3 つあります。
setCheck
JavaScript
input.setCheck('Number');
このオプション関数は、接続された入力の型チェックに使用されます。null(デフォルト)の引数を指定した場合、この入力は任意のブロックに接続できます。詳細については、型チェックをご覧ください。
setAlign
JavaScript
input.setAlign(Blockly.inputs.Align.RIGHT);
このオプションの関数は、フィールドのアライメントを行うために使用されます(以下を参照)。この関数には、Blockly.inputs.Align.LEFT
、Blockly.inputs.Align.RIGHT
、Blockly.inputs.Align.CENTER
の 3 つの自己記述型値が引数として渡されます。
RTL(アラビア語とヘブライ語)のブロックを設計する際は、左右が逆になります。
したがって、Blockly.inputs.Align.RIGHT
はフィールドを左に揃えます。
appendField
入力が作成されて appendInput
でブロックに追加されたら、必要に応じて任意の数のフィールドを入力に追加できます。これらのフィールドは多くの場合、各入力の用途を説明するラベルとして使用されます。
JavaScript
input.appendField('hello');
最もシンプルなフィールド要素はテキストです。Blockly の慣例では、固有名詞(Google、SQL など)を除き、すべて小文字のテキストを使用します。
入力行には任意の数のフィールド要素を含めることができます。複数の appendField
呼び出しを連結することで、複数のフィールドを同じ入力行に効率的に追加できます。
JavaScript
input.appendField('hello')
.appendField(new Blockly.FieldLabel('Neil', 'person'));
実際には、appendField('hello')
呼び出しは明示的な FieldLabel コンストラクタ appendField(new Blockly.FieldLabel('hello'))
を使用するためのショートカットです。コンストラクタを使用する必要があるのは、CSS ルールを使用してテキストのスタイルを設定できるように、クラス名を指定する場合のみです。
インラインと外部
ブロック入力は外部または内部としてレンダリングできます。
ブロック定義では、入力をインラインにするかどうかを制御するブール値をオプションで指定できます。false
の場合、値の入力はすべて外部(左のブロックなど)になります。true
の場合、値の入力はすべてインラインになります(上の右側のブロックなど)。
JSON
{
// ...,
"inputsInline": true
}
JavaScript
init: function() {
// ...
this.setInputsInline(true);
}
定義されていない場合、Blockly はヒューリスティックを使用して最適なモードを推測します。Blockly が正しい選択をするのであれば、このフィールドを未定義のままにすることをおすすめします。言語によって翻訳のモードが自動的に異なる場合があるためです。前述の "set %1 to %2"
(外部入力)と "put %2 in %1"
(インライン入力)の JSON の例をご覧ください。
ブロックに数字などの小さな入力がある可能性が高い場合は、インライン入力を使用します。collapse
構成が有効になっている場合、ユーザーはコンテキスト メニューからこのオプションを切り替えることができます(ツールボックスにカテゴリがある場合はデフォルトで true になります)。
フィールド
フィールドにより、ブロック内の UI 要素の大半が定義されます。これには、文字列ラベル、画像、文字列や数値などのリテラルデータの入力が含まれます。最もシンプルな例は math_number
ブロックです。これは、field_input
を使用してユーザーが数値を入力できるようにします。
フィールドは、appendField を使用してブロックに追加されます。
Blockly には、テキスト入力、カラー選択ツール、画像など、多くの組み込みフィールドが用意されています。独自のフィールドを作成することもできます。
→ 組み込みフィールドについて詳細をご確認ください。
→ カスタム フィールドの作成に関する詳細
アイコン
アイコンは、ブロックに関する「メタ」情報を表示するブロック上の UI 要素を定義します。
アイコンは、addIcon を使用してブロックに追加します。
Blockly には、コメント アイコンや警告アイコンなど、いくつかの組み込みアイコンが用意されています。独自のアイコンを作成することもできます。
→ 詳しくは、カスタム アイコンの作成をご覧ください。
ツールチップ
ブロックにカーソルを合わせると、ツールチップですぐに役立つ情報が提供されます。テキストが長い場合は、自動的に改行が行われます。
JSON
{
// ...,
"tooltip": "Tooltip text."
}
JavaScript
init: function() {
this.setTooltip("Tooltip text.");
}
JavaScript API では、ツールチップを静的な文字列ではなく、関数として定義することもできます。これにより、動的なヘルプが可能になります。選択されたプルダウン オプションに応じてツールチップが変わるツールチップの例については、math_arithmetic
をご覧ください。
JavaScript
Blockly.Blocks['math_arithmetic'] = {
init: function() {
// ...
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
var mode = thisBlock.getFieldValue('OP');
var TOOLTIPS = {
'ADD': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD,
'MINUS': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS,
'MULTIPLY': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY,
'DIVIDE': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE,
'POWER': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER
};
return TOOLTIPS[mode];
});
}
};
JavaScript API を使用すると、ブロックで静的文字列ではなく、ツールチップ文字列を返す関数を指定できます。これにより、動的なツールチップを実現できます。
例として math_arithmetic
をご覧ください。
カスタマイズ
また、カスタム レンダリング関数を使用して、ツールチップの外観をカスタマイズすることもできます。次の 2 つのパラメータを受け取る関数を作成します。
- 1 つ目は、コンテンツをレンダリングする
<div>
要素です。 - 2 つ目はカーソルが置かれている 実際の要素で
関数の本体では、どのようなコンテンツでも div にレンダリングできます。マウスオーバーしたブロックで定義されているツールチップ文字列を取得するには、Blockly.Tooltip.getTooltipOfObject(element);
を呼び出します。ここで、element
は上記の 2 番目のパラメータです。
最後に、この関数を登録して、Blockly が適切なタイミングで呼び出せるようにします。
Blockly.Tooltip.setCustomTooltip(yourFnHere);
例については、カスタム ツールチップのデモをご覧ください。
ヘルプの URL
ブロックにはヘルプページを関連付けることができます。Blockly for Web のユーザーは、ブロックを右クリックしてコンテキスト メニューから [ヘルプ] を選択することで、これを利用できます。この値が null
の場合、メニューはグレー表示されます。
JSON
{
// ...,
"helpUrl": "https://en.wikipedia.org/wiki/For_loop"
}
JavaScript
init: function() {
// ...
this.setHelpUrl('https://en.wikipedia.org/wiki/For_loop');
}
JavaScript API を使用すると、URL 文字列を返す静的文字列の代わりに関数をブロックできるため、動的なヘルプが可能になります。
変更リスナーとバリデータ
ブロックには、ワークスペースが変更されると呼び出される変更リスナー関数(ブロックに関係のない関数を含む)を含めることができます。これらは主に、ブロックの警告テキストや同様のユーザー通知をワークスペースの外部で設定するために使用されます。
関数を追加するには setOnChange を呼び出し、init で行います。すべてのプラットフォームで使用する場合は、JSON 拡張機能を使用します。
JSON
{
// ...,
"extensions":["warning_on_change"],
}
Blockly.Extensions.register('warning_on_change', function() {
// Example validation upon block change:
this.setOnChange(function(changeEvent) {
if (this.getInput('NUM').connection.targetBlock()) {
this.setWarningText(null);
} else {
this.setWarningText('Must have an input block.');
}
});
});
JavaScript
Blockly.Blocks['block_type'] = {
init: function() {
// Example validation upon block change:
this.setOnChange(function(changeEvent) {
if (this.getInput('NUM').connection.targetBlock()) {
this.setWarningText(null);
} else {
this.setWarningText('Must have an input block.');
}
});
}
}
システムが関数を呼び出し、変更イベントが渡されます。関数内で、this
はブロック インスタンスを参照します。
この関数はあらゆる変更で呼び出されるため、使用する場合はリスナーが迅速に実行されることを確認する必要があります。また、ワークスペースの変更によってリスナーにカスケードまたはループバックされる可能性があることにも注意してください。
例については、controls_flow_statements
、logic_compare
、procedures_ifreturn
ブロックをご覧ください。
編集可能なフィールドには、入力検証と副作用を引き起こす独自のイベント リスナーがあります。
ミューテータ
ミューテータを使用すると、特にユーザーがダイアログを開いてコンポーネントの追加、削除、再配置を行うことで、高度なブロックの形状を変更できます。ミューテータは JSON を使用して mutator
キーで追加できます。
JSON
{
// ...,
"mutator":"if_else_mutator"
}
ブロックごとの構成
ブロック インスタンスには、ユーザーに対する動作を構成するさまざまなプロパティがあります。これらを使用して、ワークスペースにドメインの特定のプロパティを反映させる(「start」イベントが 1 つだけ発生するなど)ことや、ユーザーの作業(チュートリアルなど)に焦点を当てることができます。
削除可能な状態
block.setDeletable(false);
false に設定した場合、ユーザーはブロックを削除できません。編集可能なワークスペースではブロックがデフォルトで削除可能になります。
任意のブロック(削除不可のブロックも含む)はプログラムで削除できます。
block.dispose();
編集可能な状態
block.setEditable(false);
false に設定した場合、ユーザーはブロックのフィールド(プルダウンやテキスト入力など)を変更できません。編集可能なワークスペースでは、ブロックがデフォルトで編集可能です。
移動可能な状態
block.setMovable(false);
false に設定した場合、ユーザーはブロックを直接移動できません。別のブロックの子である移動できないブロックは、そのブロックから切断されませんが、親が移動されると親と一緒に移動します。編集可能なワークスペース上で、ブロックはデフォルトで移動可能に設定されます。
任意のブロック(移動できないブロックも含む)は、ワークスペースに配置するとプログラムで移動できます。
block.moveBy(dx, dy)
ワークスペース上のブロックの開始位置はデフォルトで(0, 0)に設定されます。
データをブロックする
this.data = '16dcb3a4-bd39-11e4-8dfc-aa07a5b093db';
data は、ブロックに添付できる任意の文字列です。ブロックがシリアル化されると、データ文字列がシリアル化されます。これには、ブロックの複製やコピー/貼り付けを行う場合も含まれます。
多くの場合、ブロックを外部リソースに関連付けるために使用されます。
JSON にシリアル化されたデータは、最上位プロパティとしてブロック内に格納されます。
{
"type": "my_block",
"data": "16dcb3a4-bd39-11e4-8dfc-aa07a5b093db",
// etc..
}
XML(古い Iceboxed シリアル化システム)にシリアル化された場合、データ文字列はブロック内の <data></data>
タグに格納されます。
<block type="my_block">
<data>16dcb3a4-bd39-11e4-8dfc-aa07a5b093db</data>
<!-- etc... -->
</block>
破壊
ブロックには destroy
フックがあります。このフックは、ワークスペースから削除されたときに呼び出されます。これを使用して、ブロックに関連付けられたバッキング データモデルや外部リソースのうち、不要になったものを破棄できます。
JSON
{
// ...,
"extensions":["destroy"],
}
Blockly.Extensions.registerMixin('destroy', {
destroy: function() {
this.myResource.dispose();
}
});
JavaScript
Blockly.Blocks['block_type'] = {
destroy: function() {
this.myResource.dispose();
}
}
destroy
メソッドは、ブロックの親が破棄された後、その子やフィールドが破棄される前に呼び出されます。
コンテキストメニュー
デフォルトでは、ブロックには右クリックのコンテキスト メニューがあり、ユーザーはコメントの追加やブロックの複製などを行うことができます。
個々のブロックのコンテキスト メニューを無効にする方法は次のとおりです。
block.contextMenu = false;
メニューに表示されるオプションをカスタマイズすることもできます。すべてのブロックのメニューをカスタマイズするには、コンテキスト メニューのドキュメントをご覧ください。個々のブロックのメニューをカスタマイズするには、customContextMenu
を実装します。この関数は、メニュー オプションの配列を受け取ってその場で変更します。つまり、アイテムの追加と削除の両方を行うことができます。
各メニュー オプションは、次の 3 つのプロパティを持つオブジェクトです。
text
は表示テキストです。enabled
はブール値です。無効にすると、このオプションはグレーのテキストで表示されます。callback
は、オプションがクリックされたときに呼び出される関数です。