カスタム フィールドのアップグレード

2019 年 7 月(リリース 2.20190722)で、より体系化されたフィールド API が追加されました。可能な限り下位互換性を持たせることが意図されています。つまり、2019 年 7 月より前に作成したカスタム フィールドは、引き続き機能する可能性が高いということです。カスタム フィールドをアップグレードする必要があるかどうかを判断する前に、危険領域のセクションを読んで、フィールドを十分にテストしてください。

2019 年 7 月まではフィールド間の標準化がなかったため、デベロッパーが行う必要のあるすべての変更をカバーするのは困難でした。このドキュメントでは、考えられるすべての変更について説明しますが、このドキュメントに関心のある内容が含まれていない場合は、アップグレードのサポートのセクションをご覧ください。

危険区域

危険領域は、API が変更されたため、フィールドが破損する可能性がある既知の場所です。

Blockly.Field.register

Blockly.Field.register(); によるフィールドの登録が解除されました。登録を処理する fieldRegistry 名前空間が追加されました。

Blockly.Field.register('my_field_name', myFieldClass);

置き換えると次のようになります。

Blockly.fieldRegistry.register('my_field_name', myFieldClass);

setText

setText 関数は、Blockly コアによって呼び出されなくなったため、setText 関数にロジックが含まれている場合は、関数スイートの値処理getText 関数、レンダリング関数setText 関数の動作によって異なります)に移動する必要があります。

CustomFields.UpgradeField.prototype.setText = function(newText) {
  // Do validation.
  if (typeof newText != 'string' || newText === this.text_) {
    return;
  }

  // Fire event.
  if (this.sourceBlock_ && Blockly.Events.isEnabled()) {
    Blockly.events.fire(new Blockly.Events.BlockChange(
        this.sourceBlock_, 'field', this.name, this.text_, newText
    ));
  }

  // Update text value.
  this.text_ = 'prefix' + newText;

  // Rerender.
  this.size_.width = 0;
};

置き換えると次のようになります。

CustomFields.UpgradeField.prototype.doClassValidation_ = function(newValue) {
  if (typeof newValue != 'string') {
    return null;
  }
  return newValue;
};

CustomFields.UpgradeField.prototype.getText = function() {
  return  'prefix' + this.value_;
}

Blockly が自動的に処理:

  • 新しい値が古い値と異なるかどうかを確認する。
  • 値を更新しています。
  • 変更イベントの呼び出し。
  • フィールドを再レンダリングしています。

以下に対応する必要があります。

推奨されるアップグレードは、Field API が変更された場所です。ただし、変更を加えないことを選択した場合でも、フィールドは引き続き動作する可能性が高くなります。

直列化可能

EDITABLE プロパティと SERIALIZABLE プロパティの詳細については、編集可能およびシリアル化可能なプロパティをご覧ください。

CustomFields.UpgradeField.prototype.SERIALIZABLE = true;

以下の警告は無視できますが、SERIALIZABLE プロパティを定義することで解決できます。

Detected an editable field that was not serializable. Please define
SERIALIZABLE property as true on all editable custom fields. Proceeding
with serialization.

上記の警告は、EDITABLE プロパティが true であるため、Blockly はフィールドをシリアル化する必要があると認識していることを示していますが、SERIALIZABLE プロパティを定義するまで確認できないことを意味します。これをそのままにすると、すべてが正しく機能し、フィールドはシリアル化されますが、コンソールの警告が表示されます。

size_.width

this.size_.width = 0;

置き換えると次のようになります。

this.isDirty_ = true;

以下の警告は無視できますが、size_.width プロパティの代わりに isDirty_ プロパティを設定すると解決できます。

Deprecated use of setting size_.width to 0 to rerender a field. Set
field.isDirty_ to true instead.

上記の警告は、フィールドの再レンダリングに古い方法を使用していることを検出し、新しい方法を使用することが求められていることを意味します。

isDirty_ プロパティの詳細については、isDirty_ をご覧ください。

init

サブクラス内の重複コードを減らすために、init 関数がテンプレート関数になりました。

CustomFields.UpgradeField.prototype.init = function() {
  if (this.fieldGroup_) {
    // Already initialized once.
    return;
  }

  // Call superclass.
  CustomFields.UpgradeField.superClass_.init.call(this);

  // Create DOM elements.
  this.extraDom_ = Blockly.utils.dom.createSvgElement('image',
      {
        'height': '10px',
        'width': '10px'
      });
  this.extraDom_.setAttributeNS('http://www.w3.org/1999/xlink',
      'xlink:href', 'image.svg');
  this.extraDom_.style.cursor = 'pointer';
  this.fieldGroup_.appendChild(this.extraDom_);

  // Bind events.
  this.mouseOverWrapper_ =
    Blockly.browserEvents.bind(
        this.getClickTarget_(), 'mouseover', this, this.onMouseOver_);
  this.mouseOutWrapper_ =
    Blockly.browserEvents.bind(
        this.getClickTarget_(), 'mouseout', this, this.onMouseOut_);

  // Render.
  this.setValue(this.getValue());
};

置き換えると次のようになります。

CustomFields.UpgradeField.prototype.initView = function() {
  CustomFields.UpgradeField.superClass_.initView.call(this);

  this.extraDom_ = Blockly.utils.dom.createSvgElement('image',
      {
        'height': '10px',
        'width': '10px'
      });
  this.extraDom_.setAttributeNS('http://www.w3.org/1999/xlink',
      'xlink:href', 'image.svg');
  this.extraDom_.style.cursor = 'pointer';
  this.fieldGroup_.appendChild(this.extraDom_);
};

CustomFields.UpgradeField.prototype.bindEvents_ = function() {
  CustomFields.UpgradeField.superClass_.bindEvents_.call(this);

  this.mouseOverWrapper_ =
    Blockly.bindEvent_(
        this.getClickTarget_(), 'mouseover', this, this.onMouseOver_);
  this.mouseOutWrapper_ =
    Blockly.bindEvent_(
        this.getClickTarget_(), 'mouseout', this, this.onMouseOut_);
};

これにより、以下の処理が自動的に行われるようになります。

  • フィールドがすでに初期化されているかどうかを確認する。
  • fieldGroup_ の作成。
  • フィールドをレンダリングします。
  • バインディングのツールチップとエディタ イベントの表示。

以下に対応する必要があります。

onMouseDown_

CustomFields.UpgradeField.prototype.onMouseDown_ = function(e) {
  // ...
};

置き換えると次のようになります。

CustomFields.UpgradeField.prototype.showEditor_ = function() {
  // ...
}

入力がジェスチャー システムを通過できるように、onMouseDown_ 関数ではなく showEditor_ 関数をオーバーライドして、マウスクリックを処理することをおすすめします。

エディタの詳細については、エディタをご覧ください。

setValue

setValue 関数は、サブクラス内の重複コードを減らすテンプレート関数になりました。setValue 関数にロジックが含まれている場合は、値の処理で説明されている値処理のパスに合わせて、リファクタリングすることを検討してください。

text_

フィールドの text_ プロパティに直接アクセスしたり、更新したりしないようにすることをおすすめします。フィールドのユーザーが読み取り可能なテキストにアクセスするには、getText 関数を使用します。フィールドの保存済み値を更新するには、setValue 関数を使用します。

フィールドの値とテキストの詳細については、フィールドの構造をご覧ください。

アップグレードに関するサポートを受ける

提供する情報

サポートを依頼する際には、具体的な質問をすることをおすすめします。

非推奨例: 「この項目はどういう問題ですか?」

また、「このフィールドのアップグレードをサポートしてください」などは推奨されません。

推奨: 「フィールド テキストが正しく更新されていません。」

また、サポートする人にリソースを提供することも必要です。これらのファイルは、他のユーザーが簡単に使用できるようにする必要があります。

非推奨の方法:

  • コードの画像。
  • コードが不完全です。

推奨:

  • テキスト形式でフィールド コード全体を入力します。
  • 不正なフィールド動作の GIF の画像。
  • 不正なフィールド動作を再現する手順
  • アップグレード元の Blockly のバージョン。

投稿先

アップグレードに関する質問は、Blockly デベロッパー フォーラムに投稿してください。

問題が Blockly Core の問題であると確信している場合は、Blockly GitHub に問題を報告することもできます。問題を投稿する場合は、必要な情報をすべて記入してください。