Kolom dropdown

Bidang {i>dropdown<i} menyimpan {i>string<i} sebagai nilainya dan {i>string<i} sebagai teksnya. Nilainya adalah kunci yang netral bahasa yang akan digunakan untuk mengakses teks dan tidak akan diterjemahkan saat Blockly dialihkan antarbahasa. Teks adalah string yang dapat dibaca manusia, yang akan ditampilkan kepada pengguna.

yang Dipicu oleh Tren

Konstruktor dropdown menggunakan generator menu dan validator opsional. Generator menu memiliki banyak fleksibilitas, tetapi pada dasarnya merupakan array opsi, setiap opsi berisi bagian yang dapat dibaca manusia, dan string bahasa netral.

Dropdown teks sederhana

Buka dropdown dengan dua opsi teks

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

Memisahkan informasi yang dapat dibaca manusia dari kunci netral bahasa memungkinkan setelan menu dropdown dipertahankan antar-bahasa. Misalnya, versi bahasa Inggris dari blok dapat menentukan [['left', 'LEFT'], ['right', 'RIGHT]], sedangkan versi bahasa Jerman dari blok yang sama akan menentukan [['links', 'LEFT'], ['rechts', 'RIGHT]].

Dropdown gambar

Opsi di menu dropdown juga dapat berupa gambar, bukan teks. Objek gambar ditentukan dengan properti src, width, height, dan alt.

Perhatikan bahwa meskipun dropdown dapat memiliki campuran opsi teks dan opsi gambar, setiap opsi saat ini tidak boleh berisi gambar dan teks secara bersamaan.

Kolom dropdown yang berisi gambar dan teks

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

Dropdown dinamis

Kolom dropdown dengan hari dalam seminggu

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

Hal ini dilakukan menggunakan ekstensi JSON.

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

Dropdown juga dapat disediakan dengan fungsi, bukan daftar opsi statis, yang memungkinkan opsi menjadi dinamis. Fungsi ini akan menampilkan array opsi dalam format [human-readable-value, language-neutral-key] yang sama dengan opsi statis. Setiap kali menu dropdown diklik, fungsi dijalankan dan opsi dihitung ulang.

Serialisasi

JSON

JSON untuk kolom dropdown terlihat seperti ini:

{
  "fields": {
    "FIELDNAME": "LANGUAGE-NEUTRAL-KEY"
  }
}

Dengan FIELDNAME adalah string yang merujuk ke kolom dropdown, dan nilainya adalah nilai yang akan diterapkan ke kolom tersebut. Nilainya harus berupa kunci opsi yang bebas bahasa.

XML

XML untuk kolom dropdown terlihat seperti ini:

<field name="FIELDNAME">LANGUAGE-NEUTRAL-KEY</field>

Dengan atribut name kolom berisi string yang merujuk ke kolom dropdown, dan teks bagian dalam adalah nilai yang akan diterapkan ke kolom tersebut. Teks bagian dalam harus berupa kunci opsi netral bahasa yang valid.

Penyesuaian

Properti Blockly.FieldDropdown.ARROW_CHAR dapat digunakan untuk mengubah karakter unicode yang merepresentasikan panah drop-down.

Kolom dropdown dengan panah kustom

Properti ARROW_CHAR ditetapkan secara default ke \u25BC (▼) di Android dan \u25BE (▾) jika tidak.

Ini adalah properti global, sehingga akan mengubah semua kolom dropdown jika ditetapkan.

Properti Blockly.FieldDropdown.MAX_MENU_HEIGHT_VH dapat digunakan untuk mengubah tinggi maksimum menu. Ini didefinisikan sebagai persentase tinggi area pandang, area pandang adalah jendela.

Properti MAX_MENU_HEIGHT_VH ditetapkan secara default ke 0,45.

Ini adalah properti global, sehingga akan mengubah semua kolom dropdown jika ditetapkan.

Pencocokan awalan/akhiran

Jika semua opsi menu dropdown memiliki kata awalan dan/atau akhiran yang sama, kata-kata tersebut akan otomatis dikecualikan dan disisipkan sebagai teks statis. Misalnya, berikut adalah dua cara untuk membuat blok yang sama (yang pertama tanpa pencocokan akhiran, dan yang kedua dengan):

Tanpa pencocokan akhiran:

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

Dengan pencocokan akhiran:

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

Bidang dropdown dengan

Salah satu keuntungan dari pendekatan ini adalah blok tersebut lebih mudah diterjemahkan ke bahasa lain. Kode sebelumnya memiliki string 'hello', 'world', dan 'computer', sedangkan kode yang direvisi memiliki string 'hello world' dan 'hello computer'. Penerjemah lebih mudah menerjemahkan frasa daripada kata secara terpisah.

Keuntungan lain dari pendekatan ini adalah urutan kata sering kali berubah antarbahasa. Bayangkan bahasa yang menggunakan 'world hello' dan 'computer hello'. Algoritme pencocokan akhiran akan mendeteksi 'hello' umum dan menampilkannya setelah drop-down.

Namun, terkadang pencocokan awalan/akhiran gagal. Ada beberapa kasus saat dua kata harus selalu terhubung dan awalan tidak boleh diabaikan. Misalnya, 'drive red car' dan 'drive red truck' seharusnya hanya mengabaikan 'drive', bukan 'drive red'. Spasi non-jeda Unicode '\u00A0' dapat digunakan sebagai pengganti ruang reguler untuk menyembunyikan pencocok awalan/akhiran. Dengan demikian, contoh di atas dapat diperbaiki dengan 'drive red\u00A0car' dan 'drive red\u00A0truck'.

Tempat lain di mana pencocokan awalan/akhiran gagal adalah dalam bahasa yang tidak memisahkan kata individual dengan spasi. Bahasa Mandarin adalah contoh yang bagus. String '訪問中國' berarti 'visit China', perhatikan tidak adanya spasi di antara kata. Secara kolektif, dua karakter terakhir ('中國') adalah kata untuk 'China', tetapi jika dibagi, keduanya akan berarti 'centre' dan 'country'. Untuk membuat pencocokan awalan/akhiran berfungsi dalam bahasa seperti bahasa China, cukup sisipkan spasi di tempat yang seharusnya menjadi jeda. Misalnya, '訪問 中國' dan '訪問 美國' akan menghasilkan "visit [China/USA]", sedangkan '訪問 中 國' dan '訪問 美 國' akan menghasilkan "visit [centre/beautiful] country".

Membuat validator dropdown

Nilai kolom drop-down adalah string yang tidak tergantung bahasa, sehingga setiap validator harus menerima string dan menampilkan string yang merupakan opsi yang tersedia, null, atau undefined.

Jika validator menampilkan hal lain, perilaku Blockly tidak ditentukan dan program Anda dapat error.

Misalnya, Anda dapat menentukan kolom drop-down dengan tiga opsi dan validator seperti ini:

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 selalu menampilkan nilai yang diteruskan, tetapi memanggil fungsi helper updateConnection yang menambahkan atau menghapus input berdasarkan nilai dropdown:

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