Açılır liste alanı, değer olarak bir dize, metin olarak da bir dize depolar. Değer, metne erişmek için kullanılacak ve Blockly diller arasında değiştirildiğinde çevrilmeyecek dilden bağımsız bir anahtardır. Metin, kullanıcıya gösterilecek, okunabilir bir dizedir.
Açılır liste alanı
Düzenleyici açıkken açılır liste alanı
Daraltılmış bloktaki açılır liste alanı
içerik üretimi
Açılır liste oluşturucu, bir menü oluşturucu ve isteğe bağlı bir doğrulayıcı alır. Menü oluşturucu, bir seçenek dizisi (her seçenekte kullanıcılar tarafından okunabilir bir bölüm ve dil açısından tarafsız bir dize bulunur) veya bir seçenek dizisi oluşturan bir işlevdir. Her seçeneğin okunabilir kısmı dize, resim veya HTML öğesi olabilir. Dizi, farklı türlerdeki seçeneklerin bir karışımını içerebilir.
Basit metin açılır listeleri
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');
}
};
İnsan tarafından okunabilir bilgilerin dilden bağımsız anahtardan ayrı tutulması, açılır menü ayarının diller arasında korunmasını sağlar. Örneğin, bir bloğun İngilizce sürümü [['left', 'LEFT'], ['right',
'RIGHT]]
değerini tanımlarken aynı bloğun Almanca sürümü [['links',
'LEFT'], ['rechts', 'RIGHT]]
değerini tanımlar.
Resim açılır listeleri
Açılır menüdeki seçenekler, src
, width
, height
ve alt
özelliklerine sahip nesneler olarak gösterilen resimler olabilir.
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');
}
};
HTML açılır listeleri
Seçenek, çok büyük olmadığı ve fare veya klavye etkinliklerini işlemeye çalışmadığı sürece herhangi bir HTML öğesi olabilir. (Bu kurallara uymak sizin sorumluluğunuzdadır. Blockly bu kuralları zorunlu kılmaz.)
Açılır liste açıkken listede HTML öğesi gösterilir. Kapatıldığında ve öğe seçili seçenek olduğunda liste, öğenin title
özelliğini, aria-label
özelliğini veya innerText
özelliğini (tercih sırasına göre azalan düzende) gösterir.
JSON
{
"type": "flags_with_text_dropdown",
"message0": "flag with text %1",
"args0": [
{
"type": "field_dropdown",
"name": "FLAG_WITH_TEXT",
"options": [
["x", "X"], // Placeholder. An empty array throws an exception.
]
}
],
// Use an extension to add the HTML element options.
"extensions": ["flag_with_text_extension"]
}
Blockly.Extensions.register('flag_with_text_extension',
function() {
function createFlagWithTextDiv(text, src) {
const div = document.createElement('div');
div.setAttribute('style', 'width: 75px;');
div.setAttribute('title', text);
const img = document.createElement('img');
img.setAttribute('src', src);
img.setAttribute('style', 'height: 25px; display: block; margin: auto;');
div.appendChild(img);
const para = document.createElement('p');
para.innerText = text;
para.setAttribute('style', 'text-align: center; margin: 5px;');
div.appendChild(para);
return div;
}
const canadaDiv = createFlagWithTextDiv('Canada', 'canada.png');
const usaDiv = createFlagWithTextDiv('USA', 'usa.png');
const mexicoDiv = createFlagWithTextDiv('Mexico', 'mexico.png');
const options = [
['none', 'NONE'],
[canadaDiv, 'CANADA'],
[usaDiv, 'USA'],
[mexicoDiv, 'MEXICO']
];
this.getField('FLAG_WITH_TEXT').setOptions(options);
});
Bu işlem, JSON uzantısı kullanılarak yapılır.
JavaScript
function createFlagWithTextDiv(text, src) {
const div = document.createElement('div');
div.setAttribute('style', 'width: 75px;');
div.setAttribute('title', text);
const img = document.createElement('img');
img.setAttribute('src', src);
img.setAttribute('style', 'height: 25px; display: block; margin: auto;');
div.appendChild(img);
const para = document.createElement('p');
para.innerText = text;
para.setAttribute('style', 'text-align: center; margin: 5px;');
div.appendChild(para);
return div;
}
const canadaDiv = createFlagWithTextDiv('Canada', 'canada.png');
const usaDiv = createFlagWithTextDiv('USA', 'usa.png');
const mexicoDiv = createFlagWithTextDiv('Mexico', 'mexico.png');
Blockly.Blocks['flags_with_text_dropdown'] = {
init: function() {
const input = this.appendDummyInput()
.appendField('flag with text');
const options = [
['none', 'NONE'],
[canadaDiv, 'CANADA'],
[usaDiv, 'USA'],
[mexicoDiv, 'MEXICO']
];
input.appendField(new Blockly.FieldDropdown(options), 'FLAG_WITH_TEXT');
}
};
Dinamik açılır listeler
JSON
{
"type": "dynamic_dropdown",
"message0": "day %1",
"args0": [
{
"type": "field_dropdown",
"name": "DAY",
"options": [
["x", "X"], // Placeholder. An empty array throws an exception.
]
}
],
// Use an extension to set the menu function.
"extensions": ["dynamic_menu_extension"]
}
Blockly.Extensions.register('dynamic_menu_extension',
function() {
this.getField('DAY').setOptions(
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;
});
});
Bu işlem, JSON uzantısı kullanılarak yapılır.
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;
}
};
Açılır liste, statik seçenekler listesi yerine bir işlevle de sağlanabilir. Bu sayede seçenekler dinamik olabilir. İşlev, statik seçeneklerle aynı [human-readable-value, language-neutral-key]
biçiminde bir seçenek dizisi döndürmelidir. Açılır liste her tıklandığında işlev çalıştırılır ve seçenekler yeniden hesaplanır.
Ayırıcılar
Açılır menüdeki seçenekler arasına çizgi eklemek için 'separator'
dizesini kullanın.
JSON
{
"type": "separator_dropdown",
"message0": "food %1",
"args0": [
{
"type": "field_dropdown",
"name": "FOOD",
"options": [
["water", "WATER"],
["juice", "JUICE"],
"separator",
["salad", "SALAD"],
["soup", "SOUP"],
]
}
]
}
JavaScript
Blockly.Blocks["separator_dropdown"] = {
init: function() {
var input = this.appendDummyInput()
.appendField("food1");
var options = [
["water", "WATER"],
["juice", "JUICE"],
"separator",
["salad", "SALAD"],
["soup", "SOUP"],
];
input.appendField(new Blockly.FieldDropdown(options), "FOOD");
}
};
Serileştirme
JSON
Açılır liste alanının JSON'u şu şekilde görünür:
{
"fields": {
"FIELDNAME": "LANGUAGE-NEUTRAL-KEY"
}
}
Burada FIELDNAME
, bir açılır liste alanına referans veren bir dizedir ve değer, alana uygulanacak değerdir. Değer, dilden bağımsız bir seçenek anahtarı olmalıdır.
XML
Açılır liste alanının XML'si şu şekilde görünür:
<field name="FIELDNAME">LANGUAGE-NEUTRAL-KEY</field>
Alanının name
özelliği, bir açılır liste alanına referans veren bir dize içerdiğinde ve iç metin, alana uygulanacak değer olduğunda. İç metin, geçerli bir dilden bağımsız seçenek anahtarı olmalıdır.
Özelleştirme
Açılır ok
Blockly.FieldDropdown.ARROW_CHAR
özelliği, açılır liste okunu temsil eden Unicode karakterini değiştirmek için kullanılabilir.
ARROW_CHAR
özelliği, Android'de varsayılan olarak \u25BC
(▼), diğer durumlarda ise \u25BE
(▾) olur.
Bu global bir özelliktir. Dolayısıyla ayarlandığında tüm açılır liste alanlarını değiştirir.
Menü yüksekliği
Blockly.FieldDropdown.MAX_MENU_HEIGHT_VH
özelliği, menünün maksimum yüksekliğini değiştirmek için kullanılabilir. Görüntü alanı yüksekliğinin yüzdesi olarak tanımlanır. Görüntü alanı, penceredir.
MAX_MENU_HEIGHT_VH
özelliği varsayılan olarak 0,45'tir.
Bu global bir özelliktir. Dolayısıyla ayarlandığında tüm açılır liste alanlarını değiştirir.
Önek/sonek eşleşmesi
Açılır menüdeki tüm seçenekler ortak bir önek ve/veya sonek kelimeler içeriyorsa bu kelimeler otomatik olarak çıkarılır ve statik metin olarak eklenir. Örneğin, aynı bloğu oluşturmanın iki yolu vardır (birincisi sonek eşleştirme olmadan, ikincisi ise sonek eşleştirme ile):
Sonek eşleme olmadan:
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');
}
};
Sonek eşleme ile:
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');
}
};
Bu yaklaşımın bir avantajı, bloğun diğer dillere daha kolay çevrilmesidir. Önceki kodda 'hello'
, 'world'
ve 'computer'
dizeleri, düzeltilmiş kodda ise 'hello world'
ve 'hello computer'
dizeleri yer alıyor. Çevirmenler, kelimeleri tek tek çevirmektense cümleleri çevirirken çok daha az zorlanır.
Bu yaklaşımın bir diğer avantajı, kelime sırasının diller arasında genellikle değişmesidir. 'world hello'
ve 'computer hello'
sembollerinin kullanıldığı bir dil düşünün.
Sonek eşleştirme algoritması, ortak 'hello'
öğesini algılar ve açılır listeden sonra görüntüler.
Ancak bazen önek/sonek eşleştirme başarısız olur. İki kelimenin her zaman birlikte kullanılması gereken ve önekin çıkarılmaması gereken bazı durumlar vardır.
Örneğin, 'drive red car'
ve 'drive red truck'
değerlerinde 'drive red'
değil, yalnızca 'drive'
değerinin çıkarılması gerekir. Önek/sonek eşleştiricisini devre dışı bırakmak için normal boşluk yerine Unicode kesintisiz boşluk '\u00A0'
kullanılabilir. Bu nedenle, yukarıdaki örnek 'drive red\u00A0car'
ve 'drive red\u00A0truck'
ile düzeltilebilir.
Önek/sonek eşlemenin başarısız olduğu bir diğer yer ise kelimeleri boşluklarla ayırmayan dillerdir. Çince buna iyi bir örnektir. '訪問中國'
dizesi 'visit China'
anlamına gelir. Kelimeler arasında boşluk olmadığına dikkat edin.
Son iki karakter ('中國'
) birlikte 'China'
kelimesini ifade eder.
Ancak bu karakterler ayrıldığında sırasıyla 'centre'
ve 'country'
anlamına gelir. Çince gibi dillerde önek/sonek eşleştirmenin çalışması için ayrımın olması gereken yere boşluk eklemeniz yeterlidir. Örneğin, '訪問 中國'
ve '訪問 美國'
, "visit [China/USA]"
ile sonuçlanırken '訪問 中 國'
ve '訪問 美 國'
, "visit [centre/beautiful] country"
ile sonuçlanır.
Açılır liste doğrulayıcısı oluşturma
Açılır liste alanının değeri, dilden bağımsız bir dizedir. Bu nedenle, tüm doğrulayıcılar bir dizeyi kabul etmeli ve kullanılabilir bir seçenek olan, null
veya undefined
dizelerini döndürmelidir.
Doğrulayıcınız başka bir şey döndürürse Blockly'nin davranışı tanımlanmamış olur ve programınız kilitlenebilir.
Örneğin, üç seçenekli bir açılır liste alanı ve doğrulayıcıyı şu şekilde tanımlayabilirsiniz:
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
her zaman kendisine iletilen değeri döndürür ancak açılır liste değerine göre giriş ekleyen veya kaldıran yardımcı işlevi updateConnection
'ni çağırır:
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');
}
}