Im Drop-down-Feld werden ein String als Wert und ein String als Text gespeichert. Der Wert ist ein sprachneutraler Schlüssel, der für den Zugriff auf den Text verwendet und nicht übersetzt wird, wenn Blockly zwischen den Sprachen gewechselt wird. Der Text ist ein für Menschen lesbarer String, der dem Nutzer angezeigt wird.
Drop-down-Feld
Drop-down-Feld bei geöffnetem Editor
Drop-down-Feld in minimiertem Block
Erstellung
Der Drop-down-Konstruktor übernimmt einen Menügenerator und einen optionalen validator. Der Menügenerator ist sehr flexibel, besteht jedoch im Wesentlichen aus einem Array von Optionen, wobei jede Option einen für Menschen lesbaren Teil und einen sprachneutralen String enthält.
Einfache Text-Dropdown-Menüs
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');
}
};
Wenn die visuell lesbaren Informationen vom sprachneutralen Schlüssel getrennt bleiben, bleibt die Einstellung des Drop-down-Menüs zwischen den Sprachen erhalten. Beispielsweise kann für eine englische Version eines Blocks [['left', 'LEFT'], ['right',
'RIGHT]]
definiert werden, während in einer deutschen Version desselben Blocks [['links',
'LEFT'], ['rechts', 'RIGHT]]
definiert wird.
Drop-down-Menüs für Bilder
Optionen in einem Dropdown-Menü können auch Bilder anstelle von Text enthalten. Bildobjekte werden mit den Attributen src
, width
, height
und alt
angegeben.
Obwohl ein Drop-down-Menü eine Mischung aus Text- und Bildoptionen enthalten kann, kann eine einzelne Option derzeit nicht sowohl ein Bild als auch Text enthalten.
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');
}
};
Dynamische Drop-down-Menüs
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');
});
Dies geschieht mithilfe einer JSON-Erweiterung.
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;
}
};
Ein Drop-down-Menü kann auch mit einer Funktion anstelle einer Liste statischer Optionen bereitgestellt werden. Dadurch sind die Optionen dynamisch. Die Funktion sollte ein Array mit Optionen im selben [human-readable-value, language-neutral-key]
-Format wie statische Optionen zurückgeben. Bei jedem Klick auf das Drop-down-Menü wird die Funktion ausgeführt und die Optionen werden neu berechnet.
Serialisierung
JSON
Der JSON-Code für ein Drop-down-Feld sieht so aus:
{
"fields": {
"FIELDNAME": "LANGUAGE-NEUTRAL-KEY"
}
}
Dabei ist FIELDNAME
ein String, der auf ein Drop-down-Feld verweist, und der Wert ist der Wert, der auf das Feld angewendet werden soll. Der Wert sollte ein sprachneutraler Optionsschlüssel sein.
XML
Der XML-Code für ein Drop-down-Feld sieht so aus:
<field name="FIELDNAME">LANGUAGE-NEUTRAL-KEY</field>
Dabei enthält das Attribut name
des Felds einen String, der auf ein Drop-down-Feld verweist, und der innere Text ist der Wert, der auf das Feld angewendet werden soll. Der innere Text sollte ein gültiger sprachneutraler Optionsschlüssel sein.
Anpassbare
Drop-down-Pfeil
Mit dem Attribut Blockly.FieldDropdown.ARROW_CHAR
kann das Unicode-Zeichen für den Drop-down-Pfeil geändert werden.
Die Property ARROW_CHAR
ist unter Android standardmäßig auf \u25BC
(▼) und andernfalls auf \u25BE
(▾) festgelegt.
Da dies eine globale Eigenschaft ist, werden alle Drop-down-Felder geändert, wenn sie festgelegt wird.
Menühöhe
Mit dem Attribut Blockly.FieldDropdown.MAX_MENU_HEIGHT_VH
kann die maximale Höhe des Menüs geändert werden. Sie wird als Prozentsatz der Höhe des Darstellungsbereichs definiert, wobei der Darstellungsbereich das Fenster ist.
Der Standardwert für die Eigenschaft MAX_MENU_HEIGHT_VH
ist „0,45“.
Da dies eine globale Eigenschaft ist, werden alle Drop-down-Felder geändert, wenn sie festgelegt wird.
Abgleich von Präfixen und Suffixen
Wenn alle Optionen des Drop-down-Menüs ein gemeinsames Präfix und/oder Suffixe haben, werden diese Wörter automatisch herausgefiltert und als statischen Text eingefügt. Es gibt beispielsweise zwei Möglichkeiten, denselben Block zu erstellen (davon eine ohne Abgleich des Suffixes und die zweite mit):
Ohne Suffixabgleich:
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');
}
};
Mit Suffixabgleich:
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');
}
};
Ein Vorteil dieses Ansatzes besteht darin, dass der Block einfacher in andere Sprachen übersetzt werden kann. Der frühere Code hat die Strings 'hello'
, 'world'
und 'computer'
, während der überarbeitete Code die Strings 'hello world'
und 'hello computer'
enthält. Übersetzer können Sätze viel einfacher übersetzen als Wörter, die isoliert sind.
Ein weiterer Vorteil dieses Ansatzes besteht darin, dass sich die Wortreihenfolge in einer Sprache häufig ändert. Beispiel: 'world hello'
und 'computer hello'
werden verwendet.
Der Algorithmus zum Suffixabgleich erkennt den gemeinsamen 'hello'
und zeigt ihn nach dem Drop-down-Menü an.
Manchmal schlägt der Abgleich von Präfixen und Suffixen jedoch fehl. Es gibt einige Fälle, in denen zwei Wörter immer zusammen stehen sollten und das Präfix nicht außer Acht gelassen werden sollte.
Beispielsweise sollte für 'drive red car'
und 'drive red truck'
nur 'drive'
weggelassen werden, nicht 'drive red'
. Der geschützte Unicode-Bereich '\u00A0'
kann anstelle eines regulären Leerzeichens verwendet werden, um den Präfix-/Suffix-Matcher zu unterdrücken. Daher kann das obige Beispiel mit 'drive red\u00A0car'
und 'drive red\u00A0truck'
korrigiert werden.
Ein anderer Fall, bei dem der Präfix-/Suffixabgleich fehlschlägt, sind Sprachen, in denen einzelne Wörter nicht durch Leerzeichen getrennt werden. Chinesisch ist ein gutes Beispiel. Der String '訪問中國'
steht für 'visit China'
. Beachten Sie, dass zwischen den Wörtern keine Leerzeichen vorhanden sind.
Zusammen sind die letzten beiden Zeichen ('中國'
) das Wort für 'China'
. Bei Aufteilung bedeuten sie jedoch 'centre'
bzw. 'country'
. Damit der Abgleich von Präfixen und Suffixen in Sprachen wie Chinesisch funktioniert, fügen Sie an der Stelle, an der die Pause stehen soll, ein Leerzeichen ein. Beispielsweise würden '訪問 中國'
und '訪問 美國'
zu "visit [China/USA]"
führen, während '訪問 中 國'
und '訪問 美 國'
zu "visit [centre/beautiful] country"
führen.
Drop-down-Validator erstellen
Der Wert eines Drop-down-Felds ist ein sprachneutraler String. Daher müssen alle Validierungen einen String akzeptieren und einen String zurückgeben, der als Option verfügbar ist, null
oder undefined
.
Wenn Ihre Validierung etwas anderes zurückgibt, ist das Verhalten von Blockly nicht definiert und Ihr Programm kann abstürzen.
Sie könnten beispielsweise ein Drop-down-Feld mit drei Optionen und eine Validierung wie diese definieren:
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
gibt immer den übergebenen Wert zurück, ruft jedoch die Hilfsfunktion updateConnection
auf, die Eingaben basierend auf dem Drop-down-Wert hinzufügt oder entfernt:
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');
}
}