Le champ déroulant stocke une chaîne en tant que valeur et une chaîne en tant que texte. La est une clé indépendante du langage qui sera utilisée pour accéder au texte n'est pas traduit lorsque vous changez de langue avec Blockly. Le texte est une chaîne lisible qui sera présentée à l'utilisateur.
Champ déroulant
Champ déroulant avec l'éditeur ouvert
Champ déroulant du bloc réduit
Création
Le constructeur de menu déroulant utilise un générateur de menu et un programme de validation. Le générateur de menu a beaucoup de la flexibilité, mais il s'agit essentiellement d'un tableau d'options, chacune contenant une une partie lisible par l'humain et une chaîne indépendante du langage.
Menus déroulants contenant du texte simple
JSON
{
"type": "example_dropdown",
"message0": "drop down: %1",
"args0": [
{
"type": "field_dropdown",
"name": "FIELDNAME",
"options": [
[ "first item", "ITEM1" ],
[ "second item", "ITEM2" ]
]
}
]
}
JavaScript
Blockly.Blocks['example_dropdown'] = {
init: function() {
this.appendDummyInput()
.appendField('drop down:')
.appendField(new Blockly.FieldDropdown([
['first item', 'ITEM1'],
['second item', 'ITEM2']
]), 'FIELDNAME');
}
};
Séparer les informations lisibles par l'humain de la clé neutre en termes de langue
permet de conserver les paramètres du menu déroulant d'une langue à l'autre. Pour
instance Une version anglaise d'un bloc peut définir [['left', 'LEFT'], ['right',
'RIGHT]]
tandis qu'une version allemande du même bloc définirait [['links',
'LEFT'], ['rechts', 'RIGHT]]
.
Menus déroulants d'images
Les options d'un menu déroulant peuvent également être des images au lieu de texte. Les objets image sont
spécifié avec les propriétés src
, width
, height
et alt
.
Remarque : bien qu'un menu déroulant puisse contenir à la fois des options de texte et d'image, une option individuelle ne peut pas contenir à la fois une image et du texte.
JSON
{
"type": "image_dropdown",
"message0": "flag %1",
"args0": [
{
"type": "field_dropdown",
"name": "FLAG",
"options": [
["none", "NONE"],
[{"src": "canada.png", "width": 50, "height": 25, "alt": "Canada"}, "CANADA"],
[{"src": "usa.png", "width": 50, "height": 25, "alt": "USA"}, "USA"],
[{"src": "mexico.png", "width": 50, "height": 25, "alt": "Mexico"}, "MEXICO"]
]
}
]
}
JavaScript
Blockly.Blocks['image_dropdown'] = {
init: function() {
var input = this.appendDummyInput()
.appendField('flag');
var options = [
['none', 'NONE'],
[{'src': 'canada.png', 'width': 50, 'height': 25, 'alt': 'Canada'}, 'CANADA'],
[{'src': 'usa.png', 'width': 50, 'height': 25, 'alt': 'USA'}, 'USA'],
[{'src': 'mexico.png', 'width': 50, 'height': 25, 'alt': 'Mexico'}, 'MEXICO']
];
input.appendField(new Blockly.FieldDropdown(options), 'FLAG');
}
};
Menus déroulants dynamiques
JSON
{
"type": "dynamic_dropdown",
"message0": "day %1",
"args0": [
{
"type": "input_dummy",
"name": "INPUT"
}
],
"extensions": ["dynamic_menu_extension"]
}
Blockly.Extensions.register('dynamic_menu_extension',
function() {
this.getInput('INPUT')
.appendField(new Blockly.FieldDropdown(
function() {
var options = [];
var now = Date.now();
for(var i = 0; i < 7; i++) {
var dateString = String(new Date(now)).substring(0, 3);
options.push([dateString, dateString.toUpperCase()]);
now += 24 * 60 * 60 * 1000;
}
return options;
}), 'DAY');
});
Pour ce faire, vous devez utiliser un fichier extension.
JavaScript
Blockly.Blocks['dynamic_dropdown'] = {
init: function() {
var input = this.appendDummyInput()
.appendField('day')
.appendField(new Blockly.FieldDropdown(
this.generateOptions), 'DAY');
},
generateOptions: function() {
var options = [];
var now = Date.now();
for(var i = 0; i < 7; i++) {
var dateString = String(new Date(now)).substring(0, 3);
options.push([dateString, dateString.toUpperCase()]);
now += 24 * 60 * 60 * 1000;
}
return options;
}
};
Un menu déroulant peut également être fourni avec une fonction au lieu d'une liste d'éléments statiques
ce qui leur permet d'être dynamiques. La fonction doit renvoyer une
tableau d'options dans le même [human-readable-value, language-neutral-key]
en tant qu'options statiques. Chaque fois que l'utilisateur clique
sur le menu déroulant,
et les options sont recalculées.
Sérialisation
JSON
Le JSON d'un champ de liste déroulante se présente comme suit:
{
"fields": {
"FIELDNAME": "LANGUAGE-NEUTRAL-KEY"
}
}
Où FIELDNAME
est une chaîne faisant référence à un champ de liste déroulante, et où
la valeur est celle à appliquer au champ. Cette valeur doit être une
la clé d'option neutre de la langue cible.
XML
Le code XML d'un champ de liste déroulante se présente comme suit:
<field name="FIELDNAME">LANGUAGE-NEUTRAL-KEY</field>
Où l'attribut name
du champ contient une chaîne faisant référence à un menu déroulant
et le texte interne est la valeur à appliquer au champ. L'intérieur
le texte doit être une clé d'option neutre et valide.
Personnalisation
Flèche du menu déroulant
La propriété Blockly.FieldDropdown.ARROW_CHAR
permet de modifier
caractère Unicode représentant la flèche de la liste déroulante.
Par défaut, la propriété ARROW_CHAR
est définie sur \u25BC
(▼) sur Android et \u25BE
(▾)
sinon.
Comme il s'agit d'une propriété globale, tous les champs de la liste déroulante sont modifiés lorsqu'ils sont définis.
Hauteur du menu
La propriété Blockly.FieldDropdown.MAX_MENU_HEIGHT_VH
permet de modifier
la hauteur maximale du menu. Il s'agit d'un pourcentage de la fenêtre d'affichage
la hauteur, la fenêtre d'affichage étant la fenêtre.
La propriété MAX_MENU_HEIGHT_VH
est définie par défaut sur 0,45.
Comme il s'agit d'une propriété globale, tous les champs de la liste déroulante sont modifiés lorsqu'ils sont définis.
Correspondance de préfixe/suffixe
Si toutes les options du menu déroulant partagent un préfixe et/ou un suffixe communs les mots sont automatiquement pris en compte et insérés sous forme de texte statique. Par exemple, voici deux façons de créer le même bloc (la première, sans indication de suffixe, et la deuxième par):
Sans correspondance de suffixe:
JSON
{
"type": "dropdown_no_matching",
"message0": "hello %1",
"args0": [
{
"type": "field_dropdown",
"name": "MODE",
"options": [
["world", "WORLD"],
["computer", "CPU"]
]
}
]
}
JavaScript
Blockly.Blocks['dropdown_no_matching'] = {
init: function() {
var options = [
['world', 'WORLD'],
['computer', 'CPU']
];
this.appendDummyInput()
.appendField('hello')
.appendField(new Blockly.FieldDropdown(options), 'MODE');
}
};
Avec correspondance de suffixe:
JSON
{
"type": "dropdown_with_matching",
"message0": "%1",
"args0": [
{
"type": "field_dropdown",
"name": "MODE",
"options": [
["hello world", "WORLD"],
["hello computer", "CPU"]
]
}
]
}
JavaScript
Blockly.Blocks['dropdown_with_matching'] = {
init: function() {
var options = [
['hello world', 'WORLD'],
['hello computer', 'CPU']
];
this.appendDummyInput()
.appendField(new Blockly.FieldDropdown(options), 'MODE');
}
};
L'un des avantages de cette approche est que le bloc est plus facile à traduire
dans d'autres langues. Le code précédent contient les chaînes 'hello'
, 'world'
et
'computer'
, alors que le code révisé contient les chaînes 'hello world'
et
'hello computer'
Les traducteurs ont plus de facilité à traduire des expressions
les mots
de manière isolée.
Un autre avantage de cette approche est que l'ordre des mots change souvent
langues. Imaginez un langage qui utilise 'world hello'
et 'computer hello'
.
L'algorithme de mise en correspondance des suffixes détecte le 'hello'
courant et l'affiche
après le menu déroulant.
Cependant, il arrive que la correspondance du préfixe/suffixe échoue. Dans certains cas,
deux mots doivent toujours aller ensemble
et le préfixe ne doit pas être exclu.
Par exemple, 'drive red car'
et 'drive red truck'
ne devraient normalement
ont été exclus de 'drive'
, et non de 'drive red'
. Le caractère insécable d'Unicode
l'espace '\u00A0'
peut être utilisé à la place d'un espace normal pour supprimer le
un outil de mise en correspondance des préfixes/suffixes. Ainsi, l'exemple ci-dessus peut être corrigé avec
'drive red\u00A0car'
et 'drive red\u00A0truck'
.
La mise en correspondance des préfixes/suffixes peut également échouer dans les langues qui ne
séparez les mots
individuels par des espaces. Le chinois en est un bon exemple. La chaîne
'訪問中國'
signifie 'visit China'
(notez le manque d'espaces entre les mots).
Collectivement, les deux derniers caractères ('中國'
) correspondent au mot 'China'
,
mais s'il s'agit d'une division, ils signifient respectivement 'centre'
et 'country'
. Pour
la correspondance de préfixe/suffixe fonctionne
dans des langues telles que le chinois,
il suffit d'insérer un espace
à l'emplacement du saut. Par exemple, '訪問 中國'
et
'訪問 美國'
donnerait "visit [China/USA]"
, tandis que '訪問 中 國'
et
'訪問 美 國'
générerait "visit [centre/beautiful] country"
.
Créer un validateur de liste déroulante
La valeur d'un champ déroulant est une chaîne neutre en termes de langue. Par conséquent, tous les validateurs
accepter une chaîne et renvoyer une chaîne qui est une option disponible, null
ou
undefined
Si votre programme de validation renvoie un autre élément, le comportement de Blockly n'est pas défini et votre programme peut planter.
Par exemple, vous pouvez définir un champ déroulant avec trois options et une propriété programme de validation comme suit:
validate: function(newValue) {
this.getSourceBlock().updateConnections(newValue);
return newValue;
},
init: function() {
var options = [
['has neither', 'NEITHER'],
['has statement', 'STATEMENT'],
['has value', 'VALUE'],
];
this.appendDummyInput()
// Pass the field constructor the options list, the validator, and the name.
.appendField(new Blockly.FieldDropdown(options, this.validate), 'MODE');
}
validate
renvoie toujours la valeur transmise, mais appelle l'application auxiliaire.
updateConnection
, qui ajoute ou supprime des entrées en fonction du menu déroulant
:
updateConnections: function(newValue) {
this.removeInput('STATEMENT', /* no error */ true);
this.removeInput('VALUE', /* no error */ true);
if (newValue == 'STATEMENT') {
this.appendStatementInput('STATEMENT');
} else if (newValue == 'VALUE') {
this.appendValueInput('VALUE');
}
}