Kolom dropdown

Kolom dropdown menyimpan string sebagai nilai dan string sebagai teksnya. Tujuan adalah kunci tanpa bahasa yang akan digunakan untuk mengakses teks dan tidak akan diterjemahkan saat Blockly dialihkan antarbahasa. Teksnya adalah string yang dapat dibaca manusia dan akan ditampilkan kepada pengguna.

yang Dipicu oleh Tren

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

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 tombol netral bahasa memungkinkan setelan menu dropdown dipertahankan di antara bahasa. Sebagai instance versi bahasa Inggris dari sebuah blok dapat menentukan [['left', 'LEFT'], ['right', 'RIGHT]] sedangkan versi 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 {i>dropdown<i} dapat memiliki campuran opsi teks dan opsi gambar, masing-masing opsi saat ini tidak dapat berisi gambar dan teks.

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

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 dengan menggunakan JSON ekstensi Anda.

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 statis yang memungkinkan opsi menjadi dinamis. Fungsi ini harus mengembalikan array opsi dalam [human-readable-value, language-neutral-key] yang sama format sebagai opsi statis. Setiap kali {i>dropdown<i} diklik, fungsi akan dijalankan dan opsinya dihitung ulang.

Serialisasi

JSON

JSON untuk kolom dropdown akan terlihat seperti ini:

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

Dengan FIELDNAME adalah string yang merujuk ke kolom dropdown, dan nilai adalah nilai yang akan diterapkan ke {i>field<i}. Nilainya harus berupa tombol opsi netral bahasa.

XML

XML untuk kolom dropdown terlihat seperti ini:

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

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

Penyesuaian

Properti Blockly.FieldDropdown.ARROW_CHAR dapat digunakan untuk mengubah karakter unicode yang mewakili panah {i>dropdown<i}.

Kolom dropdown dengan panah kustom

Secara default, properti ARROW_CHAR ditetapkan ke \u25BC (▼) di Android dan \u25BE (▾) sebaliknya.

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

Properti Blockly.FieldDropdown.MAX_MENU_HEIGHT_VH dapat digunakan untuk mengubah tinggi maksimum menu. Ini didefinisikan sebagai persentase area pandang {i>high<i}, area pandang adalah jendela.

Secara default, properti MAX_MENU_HEIGHT_VH ditetapkan ke 0,45.

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

Pencocokan awalan/akhiran

Jika semua opsi menu dropdown memiliki awalan dan/atau akhiran yang sama kata, kata-kata ini secara otomatis dikecualikan dan dimasukkan sebagai teks statis. Misalnya, berikut adalah dua cara untuk membuat blok yang sama (ini 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 bahwa blok tersebut lebih mudah untuk diterjemahkan ke dalam bahasa lain. Kode sebelumnya memiliki string 'hello', 'world', dan 'computer', sedangkan kode yang direvisi memiliki string 'hello world' dan 'hello computer'. Penerjemah memiliki waktu yang jauh lebih mudah untuk menerjemahkan frasa daripada kata secara terpisah.

Keuntungan lain dari pendekatan ini adalah bahwa urutan kata sering berubah antara bahasa. Bayangkan bahasa yang menggunakan 'world hello' dan 'computer hello'. Algoritma pencocokan akhiran akan mendeteksi 'hello' umum dan menampilkannya setelah menu {i>drop-down<i}.

Namun, terkadang pencocokan awalan/akhiran gagal. Ada beberapa kasus di mana dua kata harus selalu saling melengkapi dan awalannya tidak boleh dikesampingkan. Misalnya, 'drive red car' dan 'drive red truck' seharusnya hanya telah mengecualikan 'drive', bukan 'drive red'. Unicode yang tidak menyebabkan gangguan ruang '\u00A0' dapat digunakan sebagai pengganti ruang reguler untuk menekan 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 setiap kata dengan spasi. China adalah contoh yang baik. {i>String<i} '訪問中國' berarti 'visit China'. Perhatikan bahwa tidak ada spasi di antara kata. Secara kolektif, dua karakter terakhir ('中國') adalah kata untuk 'China', tetapi jika dipisah, berarti 'centre' dan 'country' masing-masing. Untuk membuat pencocokan awalan/akhiran dalam bahasa seperti bahasa China, cukup sisipkan spasi di mana istirahat seharusnya berada. Misalnya, '訪問 中國' dan '訪問 美國' akan menghasilkan "visit [China/USA]", sedangkan '訪問 中 國' dan '訪問 美 國' akan menghasilkan "visit [centre/beautiful] country".

Membuat validator dropdown

Nilai kolom dropdown adalah string tanpa bahasa, jadi 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 bisa macet.

Misalnya, Anda dapat mendefinisikan {i>field <i}dari {i>dropdown <i}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 helper fungsi updateConnection yang menambah atau menghapus input berdasarkan dropdown nilai:

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