Açılır alanlar

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:" etiketli bir blok, "ilk" seçeneğinin belirlendiği bir açılır liste alanı ve "öğe" etiketi.

Açılır liste açıkken aynı blok. Açılır listede "first" (birinci) ve "second" (ikinci) öğeleri yer alıyor.

Aynı blok daraltıldıktan sonra. "Açılır liste: ilk öğe" etiketine sahiptir ve daraltıldığını göstermek için sağ kenarı tırtıklıdır.

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

İki metin seçeneği içeren açılır listeyi açın.

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.

Resim ve metin içeren açılır liste alanı

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.

Metin ve HTML öğeleri içeren açılır liste alanı

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

Haftanın günlerini içeren açılır liste alanı

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.

İkinci ve üçüncü seçenekler arasında çizgi bulunan açılır liste alanı

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

Blockly.FieldDropdown.ARROW_CHAR özelliği, açılır liste okunu temsil eden Unicode karakterini değiştirmek için kullanılabilir.

Özel ok içeren açılır liste alanı

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.

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');
  }
};

Şu öğeleri içeren açılır liste alanı:

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');
  }
}

&quot;Hiçbiri&quot;, &quot;ifade&quot; ve &quot;değer&quot; olmak üzere üç öğe içeren bir açılır liste alanını gösteren animasyonlu GIF. &quot;Hiçbiri&quot; seçildiğinde giriş olmaz. &quot;İfade&quot; seçildiğinde ifade girişi olur. &quot;Değer&quot; bağlandığında &quot;değer&quot; girişi olur.