Upgrade di un campo personalizzato

A luglio 2019 (release 2.20190722) è stata aggiunta un'API di campi più codificata. Deve essere il più compatibile possibile con le versioni precedenti. Ciò significa che se hai creato un campo personalizzato prima di luglio 2019, molto probabilmente continuerà a funzionare. Prima di decidere se è necessario eseguire l'upgrade del campo personalizzato, ti consigliamo di leggere attentamente la sezione Aree di pericolo e di eseguire un test approfondito del campo.

A causa dell'assenza di standardizzazione tra i campi prima di luglio 2019, è difficile coprire tutte le modifiche che uno sviluppatore potrebbe dover apportare. Questo documento tratta tutte le probabili modifiche, ma se non trovi qualcosa di tuo interesse, leggi la sezione su come ricevere assistenza per l'upgrade.

Aree pericolose

Le aree pericolose sono luoghi noti in cui l'API è cambiata e il tuo campo potrebbe essere inaccessibile.

Blockly.Field.register

I campi non sono più registrati tramite Blockly.Field.register();. Ora esiste uno spazio dei nomi fieldRegistry che gestisce la registrazione.

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

Diventa:

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

setText

La funzione setText non è più chiamata dal core Blockly, quindi se la tua funzione setText contiene logica, dovrà essere spostata nella suite di funzioni di gestione valori, nella funzione getText e nelle funzioni di rendering (in base a ciò che sta facendo esattamente la funzione 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;
};

Diventa:

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

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

Blockly gestisce automaticamente:

  • Verifica che il nuovo valore sia diverso da quello precedente.
  • Aggiornamento del valore in corso...
  • Attivazione degli eventi di modifica.
  • Eseguire il rendering del campo.

Dovrai occuparti di:

Gli upgrade consigliati sono posizioni in cui l'API Field è stata modificata, ma se scegli di non apportare modifiche, il tuo campo molto probabilmente continuerà a funzionare.

SERIALIZZABILE

Per ulteriori informazioni sulle proprietà EDITABLE e SERIALIZABLE, consulta Proprietà modificabili e serializzabili.

CustomFields.UpgradeField.prototype.SERIALIZABLE = true;

L'avviso seguente è ignorabile, ma puoi risolverlo definendo la proprietà SERIALIZABLE:

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

L'avviso sopra riportato indica che Blockly crede che il campo venga serializzato (perché la proprietà EDITABLE è true), ma non può esserne sicura finché non definisci la proprietà SERIALIZABLE. Se scegli di lasciarlo invariato, tutto funzionerà correttamente e il campo verrà serializzato, ma riceverai avvisi della console.

size_.width

this.size_.width = 0;

Diventa:

this.isDirty_ = true;

L'avviso seguente è ignorabile, ma puoi risolverlo impostando la proprietà isDirty_ anziché la proprietà size_.width:

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

L'avviso sopra riportato indica che Blockly ha rilevato che stai utilizzando un vecchio metodo per il rendering di un campo e ti chiede di utilizzare il nuovo metodo.

Per ulteriori informazioni sulla proprietà isDirty_, consulta isDirty_.

init

La funzione init è stata trasformata in una funzione modello per ridurre il codice duplicato nelle sottoclassi.

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

Diventa:

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

Ciò significa che blockly ora gestisce automaticamente:

  • È in corso la verifica se il campo è già stato inizializzato.
  • Creazione di fieldGroup_.
  • Viene eseguito il rendering del campo.
  • Descrizione comando di associazione e mostra eventi dell'editor.

Dovrai occuparti di:

onMouseDown_

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

Diventa:

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

Ti consigliamo di eseguire l'override della funzione showEditor_ per gestire i clic del mouse anziché la funzione onMouseDown_ in quanto consente all'input di passare attraverso il sistema di gesti.

Per ulteriori informazioni sugli editor, consulta la sezione Editor.

setValue

Ora la funzione setValue è una funzione modello per ridurre il codice duplicato nelle sottoclassi. Se la funzione setValue contiene logica, valuta la possibilità di rivalutarla in modo che si adatti ai percorsi di gestione dei valori descritti in Gestione dei valori.

text_

Ti consigliamo di non accedere o aggiornare mai direttamente la proprietà text_ del tuo campo. Utilizza invece la funzione getText per accedere al testo leggibile del campo e la funzione setValue per aggiornare il valore memorizzato del campo.

Per ulteriori informazioni sul valore di un campo e sul relativo testo, consulta Struttura di un campo.

Richiedere assistenza per l'upgrade

Cosa fornire

Quando chiedi assistenza è meglio porre domande specifiche:

Opzione non consigliata: "Cosa c'è che non va in questo campo?"

Opzione non consigliata: "Aiutami a eseguire l'upgrade di questo campo".

Opzione consigliata: "Il testo del campo non viene aggiornato correttamente".

È inoltre necessario fornire risorse alle persone che forniscono assistenza. Questi file devono essere facili da utilizzare.

Opzione sconsigliata:

  • Immagini di codice.
  • Codice incompleto.

Consigliato:

  • Completa il codice del campo in formato testo.
  • Immagini di GIF con comportamenti dannosi sui campi.
  • Passaggi per riprodurre un comportamento non corretto dei campi.
  • La versione dei blocchi da cui stai eseguendo l'upgrade.

Dove pubblicare

Pubblica domande sull'upgrade nel forum per gli sviluppatori di blocco.

Se hai la certezza che il problema sia un problema relativo al core a blocchi, puoi anche pubblicare un problema su GitHub a blocchi. Se decidi di pubblicare un problema, fornisci tutte le informazioni richieste.