ช่องรายการแบบเลื่อนลง

ช่องเมนูแบบเลื่อนลงจะเก็บสตริงเป็นค่า และสตริงเป็นข้อความ ค่าจะเป็นคีย์ภาษากลางที่จะใช้ในการเข้าถึงข้อความและจะไม่ได้รับการแปลเมื่อ Blockly สลับไปมาระหว่างภาษาต่างๆ ข้อความนี้เป็นสตริงที่มนุษย์อ่านได้ ซึ่งจะแสดงต่อผู้ใช้

การสร้างวิดีโอ

ตัวสร้างเมนูแบบเลื่อนลงจะใช้โปรแกรมสร้างเมนูและvalidatorซึ่งไม่บังคับ เครื่องมือสร้างเมนูมีความยืดหยุ่นมาก แต่โดยพื้นฐานแล้วเป็นอาร์เรย์ของตัวเลือก แต่ละตัวเลือกมีส่วนที่มนุษย์อ่านได้ และสตริงที่เป็นกลาง

เมนูแบบเลื่อนลงที่เป็นข้อความธรรมดา

เปิดเมนูแบบเลื่อนลงที่มีข้อความ 2 ตัวเลือก

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

การแยกข้อมูลที่มนุษย์อ่านได้แยกจากคีย์กลางของภาษาจะทำให้มีการเก็บรักษาการตั้งค่าของเมนูแบบเลื่อนลงไว้ระหว่างภาษาต่างๆ สำหรับอินสแตนซ์ การบล็อกเวอร์ชันภาษาอังกฤษอาจกำหนด [['left', 'LEFT'], ['right', 'RIGHT]] ในขณะที่เวอร์ชันภาษาเยอรมันของบล็อกเดียวกันจะกำหนด [['links', 'LEFT'], ['rechts', 'RIGHT]]

รายการรูปภาพแบบเลื่อนลง

ตัวเลือกในเมนูแบบเลื่อนลงอาจเป็นรูปภาพ ไม่ใช่ข้อความ มีการระบุออบเจ็กต์รูปภาพด้วยพร็อพเพอร์ตี้ src, width, height และ alt

โปรดทราบว่าแม้เมนูแบบเลื่อนลงจะมีตัวเลือกข้อความและตัวเลือกรูปภาพผสมกันได้ แต่ตัวเลือกแต่ละรายการไม่สามารถมีทั้งรูปภาพและข้อความได้ในขณะนี้

ช่องแบบเลื่อนลงที่มีรูปภาพและข้อความ

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

เมนูแบบเลื่อนลงแบบไดนามิก

ช่องเมนูแบบเลื่อนลงที่มีวันของสัปดาห์

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

โดยใช้ส่วนขยาย 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;
  }
};

นอกจากนี้ เมนูแบบเลื่อนลงยังอาจมีฟังก์ชันแทนรายการตัวเลือกแบบคงที่ ซึ่งช่วยให้ตัวเลือกเป็นแบบไดนามิกได้ ฟังก์ชันควรแสดงผลอาร์เรย์ของตัวเลือกในรูปแบบ [human-readable-value, language-neutral-key] เดียวกันกับตัวเลือกแบบคงที่ ทุกครั้งที่มีการคลิกเมนูแบบเลื่อนลง ฟังก์ชันจะทํางานและจะมีการคำนวณตัวเลือกใหม่

การทำให้เป็นอนุกรม

JSON

JSON สำหรับช่องแบบเลื่อนลงจะมีลักษณะดังนี้

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

โดย FIELDNAME คือสตริงที่อ้างอิงช่องแบบเลื่อนลง และค่าคือค่าที่จะนำไปใช้กับช่องนั้น ค่าควรเป็นคีย์ตัวเลือกที่เป็นกลาง

XML

XML สำหรับฟิลด์แบบเลื่อนลงจะมีลักษณะดังนี้

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

ที่แอตทริบิวต์ name ของช่องมีสตริงที่อ้างอิงช่องแบบเลื่อนลง และข้อความภายในคือค่าที่จะนำไปใช้กับช่องนี้ ข้อความด้านในควรเป็นคีย์ตัวเลือกที่ถูกต้องซึ่งเป็นภาษากลาง

การปรับแต่งช่อง

คุณใช้พร็อพเพอร์ตี้ Blockly.FieldDropdown.ARROW_CHAR เพื่อเปลี่ยนอักขระ Unicode ที่แสดงลูกศรแบบเลื่อนลงได้

ช่องรายการแบบเลื่อนลงที่มีลูกศรที่กำหนดเอง

คุณสมบัติ ARROW_CHAR จะมีค่าเริ่มต้นเป็น \u25BC (▼) ใน Android และ \u25BE (▾)

พร็อพเพอร์ตี้นี้เป็นพร็อพเพอร์ตี้ส่วนกลาง ดังนั้นจึงจะแก้ไขช่องแบบเลื่อนลงทั้งหมดเมื่อตั้งค่า

คุณใช้พร็อพเพอร์ตี้ Blockly.FieldDropdown.MAX_MENU_HEIGHT_VH เพื่อเปลี่ยนความสูงสูงสุดของเมนูได้ โดยการกำหนดเป็นเปอร์เซ็นต์ของความสูงของวิวพอร์ต วิวพอร์ตคือหน้าต่าง

พร็อพเพอร์ตี้ MAX_MENU_HEIGHT_VH จะมีค่าเริ่มต้นเป็น 0.45

พร็อพเพอร์ตี้นี้เป็นพร็อพเพอร์ตี้ส่วนกลาง ดังนั้นจึงจะแก้ไขช่องแบบเลื่อนลงทั้งหมดเมื่อตั้งค่า

การจับคู่คำนำหน้า/คำต่อท้าย

หากตัวเลือกในเมนูแบบเลื่อนลงทั้งหมดใช้คำนำหน้าและ/หรือคำต่อท้ายที่ใช้ร่วมกันร่วมกัน ระบบจะแยกคำเหล่านี้ออกมาและแทรกเป็นข้อความแบบคงที่โดยอัตโนมัติ ตัวอย่างเช่น มี 2 วิธีในการสร้างบล็อกเดียวกัน (วิธีแรกโดยไม่ต้องจับคู่คำต่อท้าย และวิธีที่สองมี)

ที่ไม่มีการจับคู่คำต่อท้าย:

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

เมื่อมีการจับคู่คำต่อท้าย:

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

ช่องรายการแบบเลื่อนลงที่มี

ข้อดีอย่างหนึ่งของวิธีนี้คือทำให้บล็อกแปลเป็นภาษาอื่นๆ ได้ง่ายกว่า โค้ดก่อนหน้ามีสตริง 'hello', 'world' และ 'computer' ส่วนโค้ดที่แก้ไขจะมีสตริง 'hello world' และ 'hello computer' นักแปลใช้เวลาแปลข้อความได้ง่ายกว่า การแปลทีละคำ

ข้อดีอีกอย่างหนึ่งของวิธีนี้คือลำดับคำมักมีการเปลี่ยนแปลงระหว่างภาษาต่างๆ ลองนึกถึงภาษาที่ใช้ 'world hello' และ 'computer hello' อัลกอริทึมจับคู่ส่วนต่อท้ายจะตรวจหา 'hello' ทั่วไปและแสดงไว้หลังเมนูแบบเลื่อนลง

แต่บางครั้งการจับคู่คำนำหน้า/คำต่อท้ายก็ไม่สำเร็จ ในบางกรณีที่คำ 2 คำควรอยู่ด้วยกันเสมอ และไม่ควรนำคำขึ้นต้นออก ตัวอย่างเช่น 'drive red car' และ 'drive red truck' ควรมีเพียง 'drive' เท่านั้นที่มีการแยกตัวประกอบ ไม่ใช่ 'drive red' คุณอาจใช้ช่องว่าง '\u00A0' แบบไม่ตัดคำของ Unicode แทนการเว้นวรรคปกติเพื่อระงับตัวจับคู่คำนำหน้า/คำต่อท้าย ดังนั้นตัวอย่างด้านบนจึงแก้ไขได้ด้วย 'drive red\u00A0car' และ 'drive red\u00A0truck'

อีกจุดหนึ่งที่การจับคู่คำนำหน้า/คำต่อท้ายล้มเหลวคือการใช้ภาษาที่ไม่ได้คั่นแต่ละคำด้วยการเว้นวรรค ตัวอย่างที่ดีภาษาจีนคือ สตริง '訪問中國' หมายถึง 'visit China' โปรดสังเกตว่าไม่มีการเว้นวรรคระหว่างคำ อักขระ 2 ตัวสุดท้าย ('中國') คือคำสำหรับ 'China' แต่หากแบ่งก็จะหมายถึง 'centre' และ 'country' ตามลำดับ หากต้องการให้การจับคู่คำนำหน้า/คำต่อท้ายใช้ได้ในภาษาต่างๆ เช่น ภาษาจีน เพียงแทรกเว้นวรรคคั่นระหว่างคำ เช่น '訪問 中國' และ '訪問 美國' จะกลายเป็น "visit [China/USA]" ในขณะที่ '訪問 中 國' และ '訪問 美 國' จะกลายเป็น "visit [centre/beautiful] country"

การสร้างโปรแกรมตรวจสอบเมนูแบบเลื่อนลง

ค่าของช่องแบบเลื่อนลงเป็นสตริงที่เป็นภาษากลาง โปรแกรมตรวจสอบจึงต้องยอมรับสตริงและแสดงผลสตริงซึ่งเป็นตัวเลือกที่ใช้ได้, null หรือ undefined

หากโปรแกรมตรวจสอบแสดงผลสิ่งอื่นๆ กลับ ลักษณะการทำงานของ Blockly จะไม่ได้กำหนด และ โปรแกรมของคุณอาจขัดข้อง

ตัวอย่างเช่น คุณอาจกำหนดช่องแบบเลื่อนลงที่มี 3 ตัวเลือก และโปรแกรมตรวจสอบดังนี้

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 จะแสดงผลค่าที่ส่งผ่านไปแล้วเสมอ แต่ระบบจะเรียกฟังก์ชันตัวช่วย updateConnection ซึ่งจะเพิ่มหรือนำอินพุตออกตามค่าแบบเลื่อนลงต่อไปนี้

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