O campo suspenso armazena uma string como valor e outra como texto. A value é uma chave de linguagem neutra que será usada para acessar o texto e não será traduzido quando o Blockly alternar entre os idiomas. O texto é uma string legível que será exibida ao usuário.
Campo de menu suspenso
Campo do menu suspenso com o editor aberto
Campo de menu suspenso no bloco recolhido
Criação
O construtor de menu suspenso recebe um gerador de menu e um validador da solicitação. O gerador de menu tem muitos flexibilidade, mas é essencialmente uma matriz de opções, cada uma contendo uma uma parte legível por humanos e uma string de linguagem neutra.
Menus suspensos de texto simples
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');
}
};
Manter as informações legíveis por humanos separadas da chave de linguagem neutra
permite que a configuração do menu suspenso seja preservada entre os idiomas. Para
Uma versão em inglês de um bloco pode definir [['left', 'LEFT'], ['right',
'RIGHT]]
, enquanto uma versão em alemão do mesmo bloco define [['links',
'LEFT'], ['rechts', 'RIGHT]]
.
Menus suspensos de imagem
As opções em um menu suspenso também podem ser imagens em vez de texto. Objetos de imagem são
especificado com as propriedades src
, width
, height
e alt
.
Um menu suspenso pode ter uma mistura de opções de texto e imagem, uma opção individual não pode conter uma imagem e um texto ao mesmo tempo.
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');
}
};
Listas suspensas dinâmicas
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');
});
Isso é feito usando um JSON extensão.
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;
}
};
Um menu suspenso também pode ser fornecido com uma função em vez de uma lista de objetos
, o que permite que as opções sejam dinâmicas. A função deve retornar um
matriz de opções na mesma [human-readable-value, language-neutral-key]
como opções estáticas. Sempre que o menu suspenso é clicado, a função é
executada e as opções são recalculadas.
Serialização
JSON
O JSON de um campo suspenso tem esta aparência:
{
"fields": {
"FIELDNAME": "LANGUAGE-NEUTRAL-KEY"
}
}
Em que FIELDNAME
é uma string que faz referência a um campo suspenso e
o valor é o valor a ser aplicado ao campo. O valor deve ser um
chave de opção de linguagem neutra.
XML
O XML de um campo suspenso tem esta aparência:
<field name="FIELDNAME">LANGUAGE-NEUTRAL-KEY</field>
O atributo name
do campo contém uma string que faz referência a um menu suspenso.
e o texto interno é o valor a ser aplicado ao campo. O interior
text deve ser uma chave de opção válida de linguagem neutra.
Personalização
Seta suspensa
A propriedade Blockly.FieldDropdown.ARROW_CHAR
pode ser usada para mudar o
caractere Unicode que representa a seta suspensa.
A propriedade ARROW_CHAR
assume o \u25BC
(▼) por padrão no Android e \u25BE
(▾)
caso contrário.
Essa é uma propriedade global, portanto, ela modificará todos os campos suspensos quando definida.
Altura do menu
A propriedade Blockly.FieldDropdown.MAX_MENU_HEIGHT_VH
pode ser usada para mudar
a altura máxima do menu. Ela é definida como uma porcentagem da janela de visualização
altura, sendo a janela de visualização a janela.
A propriedade MAX_MENU_HEIGHT_VH
assume o padrão 0,45.
Essa é uma propriedade global, portanto, ela modificará todos os campos suspensos quando definida.
Correspondência de prefixo/sufixo
Se todas as opções do menu suspenso compartilharem prefixo e/ou sufixo comum as palavras são automaticamente fatoradas e inseridas como texto estático. Por exemplo, aqui estão duas maneiras de criar o mesmo bloco (a primeira sem correspondência de sufixo e o segundo com):
Sem correspondência de sufixo:
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');
}
};
Com correspondência de sufixo:
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');
}
};
Uma vantagem dessa abordagem é que o bloco é mais fácil de traduzir para
em outros idiomas. O código anterior tem as strings 'hello'
, 'world'
e
'computer'
, enquanto o código revisado tem as strings 'hello world'
e
'hello computer'
. Os tradutores têm muito mais facilidade ao traduzir frases do que
as palavras isoladamente.
Outra vantagem dessa abordagem é que a ordem das palavras geralmente muda entre
idiomas. Imagine um idioma que usa 'world hello'
e 'computer hello'
.
O algoritmo de correspondência de sufixo vai detectar e mostrar o 'hello'
comum
após o menu suspenso.
No entanto, às vezes a correspondência de prefixo/sufixo falha. Há alguns casos em que
duas palavras devem sempre andar juntas e o prefixo não deve ser considerado.
Por exemplo, 'drive red car'
e 'drive red truck'
provavelmente só deveriam
têm 'drive'
fatorado, não 'drive red'
. O modelo Unicode não interruptivo
espaço '\u00A0'
pode ser usado em vez de um espaço regular para suprimir o
prefixo/sufixo correspondente. Assim, o exemplo acima pode ser corrigido
'drive red\u00A0car'
e 'drive red\u00A0truck'
.
Outro lugar em que a correspondência de prefixo/sufixo falha é em idiomas que não
separe palavras individuais com espaços. O chinês é um bom exemplo. A string
'訪問中國'
significa 'visit China'
. Observe a falta de espaços entre as palavras.
Coletivamente, os dois últimos caracteres ('中國'
) são a palavra para 'China'
,
mas, se divididos, eles significam 'centre'
e 'country'
, respectivamente. Para fazer
a correspondência de prefixo/sufixo funciona em idiomas como chinês,
basta inserir um espaço
onde a quebra deveria estar. Por exemplo, '訪問 中國'
e
'訪問 美國'
resultaria em "visit [China/USA]"
, enquanto '訪問 中 國'
e
'訪問 美 國'
resultaria em "visit [centre/beautiful] country"
.
Como criar um validador de lista suspensa
O valor de um campo suspenso é uma string de linguagem neutra. Portanto, todos os validadores precisam
Aceitar uma string e retornar uma string que é uma opção disponível, null
ou
undefined
.
Caso seu validador retorne algo diferente, o comportamento do Blockly é indefinido e seu programa pode falhar.
Por exemplo, você pode definir um campo suspenso com três opções e um validador da seguinte forma:
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
sempre retorna o valor transmitido, mas chama o auxiliar.
função updateConnection
, que adiciona ou remove entradas com base na lista suspensa
:
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');
}
}