Avant de créer un type de champ, déterminez si l'une des autres méthodes de personnalisation des champs répond à vos besoins. Si votre application doit stocker un nouveau type de valeur ou si vous souhaitez créer une interface utilisateur pour un type de valeur existant, vous devrez probablement créer un autre type de champ.
Pour créer un champ, procédez comme suit:
- Implémenter un constructeur
- Enregistrez une clé JSON et implémentez
fromJson
. - Gérer l'initialisation de l'interface utilisateur sur le bloc et des écouteurs d'événements.
- Gérer la suppression des écouteurs d'événements (la suppression de l'UI est gérée automatiquement)
- Implémenter la gestion de la valeur
- Ajoutez une représentation textuelle de la valeur de votre champ, pour l'accessibilité.
- Ajoutez des fonctionnalités supplémentaires, par exemple :
- Configurez d'autres aspects de votre champ, tels que :
Dans cette section, nous partons du principe que vous avez lu et que vous connaissez le contenu de l'article Anatomie d'un champ.
Pour obtenir un exemple de champ personnalisé, consultez la démonstration sur les champs personnalisés.
Implémenter un constructeur
Le constructeur du champ est chargé de configurer la valeur initiale du champ et éventuellement de configurer un programme de validation local. Le constructeur du champ personnalisé est appelé lors de l'initialisation du bloc source, que celui-ci soit défini au format JSON ou JavaScript. Ainsi, le champ personnalisé 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. Cette valeur est facultative. Si vous ne transmettez pas de valeur (ou si vous transmettez une valeur qui échoue à la validation de la classe), la valeur par défaut de la super-classe est utilisée. Pour la classe Field
par défaut, cette valeur est null
. Si vous ne voulez pas utiliser cette valeur par défaut, veillez à transmettre une valeur appropriée. Le paramètre de validation n'est disponible que pour les champs modifiables et est généralement marqué comme facultatif. Pour en savoir plus sur les validateurs, consultez la documentation sur les validateurs.
Structurer
La logique à l'intérieur de votre constructeur doit suivre le flux suivant:
- Appelez le super constructeur hérité (tous les champs personnalisés doivent hériter de
Blockly.Field
ou de l'une de ses sous-classes) pour initialiser correctement la valeur et définir le validateur local de votre champ. - Si votre champ est sérialisable, définissez la propriété correspondante dans le constructeur. Les champs modifiables doivent être sérialisables, et les champs sont modifiables par défaut. Vous devez donc probablement définir cette propriété sur "true", sauf si vous savez qu'il ne doit pas être sérialisable.
- Facultatif: appliquez des personnalisations supplémentaires (par exemple, l'option Champs de libellé permet de transmettre une classe CSS, qui est ensuite appliquée au texte).
JSON et enregistrement
Dans les définitions de blocs JSON, les champs sont décrits par une chaîne (par exemple, field_number
, field_textinput
). Blockly conserve un mappage entre ces chaînes et des objets de champ, et appelle fromJson
sur l'objet approprié lors de la construction.
Appelez Blockly.fieldRegistry.register
pour ajouter votre type de champ à ce mappage, en transmettant la classe de champ comme deuxième argument:
Blockly.fieldRegistry.register('field_generic', GenericField);
Vous devez également définir votre fonction fromJson
. Votre implémentation doit d'abord déréférencer toutes les références de table de chaînes à 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 construit, il ne contient essentiellement qu'une valeur. L'initialisation désigne l'endroit où le DOM est compilé, le modèle (si le champ en possède un) et les événements sont liés.
Écran On Block
Lors de l'initialisation, vous devez créer tout ce dont vous avez besoin pour l'affichage dans le 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 souhaitez que votre champ contienne ces deux éléments, ainsi que d'autres avantages, appelez la fonction de super-classe initView
avant d'ajouter les autres éléments DOM. Si vous souhaitez que votre champ comporte un seul de ces éléments, mais pas les deux, vous pouvez utiliser les fonctions createBorderRect_
ou createTextElement_
.
Personnaliser la construction DOM
Si votre champ est un champ de texte générique (par exemple, Entrée de texte), la construction DOM est assurée automatiquement. Sinon, vous devrez remplacer la fonction initView
afin de créer les éléments DOM dont vous aurez besoin lors du rendu ultérieur de votre champ.
Par exemple, un champ déroulant peut contenir à la fois des images et du texte. Dans initView
, il crée un seul élément image et un seul élément de texte. Ensuite, pendant render_
, il affiche l'élément actif et masque l'autre, en fonction du type de l'option sélectionnée.
Vous pouvez créer des éléments DOM à l'aide de la méthode Blockly.utils.dom.createSvgElement
ou des méthodes traditionnelles de création DOM.
Voici les conditions requises pour l'affichage sur le bloc d'un champ:
- Tous les éléments DOM doivent être des enfants du
fieldGroup_
du champ. Le groupe de champs est créé automatiquement. - Tous les éléments DOM doivent rester à l'intérieur des dimensions signalées du champ.
Consultez la section Rendu pour découvrir comment personnaliser et mettre à jour l'affichage dans le bloc.
Ajouter des symboles de texte
Si vous souhaitez ajouter des symboles au texte d'un champ (comme le symbole de degré du champ Angle), vous pouvez ajouter l'élément de symbole (généralement contenu dans un <tspan>
) directement au textElement_
du champ.
Événements de saisie
Par défaut, les champs enregistrent les événements d'info-bulle et les événements de défilement du curseur (à utiliser pour afficher les éditeurs).
Si vous souhaitez écouter d'autres types d'événements (par exemple, si vous souhaitez gérer le déplacement 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 une liaison avec un événement, vous devez généralement utiliser la fonction Blockly.utils.browserEvents.conditionalBind
. Cette méthode d'association des événements filtre les gestes secondaires lors des déplacements. Si vous souhaitez que votre gestionnaire s'exécute même au milieu d'un déplacement en cours, vous pouvez utiliser la fonction Blockly.browserEvents.bind
.
Mise au rebut
Si vous avez enregistré des écouteurs d'événements personnalisés dans la fonction bindEvents_
du champ, vous devrez les désenregistrer dans la fonction dispose
.
Si vous avez correctement initialisé la vue de votre champ (en ajoutant tous les éléments DOM à fieldGroup_
), le DOM du champ est supprimé automatiquement.
Gestion de la valeur
→ Pour en savoir plus sur la valeur d'un champ par rapport à son texte, consultez la section Anatomie d'un champ.
Ordre de validation
Implémenter un validateur de classe
Les champs ne doivent accepter que certaines valeurs. Par exemple, les champs numériques ne doivent accepter que les chiffres, les champs de couleur ne doivent accepter que les couleurs, etc. Ce processus est garanti par des programmes de validation de classe et locaux. Le validateur de classe suit les mêmes règles que les validateurs locaux, sauf qu'il est également exécuté dans le constructeur et, par conséquent, il ne doit pas référencer le bloc source.
Pour implémenter le validateur de classe de votre champ, remplacez la fonction doClassValidation_
.
doClassValidation_(newValue) {
if (typeof newValue != 'string') {
return null;
}
return newValue;
};
Gérer les valeurs valides
Si la valeur transmise à un champ avec setValue
est valide, vous recevrez un rappel doValueUpdate_
. Par défaut, la fonction doValueUpdate_
:
- Définit la propriété
value_
surnewValue
. - Il définit la propriété
isDirty_
surtrue
.
Si vous devez simplement stocker la valeur et que vous ne souhaitez pas effectuer de gestion personnalisée, vous n'avez pas besoin de remplacer doValueUpdate_
.
Sinon, si vous souhaitez effectuer les opérations suivantes:
- Espace de stockage personnalisé de
newValue
. - Modifier d'autres propriétés en fonction de
newValue
. - Indiquez si la valeur actuelle est valide ou non.
Vous devez remplacer doValueUpdate_
:
doValueUpdate_(newValue) {
super.doValueUpdate_(newValue);
this.displayValue_ = newValue;
this.isValueValid_ = true;
}
Traiter les valeurs non valides
Si la valeur transmise dans le champ avec setValue
n'est pas valide, vous recevrez un rappel doValueInvalid_
. Par défaut, la fonction doValueInvalid_
n'a aucun effet. Cela signifie que, par défaut, les valeurs non valides ne sont pas affichées. Cela signifie également que le champ ne sera pas à nouveau affiché, car la propriété isDirty_
n'est 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 la valeur non valide, définir isDirty_
sur true
et remplacer render_ pour que l'affichage sur le bloc se mette à jour en fonction de displayValue_
au lieu de 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 (par exemple, des listes, des vecteurs, des objets), vous pouvez souhaiter que ces 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 n'est pas valide, la valeur est mise en cache dans la propriété cacheValidatedValue_
avant de renvoyer null
(non valide). La mise en cache de l'objet avec des propriétés validées individuellement permet à la fonction doValueInvalid_
de les gérer séparément, simplement en effectuant une vérification !this.cacheValidatedValue_.property
au lieu de revalider chaque propriété individuellement.
Ce modèle de validation des valeurs en plusieurs parties peut également être utilisé dans les programmes de validation locaux, mais il n'existe actuellement aucun moyen de l'appliquer.
isDirty_
isDirty_
est un indicateur utilisé dans la fonction setValue
, ainsi que dans d'autres parties du champ, pour déterminer si le champ doit être à nouveau affiché. Si la valeur d'affichage du champ a changé, isDirty_
doit généralement être défini sur true
.
Texte
→ Pour savoir où le texte d'un champ est utilisé et en quoi il diffère de la valeur du champ, consultez la section Anatomie d'un champ.
Si le texte de votre champ est différent de sa valeur, vous devez remplacer la 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 écoute automatiquement les clics et appelle showEditor_
au moment approprié. Vous pouvez afficher n'importe quel code HTML dans votre éditeur en l'encapsulant dans l'un des deux div spéciaux, appelés DropDownDiv et WidgetDiv, qui flottent au-dessus du reste de l'interface utilisateur de Blockly.
DropDownDiv vs WidgetDiv
DropDownDiv
permet de fournir des éditeurs qui résident dans une zone connectée à un champ. Il se positionne automatiquement pour être à proximité du champ tout en respectant les limites visibles. Le sélecteur d'angle et le sélecteur de couleur sont de bons exemples de DropDownDiv
.
WidgetDiv
permet de fournir des éditeurs qui ne se trouvent pas à l'intérieur d'une zone. Les champs numériques utilisent la classe WidgetDiv pour couvrir le champ avec une zone de saisie de texte HTML. Contrairement à DropDownDiv, qui gère le positionnement pour vous, WidgetDiv ne le fait pas. Les éléments devront être
positionnés manuellement. Le système de coordonnées est exprimé en coordonnées en pixels par rapport à l'angle supérieur gauche de la fenêtre. L'éditeur de saisie de texte est un bon exemple de WidgetDiv
.
Exemple de code DropDownDiv
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
DropDownDiv et WidgetDiv gèrent tous deux la destruction des éléments HTML du widget, mais vous devez supprimer manuellement tous les écouteurs d'événements que vous avez appliqués à 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 DropDownDiv
. Sur WidgetDiv
, elle est appelée dans le contexte de WidgetDiv
. Dans les deux cas, il est préférable d'utiliser la fonction bind lors de la transmission d'une fonction de suppression, comme indiqué dans les exemples DropDownDiv
et WidgetDiv
ci-dessus.
→ Pour en savoir plus sur la suppression des éditeurs, consultez la section Suppression.
Mettre à jour l'écran de blocage
La fonction render_
permet de mettre à jour l'affichage du champ dans le bloc pour qu'il corresponde à sa valeur interne.
Voici quelques exemples courants :
- Modifier le texte (liste déroulante)
- Modifier la couleur
Valeurs par défaut
La fonction render_
par défaut définit le texte d'affichage sur le résultat de la fonction getDisplayText_
. La fonction getDisplayText_
renvoie la propriété value_
du champ convertie en chaîne, une fois que celle-ci a été tronquée afin de respecter la longueur maximale du texte.
Si vous utilisez l'affichage par défaut sur le bloc et que le comportement de texte par défaut fonctionne pour votre champ, vous n'avez pas besoin de remplacer render_
.
Si le comportement de texte par défaut fonctionne pour votre champ, mais que l'affichage sur le bloc de votre champ contient des éléments statiques supplémentaires, vous pouvez appeler la fonction render_
par défaut, mais vous devrez toujours la remplacer pour mettre à jour la taille du champ.
Si le comportement de texte par défaut ne fonctionne pas pour votre champ ou si l'affichage sur le bloc de votre champ comporte des éléments dynamiques supplémentaires, vous devrez personnaliser la fonction render_
.
Personnaliser le rendu
Si le comportement de rendu par défaut ne fonctionne pas pour votre champ, vous devez définir un comportement d'affichage personnalisé. Il peut s'agir de définir un texte d'affichage personnalisé, de modifier des éléments d'image ou encore de modifier les couleurs d'arrière-plan.
Toutes les modifications d'attributs DOM sont légales. Les deux seuls points à retenir sont les suivants:
- La création DOM doit être gérée lors de l'initialisation, car elle est plus efficace.
- Vous devez toujours mettre à jour la propriété
size_
pour qu'elle corresponde à la taille de l'écran dans le 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 indique au code de rendu du bloc comment positionner le champ. Le meilleur moyen de déterminer exactement quel devrait être size_
est d'effectuer des tests.
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 correspondantes
Si vous souhaitez que les éléments de votre champ correspondent aux couleurs du bloc auquel ils sont associés, 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 possibilité de modification...
La fonction updateEditable
permet de modifier l'apparence d'un champ selon qu'il est modifiable ou non. Avec la fonction par défaut, l'arrière-plan présente ou n'a pas de réponse de survol (bordure) s'il est/n'est pas modifiable.
La taille de l'écran d'un bloc ne doit pas changer en fonction de sa possibilité 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 afin de pouvoir l'actualiser 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 un autre état, tel que l'état de l'interface utilisateur du champ. Par exemple, si votre champ était une carte avec possibilité de zoom permettant à l'utilisateur de sélectionner des pays, vous pouvez également sérialiser 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 hooks fonctionne avec le nouveau système de sérialisation JSON, et l'autre paire fonctionne avec 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 système de sérialisation JSON.
Dans certains cas, vous n'avez pas besoin de les fournir, car les implémentations par défaut fonctionneront. Si (1) votre champ est une sous-classe directe de la classe Blockly.Field
de base, (2) votre valeur est un type sérialisable JSON et (3) vous devez seulement sérialiser la valeur, l'implémentation par défaut fonctionnera parfaitement.
Sinon, votre fonction saveState
doit renvoyer un objet ou une valeur JSON sérialisable qui représente l'état du champ. De plus, votre fonction loadState
doit accepter le même objet/valeur JSON sérialisable et l'appliquer au champ.
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 sauvegarde des données
saveState
reçoit également un paramètre facultatif doFullSerialization
. Elle est utilisée par les champs qui font normalement référence à un état sérialisé par un 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é. Le champ doit donc effectuer l'intégralité de la sérialisation. C'est le cas lorsqu'un bloc individuel est sérialisé ou lorsqu'un bloc est copié et collé.
Voici deux cas d'utilisation courants:
- Lorsqu'un bloc individuel est chargé dans un espace de travail où le modèle de données de sauvegarde n'existe pas, le champ dispose de 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 modèle de données de sauvegarde au lieu de référencer un modèle existant.
Un champ qui l'utilise est le champ de variable intégrée. Normalement, elle sérialise l'ID de la variable à laquelle elle fait référence, mais si doFullSerialization
est défini sur "true", il sérialise l'ensemble de son état.
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 de variable permet de s'assurer que, si elle est chargée dans un espace de travail où sa variable n'existe pas, il peut créer une variable à référencer.
toXml
et fromXml
toXml
et fromXml
sont des hooks de sérialisation qui fonctionnent avec l'ancien système de sérialisation XML. N'utilisez ces hooks que si vous le devez (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 du champ. De plus, votre fonction fromXml
doit accepter le même nœud XML et l'appliquer au champ.
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 qu'il est possible d'interagir avec. Sa valeur par défaut est true
.
La propriété SERIALIZABLE
détermine si le champ doit être sérialisé. La valeur par défaut est false
. Si cette propriété est true
, vous devrez peut-être fournir des fonctions de sérialisation et de désérialisation (voir la section Sérialisation).
Personnaliser le curseur
La propriété CURSOR
détermine le curseur que les utilisateurs voient lorsqu'ils passent la souris sur votre champ. 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 est le curseur de saisie.