Les extensions sont des fonctions qui s'exécutent sur chaque bloc d'un type donné lorsque le bloc est créé. Ils ajoutent souvent une configuration ou un comportement personnalisés à un bloc.
Un mutateur est un type spécial d'extension qui ajoute une sérialisation personnalisée, et parfois à l'UI, à un bloc.
Extensions
Les extensions sont des fonctions qui s'exécutent sur chaque bloc d'un type donné lorsque le bloc est créé. Il peut ajouter une configuration personnalisée (par exemple, en définissant l'info-bulle du bloc) ou comportement personnalisé (par exemple, ajout d'un écouteur d'événements au bloc).
// This extension sets the block's tooltip to be a function which displays
// the parent block's tooltip (if it exists).
Blockly.Extensions.register(
'parent_tooltip_extension',
function() { // this refers to the block that the extension is being run on
var thisBlock = this;
this.setTooltip(function() {
var parent = thisBlock.getParent();
return (parent && parent.getInputsInline() && parent.tooltip) ||
Blockly.Msg.MATH_NUMBER_TOOLTIP;
});
});
Les extensions doivent être enregistrées. afin qu'ils puissent être associés à une chaîne
. Vous pouvez ensuite attribuer cette clé de chaîne à la propriété extensions
de votre
le code JSON du type de bloc
définition pour appliquer la
l'extension au bloc.
{
//...,
"extensions": ["parent_tooltip_extension",]
}
Vous pouvez également ajouter plusieurs extensions à la fois. Notez que extensions
doit être un tableau, même si vous n'appliquez qu'une seule extension.
{
//...,
"extensions": ["parent_tooltip_extension", "break_warning_extension"],
}
Mix
Blockly offre également une méthode pratique pour les situations où vous souhaitez ajouter des propriétés/fonctions d'assistance à un bloc, mais pas de les exécuter immédiatement. Ce car elle vous permet d'enregistrer un mixin qui contient toutes vos propriétés/méthodes supplémentaires. Objet mixin est ensuite encapsulé dans une fonction qui applique le mixin chaque fois qu'une instance de le type de bloc donné est créé.
Blockly.Extensions.registerMixin('my_mixin', {
someProperty: 'a cool value',
someMethod: function() {
// Do something cool!
}
))`
Les clés de chaîne associées aux mixins peuvent être référencées dans JSON comme n'importe quelle autre .
{
//...,
"extensions": ["my_mixin"],
}
Mutateurs
Un mutateur est un type spécial d'extension qui ajoute une sérialisation supplémentaire
enregistré et chargé) dans un bloc. Par exemple, l'API intégrée
Les blocs controls_if
et list_create_with
nécessitent une sérialisation supplémentaire pour que
il peut enregistrer le nombre
d'entrées dont il dispose.
Notez que la modification de la forme de votre volume ne signifie pas nécessairement que vous devez
une sérialisation supplémentaire. Par exemple, le bloc math_number_property
change
mais en se basant sur un champ de liste déroulante, dont la valeur est déjà
sérialisées. Par conséquent, il peut simplement utiliser un champ
de l'outil de validation
ont besoin d'un mutateur.
Examinez la sérialisation de Google pour plus d'informations sur les cas où vous avez besoin d'un mutateur ou non.
Ils fournissent également une interface utilisateur intégrée permettant aux utilisateurs de modifier la forme des volumes si vous fournissez des méthodes facultatives.
Hooks de sérialisation
Les mutateurs utilisent deux paires de hooks de sérialisation. 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. Vous devez fournir au moins l'une de ces paires.
saveExtraState et loadExtraState
saveExtraState
et loadExtraState
sont des hooks de sérialisation qui fonctionnent avec
un nouveau système de sérialisation JSON. saveExtraState
renvoie un objet JSON sérialisable
qui représente l'état supplémentaire du bloc, et loadExtraState
accepte cette même valeur JSON sérialisable et l'applique au bloc.
// These are the serialization hooks for the lists_create_with block.
saveExtraState: function() {
return {
'itemCount': this.itemCount_,
};
},
loadExtraState: function(state) {
this.itemCount_ = state['itemCount'];
// This is a helper function which adds or removes inputs from the block.
this.updateShape_();
},
Le fichier JSON obtenu se présente comme suit:
{
"type": "lists_create_with",
"extraState": {
"itemCount": 3 // or whatever the count is
}
}
Aucun état
Si votre bloc est dans son état par défaut lorsqu'il est sérialisé, votre
La méthode saveExtraState
peut renvoyer null
pour l'indiquer. Si votre
La méthode saveExtraState
renvoie null
, puis aucune propriété extraState
n'est ajoutée à
au format JSON. Cela permet de réduire la taille du fichier d'enregistrement.
Sérialisation complète et données de sauvegarde
saveExtraState
reçoit également un paramètre doFullSerialization
facultatif. Ce
est utilisée par les blocs qui font référence à l'é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 sérialiser tout l'état de support lui-même. Par exemple, il s'agit
Valeur true 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ù les données de sauvegarde n'existe pas, il dispose de suffisamment d'informations dans son propre état pour créer un modèle de données.
- Lorsqu'un bloc est copié-collé, il crée toujours un nouveau support au lieu de référencer un modèle existant.
Certains blocs qui l'utilisent sont
Blocages @blockly/block-shareable-procedures Normalement
ils sérialisent une référence à un modèle de données de sauvegarde, qui stocke leur état.
Mais si le paramètre doFullSerialization
est "true", ils sérialisent l'ensemble
leur état. Les blocs de procédures partageables l'utilisent
pour s'assurer que lorsqu'ils
Ils créent un modèle de données de sauvegarde au lieu de référencer
un modèle existant.
mutationToDom et domToMutation
mutationToDom
et domToMutation
sont des hooks de sérialisation qui fonctionnent avec
de l'ancien système de sérialisation XML. N'utilisez ces hooks que si cela est nécessaire (par exemple,
travaillant sur un ancien codebase qui n'a pas encore été migré), sinon utilisez
saveExtraState
et loadExtraState
.
mutationToDom
renvoie un nœud XML qui représente l'état supplémentaire du
bloc, et domToMutation
accepte le même nœud XML et applique l'état à
dans le bloc.
// These are the old XML serialization hooks for the lists_create_with block.
mutationToDom: function() {
// You *must* create a <mutation></mutation> element.
// This element can have children.
var container = Blockly.utils.xml.createElement('mutation');
container.setAttribute('items', this.itemCount_);
return container;
},
domToMutation: function(xmlElement) {
this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10);
// This is a helper function which adds or removes inputs from the block.
this.updateShape_();
},
Le code XML obtenu se présente comme suit:
<block type="lists_create_with">
<mutation items="3"></mutation>
</block>
Si votre fonction mutationToDom
renvoie une valeur nulle, aucun élément supplémentaire ne sera
dans le fichier XML.
Crochets d'interface utilisateur
Si vous fournissez certaines fonctions dans votre mutateur, Blockly ajoute un "mutateur" par défaut à votre bloc.
Vous n'avez pas besoin d'utiliser cette interface utilisateur si vous souhaitez ajouter une sérialisation supplémentaire. Vous pourriez utilisez une interface utilisateur personnalisée, comme la fonction blocs-plus-moins plug-in ou vous pourriez n'utiliser aucune UI !
compose et décompose
L'interface utilisateur par défaut repose sur les fonctions compose
et decompose
.
decompose
"explose" le bloc en sous-blocs plus petits,
supplémentaires, ajoutées et supprimées. Cette fonction doit renvoyer un "bloc supérieur" qui est
le bloc principal de l'espace de travail du mutateur auquel les sous-blocs se connectent.
compose
interprète ensuite la configuration des sous-blocs et les utilise pour
modifier le bloc principal. Cette fonction doit accepter le "bloc supérieur" qui était
renvoyé par decompose
en tant que paramètre.
Notez que ces fonctions sont "mélangées" au bloc "muté" donc this
pour faire référence à ce bloc.
// These are the decompose and compose functions for the lists_create_with block.
decompose: function(workspace) {
// This is a special sub-block that only gets created in the mutator UI.
// It acts as our "top block"
var topBlock = workspace.newBlock('lists_create_with_container');
topBlock.initSvg();
// Then we add one sub-block for each item in the list.
var connection = topBlock.getInput('STACK').connection;
for (var i = 0; i < this.itemCount_; i++) {
var itemBlock = workspace.newBlock('lists_create_with_item');
itemBlock.initSvg();
connection.connect(itemBlock.previousConnection);
connection = itemBlock.nextConnection;
}
// And finally we have to return the top-block.
return topBlock;
},
// The container block is the top-block returned by decompose.
compose: function(topBlock) {
// First we get the first sub-block (which represents an input on our main block).
var itemBlock = topBlock.getInputTargetBlock('STACK');
// Then we collect up all of the connections of on our main block that are
// referenced by our sub-blocks.
// This relates to the saveConnections hook (explained below).
var connections = [];
while (itemBlock && !itemBlock.isInsertionMarker()) { // Ignore insertion markers!
connections.push(itemBlock.valueConnection_);
itemBlock = itemBlock.nextConnection &&
itemBlock.nextConnection.targetBlock();
}
// Then we disconnect any children where the sub-block associated with that
// child has been deleted/removed from the stack.
for (var i = 0; i < this.itemCount_; i++) {
var connection = this.getInput('ADD' + i).connection.targetConnection;
if (connection && connections.indexOf(connection) == -1) {
connection.disconnect();
}
}
// Then we update the shape of our block (removing or adding iputs as necessary).
// `this` refers to the main block.
this.itemCount_ = connections.length;
this.updateShape_();
// And finally we reconnect any child blocks.
for (var i = 0; i < this.itemCount_; i++) {
connections[i].reconnect(this, 'ADD' + i);
}
},
saveConnections
Vous pouvez également définir une fonction saveConnections
compatible avec
l'interface utilisateur par défaut. Cette fonction vous permet d'associer les enfants
bloc principal (qui existe dans l'espace de travail principal) avec des sous-blocs présents dans
l'espace de travail du mutateur. Vous pouvez ensuite utiliser ces données pour vous assurer que votre compose
relie correctement les enfants de votre bloc principal lorsque votre
les sous-blocs sont réorganisés.
saveConnections
doit accepter le "bloc supérieur" renvoyées par votre decompose
en tant que paramètre. Si la fonction saveConnections
est définie, Blockly
l'appellera avant d'appeler compose
.
saveConnections: function(topBlock) {
// First we get the first sub-block (which represents an input on our main block).
var itemBlock = topBlock.getInputTargetBlock('STACK');
// Then we go through and assign references to connections on our main block
// (input.connection.targetConnection) to properties on our sub blocks
// (itemBlock.valueConnection_).
var i = 0;
while (itemBlock) {
// `this` refers to the main block (which is being "mutated").
var input = this.getInput('ADD' + i);
// This is the important line of this function!
itemBlock.valueConnection_ = input && input.connection.targetConnection;
i++;
itemBlock = itemBlock.nextConnection &&
itemBlock.nextConnection.targetBlock();
}
},
Enregistrement…
Les mutateurs ne sont qu'un type d'extension spécial. Ils doivent donc également être enregistrées avant de pouvoir les utiliser dans le fichier JSON de votre type de bloc définition.
// Function signature.
Blockly.Extensions.registerMutator(name, mixinObj, opt_helperFn, opt_blockList);
// Example call.
Blockly.Extensions.registerMutator(
'controls_if_mutator',
{ /* mutator methods */ },
undefined,
['controls_if_elseif', 'controls_if_else']);
name
: chaîne à associer au mutateur pour pouvoir l'utiliser au format JSON.mixinObj
: objet contenant les différentes méthodes de mutation. Exemple :saveExtraState
etloadExtraState
.opt_helperFn
: fonction d'assistance facultative qui s'exécuter sur le bloc après le mélange.opt_blockList
: tableau facultatif de types de blocs (sous forme de chaînes) qui ajouté au menu déroulant dans l'UI du mutateur par défaut, si les méthodes d'UI sont également définis.
Notez que, contrairement aux extensions, chaque type de bloc ne peut avoir qu'un seul mutateur.
{
//...
"mutator": "controls_if_mutator"
}
Fonction d'assistance
Avec le mixin, un mutateur peut enregistrer une fonction d'assistance. Cette fonction est sur chaque bloc du type donné après sa création et que le mixinObj est ajouté. Elle permet d'ajouter des déclencheurs ou des effets à une mutation.
Par exemple, vous pouvez ajouter un assistant à votre bloc de type liste qui définit nombre initial d'articles:
var helper = function() {
this.itemCount_ = 5;
this.updateShape();
}