Mise à niveau d'un champ personnalisé

En juillet 2019 (version 2.20190722), une API de champs codifiés plus codifié a été ajoutée. Elle est conçue pour être aussi rétrocompatible que possible. Cela signifie que si vous avez créé un champ personnalisé avant juillet 2019, il continuera probablement de fonctionner. Avant de décider si votre champ personnalisé doit être mis à niveau, lisez la section Zones de danger et effectuez des tests approfondis.

Comme il n'y avait pas de standardisation entre les champs avant juillet 2019, il est difficile de couvrir toutes les modifications qu'un développeur pourrait avoir à apporter. Ce document tente de couvrir toutes les modifications probables, mais s'il ne couvre pas un élément qui vous intéresse, consultez la section sur l'assistance pour la mise à niveau.

Zones dangereuses

Les zones de danger sont des endroits connus où l'API a changé, ce qui peut compromettre votre champ.

Blockly.Field.register

Les champs ne sont plus enregistrés via Blockly.Field.register();. Il existe désormais un espace de noms fieldRegistry qui gère l'enregistrement.

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

Devient:

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

setText

La fonction setText n'est plus appelée par le noyau Blockly. Par conséquent, si votre fonction setText contient une logique, elle devra être déplacée vers la suite de fonctions de gestion des valeurs, la fonction getText et les fonctions de rendu (selon ce que fait votre fonction 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;
};

Devient:

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

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

Blockly gère automatiquement les éléments suivants:

  • Vérifiez si la nouvelle valeur est différente de l'ancienne.
  • Mise à jour de la valeur.
  • Déclenchement d'événements de modification
  • Rendu du champ en cours.

Voici ce que vous allez devoir gérer:

Les mises à niveau recommandées sont des endroits où l'API du champ a été modifiée, mais si vous choisissez de ne pas apporter de modifications, votre champ fonctionnera probablement toujours.

Sérialisables

Pour en savoir plus sur les propriétés EDITABLE et SERIALIZABLE, consultez la section Propriétés modifiables et sérialisables.

CustomFields.UpgradeField.prototype.SERIALIZABLE = true;

L'avertissement ci-dessous peut être ignoré, mais vous pouvez le résoudre en définissant la propriété SERIALIZABLE:

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

L'avertissement ci-dessus signifie que Blockly pense que vous souhaitez que le champ soit sérialisé (car la propriété EDITABLE est "true"), mais vous ne pouvez pas le vérifier tant que vous n'avez pas défini la propriété SERIALIZABLE. Si vous choisissez de laisser cette option seule, tout fonctionnera correctement et votre champ sera sérialisé, mais vous recevrez des avertissements dans la console.

size_.width

this.size_.width = 0;

Devient:

this.isDirty_ = true;

L'avertissement ci-dessous peut être ignoré, mais vous pouvez le résoudre en définissant la propriété isDirty_ au lieu de la propriété size_.width:

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

L'avertissement ci-dessus signifie que Blockly a détecté que vous utilisez une ancienne méthode pour afficher à nouveau un champ et que vous souhaitez utiliser la nouvelle.

Pour en savoir plus sur la propriété isDirty_, consultez isDirty_.

init

La fonction init a été transformée en fonction de modèle pour réduire le code en double dans les sous-classes.

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());
};

Devient:

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_);
};

Par conséquent, blockly gère désormais automatiquement les éléments suivants:

  • Vérifiez si le champ est déjà initialisé.
  • Créer la fieldGroup_
  • Affichage du champ.
  • Info-bulle de liaison et affichage des événements de l'éditeur.

Voici ce que vous allez devoir gérer:

onMouseDown_

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

Devient:

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

Nous vous recommandons de remplacer la fonction showEditor_ pour gérer les clics de souris plutôt que la fonction onMouseDown_, car elle permet aux entrées de passer par le système de gestes.

Pour en savoir plus sur les éditeurs, consultez la section Éditeurs.

setValue

setValue est désormais une fonction de modèle visant à réduire le code en double dans les sous-classes. Si votre fonction setValue contient une logique, envisagez de la refactoriser pour qu'elle corresponde aux chemins de gestion des valeurs décrits dans la section Gestion des valeurs.

text_

Nous vous recommandons de ne jamais accéder ni mettre à jour directement la propriété text_ de votre champ. Utilisez plutôt la fonction getText pour accéder au texte lisible par l'utilisateur de votre champ, et la fonction setValue pour mettre à jour la valeur stockée de votre champ.

Pour en savoir plus sur la valeur d'un champ par rapport à son texte, consultez la section Anatomie d'un champ.

Obtenir de l'aide pour la mise à niveau

Éléments à fournir

Lorsque vous demandez de l'aide, il est préférable de poser des questions spécifiques:

Non recommandé: "Quel est le problème avec ce champ ?"

Autre recommandation déconseillée: "M'aider à mettre à jour ce champ".

Recommandation: "Le texte du champ n'est pas mis à jour correctement."

Il est également nécessaire de fournir des ressources aux personnes qui vous assistent. Ces fichiers doivent être faciles à utiliser pour les autres utilisateurs.

Option déconseillée :

  • Images de code
  • Code incomplet.

Recommandations :

  • Code de champ complet au format texte.
  • Images de GIF montrant un comportement de champ incorrect
  • Étapes permettant de reproduire un comportement de champ incorrect.
  • Version de Blockly à partir de laquelle vous effectuez la mise à niveau.

Où publier

Posez vos questions de mise à niveau sur le forum des développeurs blockly.

Si vous êtes sûr qu'il s'agit d'un problème lié au cœur de blocs, vous pouvez également publier un problème sur GitHub. Si vous décidez de publier un problème, veuillez fournir toutes les informations demandées.