Création d'un type de champ

Avant de créer un type de champ, déterminez si l'un des autres méthodes pour personnaliser les champs selon vos besoins. Si votre application doit stocker un ou que vous souhaitez créer une interface utilisateur pour un type de valeur existant, vous vous devrez probablement créer un nouveau type de champ.

Pour créer un champ, procédez comme suit:

  1. Implémentez un constructeur.
  2. Enregistrez une clé JSON et implémentez fromJson.
  3. Gérer l'initialisation de l'interface utilisateur et de l'événement dans le bloc des écouteurs.
  4. Gérer la suppression des écouteurs d'événements (la suppression de l'UI est gérée pour vous).
  5. Implémentez la gestion de la valeur.
  6. Ajoutez une représentation textuelle de la valeur de votre champ pour améliorer l'accessibilité.
  7. Ajoutez des fonctionnalités supplémentaires, par exemple: <ph type="x-smartling-placeholder">
  8. Configurez d'autres aspects de votre champ, par exemple: <ph type="x-smartling-placeholder">

Dans cette section, nous partons du principe que vous avez lu et que vous connaissez le contenu des Anatomie d'une Champ.

Pour voir un exemple de champ personnalisé, consultez la rubrique Champs personnalisés démo pour en savoir plus.

Implémenter un constructeur

Le constructeur du champ est chargé de configurer la valeur initiale du champ et éventuellement de configurer un réseau local programme de validation. L'attribut personnalisé constructeur du champ est appelé lors de l'initialisation du bloc source, indépendamment indiquant si le bloc source est défini en JSON ou en JavaScript. Ainsi, n'a pas accès au bloc source pendant la construction.

L'exemple de code suivant crée un champ personnalisé nommé GenericField:

class GenericField extends Blockly.Field {
  constructor(value, validator) {
    super(value, validator);

    this.SERIALIZABLE = true;
  }
}

Signature de la méthode

Les constructeurs de champs utilisent généralement une valeur et un validateur local. La valeur est est facultatif, et si vous ne transmettez pas de valeur (ou si vous transmettez une valeur qui échoue à la classe validation), la valeur par défaut de la super-classe sera utilisée. Pour le la classe Field par défaut, cette valeur est null. Si vous ne voulez pas que cette valeur par défaut , assurez-vous de transmettre une valeur appropriée. Le paramètre de l'outil de validation s'affichent dans les champs modifiables et sont généralement marqués comme facultatifs. En savoir plus les validateurs dans la section Validators d'assistance.

Structure

La logique de votre constructeur doit suivre ce flux:

  1. Appelez le super-constructeur hérité (tous les champs personnalisés doivent hériter de Blockly.Field ou l'une de ses sous-classes) pour initialiser correctement la valeur et définissez l'outil de validation local pour votre champ.
  2. Si votre champ est sérialisable, définissez la propriété correspondante dans la d'un constructeur. Les champs modifiables doivent être sérialisables et les champs modifiables par défaut. Vous devriez donc probablement définir cette propriété sur "true", il ne devrait pas être sérialisable.
  3. Facultatif: personnalisez davantage votre campagne (par exemple, Champs de libellé). permettre la transmission d'une classe CSS, qui est ensuite appliquée au texte).

JSON et enregistrement

Dans un bloc JSON définitions, sont décrits par une chaîne (par exemple, field_number, field_textinput). Il gère Blockly une correspondance entre ces chaînes et des objets de champ, et appelle fromJson sur l'objet approprié pendant la construction.

Appelez Blockly.fieldRegistry.register pour ajouter votre type de champ à cette carte. en transmettant la classe field comme deuxième argument:

Blockly.fieldRegistry.register('field_generic', GenericField);

Vous devez également définir votre fonction fromJson. Votre implémentation doit déréférencez d'abord une chaîne tableau des références à l'aide de replaceMessageReferences, puis transmettre les valeurs au constructeur.

GenericField.fromJson = function(options) {
  const value = Blockly.utils.parsing.replaceMessageReferences(
      options['value']);
  return new CustomFields.GenericField(value);
};

Initialisation…

Lorsque votre champ est créé, il ne contient essentiellement qu'une valeur. L'initialisation est l'endroit où le DOM est créé, c'est-à-dire le modèle (si le champ possède un modèle), et les événements sont liés.

Écran On-Block

Lors de l'initialisation, vous êtes responsable de la création de tout ce dont vous aurez besoin pour l'affichage sur bloc du champ.

Valeurs par défaut, arrière-plan et texte

La fonction initView par défaut crée un élément rect de couleur claire et un élément text. Si vous voulez que votre domaine comprenne ces deux éléments, plus quelques des goodies, appelez la fonction initView de super-classe avant d'ajouter le reste de votre éléments DOM. Si vous voulez que votre domaine en comporte un, mais pas les deux, vous pouvez utiliser les fonctions createBorderRect_ ou createTextElement_.

Personnaliser la construction du DOM

Si votre champ est un champ de texte générique (par exemple, Texte d'entrée), La construction du DOM sera traitée pour vous. Sinon, vous devrez remplacer la fonction initView pour créer les éléments DOM dont vous aurez besoin le rendu futur de votre champ.

Par exemple, un champ déroulant peut contenir à la fois des images et du texte. En initView, crée un seul élément image et un seul élément de texte. Puis pendant render_ l'élément actif est affiché et l'autre est masqué, en fonction du type sélectionnée.

Pour créer des éléments DOM, vous pouvez utiliser la méthode Blockly.utils.dom.createSvgElement, ou à l'aide de la création DOM traditionnelle méthodes.

Les conditions requises pour l'affichage dans les blocs d'un champ sont les suivantes:

  • Tous les éléments DOM doivent être des enfants de l'élément fieldGroup_ du champ. Champ est créé automatiquement.
  • Tous les éléments DOM doivent rester dans les dimensions signalées du champ.

Consultez le Affichage pour en savoir plus sur la personnalisation et la mise à jour de votre affichage pour les blocs.

Ajouter des symboles textuels

Si vous souhaitez ajouter des symboles au texte d'un champ (comme Angle symbole degré du champ), vous pouvez ajouter l'élément de symbole (généralement contenu dans <tspan>) directement dans la textElement_ du champ.

Événements de saisie

Par défaut, les champs enregistrent les événements d'info-bulle et les événements de survol (à utiliser pour affichage éditeurs). Si vous souhaitez écouter d'autres types d'événements (par exemple, si vous voulez gérer (faire glisser sur un champ), vous devez remplacer la fonction bindEvents_ du champ.

bindEvents_() {
  // Call the superclass function to preserve the default behavior as well.
  super.bindEvents_();

  // Then register your own additional event listeners.
  this.mouseDownWrapper_ =
  Blockly.browserEvents.conditionalBind(this.getClickTarget_(), 'mousedown', this,
      function(event) {
        this.originalMouseX_ = event.clientX;
        this.isMouseDown_ = true;
        this.originalValue_ = this.getValue();
        event.stopPropagation();
      }
  );
  this.mouseMoveWrapper_ =
    Blockly.browserEvents.conditionalBind(document, 'mousemove', this,
      function(event) {
        if (!this.isMouseDown_) {
          return;
        }
        var delta = event.clientX - this.originalMouseX_;
        this.setValue(this.originalValue_ + delta);
      }
  );
  this.mouseUpWrapper_ =
    Blockly.browserEvents.conditionalBind(document, 'mouseup', this,
      function(_event) {
        this.isMouseDown_ = false;
      }
  );
}

Pour créer un lien avec un événement, vous devez généralement utiliser Blockly.utils.browserEvents.conditionalBind . Cette méthode de liaison d'événements filtre les touches secondaires pendant fait glisser. Si vous souhaitez que votre gestionnaire s'exécute même pendant un déplacement en cours vous pouvez utiliser Blockly.browserEvents.bind .

Mise au rebut

Si vous avez enregistré des écouteurs d'événements personnalisés dans l'bindEvents_ du champ leur enregistrement dans la fonction dispose doit être annulé.

Si vous avez correctement initialisé le vue de votre champ (en ajoutant tous les éléments DOM à fieldGroup_), la fonction le DOM du champ seront automatiquement supprimés.

Traitement de la valeur

→ Pour plus d'informations sur la valeur d'un champ et son texte, consultez la section Anatomie d'une .

Ordre de validation

Organigramme décrivant l&#39;ordre d&#39;exécution des validateurs

Implémenter un validateur de classe

Les champs ne doivent accepter que certaines valeurs. Par exemple, les champs numériques ne doivent les nombres, les champs de couleur ne doivent accepter que les couleurs, etc. en classe et en local programmes de validation. La classe les programmes de validation suivent les mêmes règles que les validateurs locaux, à la différence qu'il est aussi exécuté dans constructeur et ne doit donc pas faire référence au bloc source.

Pour implémenter l'outil de validation des classes de votre champ, remplacez doClassValidation_ .

doClassValidation_(newValue) {
  if (typeof newValue != 'string') {
    return null;
  }
  return newValue;
};

Traiter les valeurs valides

Si la valeur transmise à un champ comportant setValue est valide, vous recevez une Rappel doValueUpdate_. Par défaut, la fonction doValueUpdate_:

  • Définit la propriété value_ sur newValue.
  • Définit la isDirty_ sur true.

Si vous avez simplement besoin de stocker la valeur et que vous ne voulez pas effectuer de traitement personnalisé, vous n'avez pas besoin de remplacer doValueUpdate_.

Vous pouvez également effectuer les opérations suivantes:

  • Stockage personnalisé de newValue.
  • Modifiez d'autres propriétés en fonction de newValue.
  • Enregistrer si la valeur actuelle est valide ou non.

Vous devez ignorer doValueUpdate_:

doValueUpdate_(newValue) {
  super.doValueUpdate_(newValue);
  this.displayValue_ = newValue;
  this.isValueValid_ = true;
}

Traiter les valeurs non valides

Si la valeur transmise au champ avec setValue n'est pas valide, vous recevez une Rappel doValueInvalid_. Par défaut, la fonction doValueInvalid_ effectue rien. Cela signifie que, par défaut, les valeurs non valides ne seront pas affichées. Il y a aussi signifie que le champ ne sera pas renvoyé, car isDirty_ ne sera pas définie.

Si vous souhaitez afficher des valeurs non valides, vous devez remplacer doValueInvalid_. Dans la plupart des cas, vous devez définir une propriété displayValue_ sur valeur incorrecte, définir isDirty_ à true, et remplacer render_ pour que l'affichage en mode bloc se mette à jour en fonction de displayValue_ au lieu de la value_

doValueInvalid_(newValue) {
  this.displayValue_ = newValue;
  this.isDirty_ = true;
  this.isValueValid_ = false;
}

Valeurs en plusieurs parties

Lorsque votre champ contient une valeur en plusieurs parties (ex. : listes, vecteurs, objets), vous peuvent souhaiter que les parties soient traitées comme des valeurs individuelles.

doClassValidation_(newValue) {
  if (FieldTurtle.PATTERNS.indexOf(newValue.pattern) == -1) {
    newValue.pattern = null;
  }

  if (FieldTurtle.HATS.indexOf(newValue.hat) == -1) {
    newValue.hat = null;
  }

  if (FieldTurtle.NAMES.indexOf(newValue.turtleName) == -1) {
    newValue.turtleName = null;
  }

  if (!newValue.pattern || !newValue.hat || !newValue.turtleName) {
    this.cachedValidatedValue_ = newValue;
    return null;
  }
  return newValue;
}

Dans l'exemple ci-dessus, chaque propriété de newValue est validée individuellement. Ensuite, à la fin de la fonction doClassValidation_, si une propriété individuelle est non valide, la valeur est mise en cache dans la propriété cacheValidatedValue_ avant retour de null (non valide). Mettre en cache l'objet avec des données validées individuellement permet au doValueInvalid_ pour les gérer séparément, simplement en effectuant !this.cacheValidatedValue_.property, au lieu de les revalider individuellement.

Ce modèle de validation des valeurs en plusieurs parties peut également être utilisé dans des localisations de validation, il n'existe actuellement aucun moyen d'appliquer ce modèle.

isDirty_

isDirty_ est un indicateur utilisé dans la setValue la fonction, ainsi que d'autres parties du champ, pour savoir si le champ doit être à nouveau. Si la valeur d'affichage du champ a changé, isDirty_ doit généralement doit être définie sur true.

Texte

→ Pour en savoir plus sur l'utilisation et les différences du texte d'un champ de la valeur du champ, consultez la section Anatomie d'une .

Si le texte de votre champ est différent de la valeur de votre champ, vous devez remplacer Fonction getText pour fournir le texte correct.

getText() {
  let text = this.value_.turtleName + ' wearing a ' + this.value_.hat;
  if (this.value_.hat == 'Stovepipe' || this.value_.hat == 'Propeller') {
    text += ' hat';
  }
  return text;
}

Créer un éditeur

Si vous définissez la fonction showEditor_, Blockly écoutera automatiquement les clics et appeler showEditor_ au moment opportun. Vous pouvez afficher n'importe quel code HTML dans votre éditeur en l'encapsulant avec l'un des deux div spéciaux, appelé "DropDownDiv", et WidgetDiv, qui flottent au-dessus du reste de l'UI de Blockly.

Le DropDownDiv permet de fournir des éditeurs qui se trouvent dans une boîte connectée. à un champ. Il se positionne automatiquement pour être près du champ tout en restant dans les limites visibles. Le sélecteur d'angle et le sélecteur de couleur sont de bons exemples le DropDownDiv.

Image de l&#39;outil de sélection d&#39;angle

Le WidgetDiv permet de en fournissant des éditeurs qui ne se trouvent pas dans une boîte. Les champs numériques utilisent le paramètre WidgetDiv pour couvrir le champ avec une zone de saisie de texte HTML. Alors que la classe DropDownDiv gère automatiquement le positionnement, contrairement à WidgetDiv. Les éléments devront être positionné manuellement. Le système de coordonnées est exprimé en coordonnées en pixels par rapport en haut à gauche de la fenêtre. L'éditeur de saisie de texte est un bon exemple WidgetDiv

Image de l&#39;éditeur de saisie de texte

showEditor_() {
  // Create the widget HTML
  this.editor_ = this.dropdownCreate_();
  Blockly.DropDownDiv.getContentDiv().appendChild(this.editor_);

  // Set the dropdown's background colour.
  // This can be used to make it match the colour of the field.
  Blockly.DropDownDiv.setColour('white', 'silver');

  // Show it next to the field. Always pass a dispose function.
  Blockly.DropDownDiv.showPositionedByField(
      this, this.disposeWidget_.bind(this));
}

Exemple de code WidgetDiv

showEditor_() {
  // Show the div. This automatically closes the dropdown if it is open.
  // Always pass a dispose function.
  Blockly.WidgetDiv.show(
    this, this.sourceBlock_.RTL, this.widgetDispose_.bind(this));

  // Create the widget HTML.
  var widget = this.createWidget_();
  Blockly.WidgetDiv.getDiv().appendChild(widget);
}

Nettoyer

Les éléments DropDownDiv et WidgetDiv détruits le code HTML du widget mais vous devez supprimer manuellement tous les écouteurs d'événements appliquée à ces éléments.

widgetDispose_() {
  for (let i = this.editorListeners_.length, listener;
      listener = this.editorListeners_[i]; i--) {
    Blockly.browserEvents.unbind(listener);
    this.editorListeners_.pop();
  }
}

La fonction dispose est appelée dans un contexte null sur le DropDownDiv. Activé le WidgetDiv, il est appelé dans le contexte de WidgetDiv. Dans les deux cas il est préférable d'utiliser liaison lors de la transmission d'une fonction "dispose", comme indiqué dans le DropDownDiv ci-dessus. et WidgetDiv.

→ Pour en savoir plus sur la suppression et non sur celle des éditeurs, consultez Mise au rebut.

Mise à jour de l'écran de blocage...

La fonction render_ permet de mettre à jour l'affichage du champ dans le bloc afin qu'il corresponde sa valeur interne.

Voici quelques exemples courants :

  • Modifier le texte (menu déroulant)
  • Modifier la couleur

Valeurs par défaut

La fonction render_ par défaut définit le texte à afficher sur le résultat de la getDisplayText_ . La fonction getDisplayText_ renvoie la propriété value_ du champ. en une chaîne, après avoir été tronquée pour respecter le nombre maximal de caractères

Si vous utilisez l'affichage par défaut des blocs d'annonces bloqués et le comportement par défaut du texte fonctionne pour votre champ, il n'est pas nécessaire de remplacer render_.

Si le comportement du texte par défaut fonctionne pour votre champ, mais que celui-ci est bloqué contient des éléments statiques supplémentaires, vous pouvez appeler la méthode render_ par défaut , mais vous devrez tout de même la remplacer pour mettre à jour le paramètre taille.

Si le comportement par défaut du texte ne fonctionne pas pour votre champ ou si la fonction l'écran de blocage comporte des éléments dynamiques supplémentaires, vous devez personnaliser le render_ de commande.

Organigramme décrivant comment décider de remplacer ou non le rendu

Personnaliser le rendu

Si le comportement d'affichage par défaut ne fonctionne pas pour votre champ, vous devez définir le comportement d'affichage personnalisé. Il peut s'agir, par exemple, de définir des le texte d'affichage, les éléments d'une image, la mise à jour des couleurs d'arrière-plan...

Toutes les modifications d'attributs DOM sont autorisées. Les deux seules choses à retenir sont les suivantes:

  1. La création d'un DOM doit être gérée initialisation car il est plus efficace.
  2. Vous devez toujours mettre à jour le size_ pour qu'elle corresponde à la taille de l'écran de bloc.
render_() {
  switch(this.value_.hat) {
    case 'Stovepipe':
      this.stovepipe_.style.display = '';
      break;
    case 'Crown':
      this.crown_.style.display = '';
      break;
    case 'Mask':
      this.mask_.style.display = '';
      break;
    case 'Propeller':
      this.propeller_.style.display = '';
      break;
    case 'Fedora':
      this.fedora_.style.display = '';
      break;
  }

  switch(this.value_.pattern) {
    case 'Dots':
      this.shellPattern_.setAttribute('fill', 'url(#polkadots)');
      break;
    case 'Stripes':
      this.shellPattern_.setAttribute('fill', 'url(#stripes)');
      break;
    case 'Hexagons':
      this.shellPattern_.setAttribute('fill', 'url(#hexagons)');
      break;
  }

  this.textContent_.nodeValue = this.value_.turtleName;

  this.updateSize_();
}

Mise à jour de la taille...

Il est très important de mettre à jour la propriété size_ d'un champ, car elle renseigne le comment positionner le champ. La meilleure façon de déterminer exactement ce que devrait être size_ en expérimentant.

updateSize_() {
  const bbox = this.movableGroup_.getBBox();
  let width = bbox.width;
  let height = bbox.height;
  if (this.borderRect_) {
    width += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
    height += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
    this.borderRect_.setAttribute('width', width);
    this.borderRect_.setAttribute('height', height);
  }
  // Note how both the width and the height can be dynamic.
  this.size_.width = width;
  this.size_.height = height;
}

Couleurs de bloc assorties

Si vous souhaitez que les éléments de votre champ correspondent aux couleurs du bloc, vous devez remplacer la méthode applyColour. Vous devez accéder à la couleur via la propriété de style du bloc.

applyColour() {
  const sourceBlock = this.sourceBlock_;
  if (sourceBlock.isShadow()) {
    this.arrow_.style.fill = sourceBlock.style.colourSecondary;
  } else {
    this.arrow_.style.fill = sourceBlock.style.colourPrimary;
  }
}

Mise à jour de la modification...

Vous pouvez utiliser la fonction updateEditable pour modifier l'apparence d'un champ. selon qu'il est modifiable ou non. La fonction par défaut permet L'arrière-plan comporte ou n'affiche pas de réponse de survol (bordure) s'il est ou n'est pas modifiable. La taille de l'écran ne doit pas changer en fonction de sa capacité de modification, mais toutes les autres modifications sont autorisées.

updateEditable() {
  if (!this.fieldGroup_) {
    // Not initialized yet.
    return;
  }
  super.updateEditable();

  const group = this.getClickTarget_();
  if (!this.isCurrentlyEditable()) {
    group.style.cursor = 'not-allowed';
  } else {
    group.style.cursor = this.CURSOR;
  }
}

Sérialisation

La sérialisation consiste à enregistrer l'état du champ pour pouvoir le recharger ultérieurement dans l'espace de travail.

L'état de votre espace de travail inclut toujours la valeur du champ, mais il peut également inclure d'autres états, tels que l'état de l'UI de votre champ. Par exemple, si votre était une carte sur laquelle l'utilisateur pouvait zoomer, permettant à l'utilisateur de sélectionner des pays, sérialise également le niveau de zoom.

Si votre champ est sérialisable, vous devez définir la propriété SERIALIZABLE sur true

Blockly fournit deux ensembles de hooks de sérialisation pour les champs. Une paire de crochets fonctionne avec le nouveau système de sérialisation JSON, tandis que l'autre paire fonctionne avec le de l'ancien système de sérialisation XML.

saveState et loadState

saveState et loadState sont des hooks de sérialisation qui fonctionnent avec le nouveau fichier JSON système de sérialisation.

Dans certains cas, vous n'avez pas besoin de les fournir, car les implémentations fonctionneront. Si (1) votre champ est une sous-classe directe de la base Blockly.Field, (2) votre valeur est un sérialisable JSON. type, et (3) il vous suffit de sérialiser la valeur, l'implémentation par défaut fonctionnera parfaitement.

Sinon, votre fonction saveState doit renvoyer une valeur JSON sérialisable objet/valeur qui représente l'état du champ. Et votre loadState doit accepter le même objet/la même valeur sérialisable JSON et l'appliquer à sur le terrain.

saveState() {
  return {
    'country': this.getValue(),  // Value state
    'zoom': this.getZoomLevel(), // UI state
  };
}

loadState(state) {
  this.setValue(state['country']);
  this.setZoomLevel(state['zoom']);
}

Sérialisation complète et données de sauvegarde

saveState reçoit également un paramètre facultatif doFullSerialization. C'est utilisés par les champs qui font normalement référence à un état sérialisé par une autre sérialiseur (comme les modèles de données de sauvegarde). Le paramètre indique que l'état référencé n'est pas disponible lorsque le bloc est désérialisé. Par conséquent, doit effectuer toute la sérialisation elle-même. Par exemple, c'est le cas lorsque un bloc individuel est sérialisé ou lorsqu'un bloc est copié-collé.

Voici deux cas d'utilisation courants:

  • Lorsqu'un bloc individuel est chargé dans un espace de travail où les données de sauvegarde n'existe pas, le champ contient suffisamment d'informations dans son propre état pour créer un modèle de données.
  • Lorsqu'un bloc est copié-collé, le champ crée toujours un support au lieu de référencer un modèle existant.

L'un des champs qui l'utilise est le champ de variable intégrée. Normalement, il sérialise L'ID de la variable à laquelle il fait référence, mais si la valeur de doFullSerialization est "true" il sérialise tous ses états.

saveState(doFullSerialization) {
  const state = {'id': this.variable_.getId()};
  if (doFullSerialization) {
    state['name'] = this.variable_.name;
    state['type'] = this.variable_.type;
  }
  return state;
}

loadState(state) {
  const variable = Blockly.Variables.getOrCreateVariablePackage(
      this.getSourceBlock().workspace,
      state['id'],
      state['name'],   // May not exist.
      state['type']);  // May not exist.
  this.setValue(variable.getId());
}

Le champ "variable" effectue cette opération pour garantir que, si le fichier est chargé dans un espace de travail, où sa variable n'existe pas, il peut créer une nouvelle variable à référencer.

toXml et fromXml

toXml et fromXml sont des hooks de sérialisation qui fonctionnent avec l'ancien fichier XML. système de sérialisation. N'utilisez ces hooks que si c'est nécessaire (par exemple, si vous travaillez sur un ancien codebase qui n'a pas encore été migré), sinon utilisez saveState et loadState

Votre fonction toXml doit renvoyer un nœud XML qui représente l'état de sur le terrain. Votre fonction fromXml doit accepter le même nœud XML et s'appliquer sur le terrain.

toXml(fieldElement) {
  fieldElement.textContent = this.getValue();
  fieldElement.setAttribute('zoom', this.getZoomLevel());
  return fieldElement;
}

fromXml(fieldElement) {
  this.setValue(fieldElement.textContent);
  this.setZoomLevel(fieldElement.getAttribute('zoom'));
}

Propriétés modifiables et sérialisables

La propriété EDITABLE détermine si le champ doit comporter une UI pour indiquer que avec lequel il est possible d'interagir. Sa valeur par défaut est true.

La propriété SERIALIZABLE détermine si le champ doit être sérialisé. Il la valeur par défaut est false. Si cette propriété est true, vous devrez peut-être fournir fonctions de sérialisation et de désérialisation (voir sérialisation).

Personnaliser le curseur

La propriété CURSOR détermine le curseur que les utilisateurs voient lorsqu'ils pointent sur votre domaine. Il doit s'agir d'une chaîne de curseur CSS valide. La valeur par défaut est le curseur défini par .blocklyDraggable, qui correspond au curseur de sélection.