드롭다운 필드

드롭다운 필드는 문자열을 값으로 저장하고 문자열을 텍스트로 저장합니다. 이 값은 텍스트에 액세스하는 데 사용되는 언어 중립 키이며, Blockly가 언어 간에 전환될 때 번역되지 않습니다. 텍스트는 사람이 읽을 수 있는 문자열로, 사용자에게 표시됩니다.

제작

드롭다운 생성자는 메뉴 생성기와 선택적 validator를 사용합니다. 메뉴 생성기는 많은 유연성을 갖추고 있지만 기본적으로 옵션의 배열로, 각 옵션은 사람이 읽을 수 있는 부분과 언어 중립적 문자열을 포함합니다.

간단한 텍스트 드롭다운

두 개의 텍스트 옵션이 있는 드롭다운 열기

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 속성을 사용하여 드롭다운 화살표를 나타내는 유니코드 문자를 변경할 수 있습니다.

맞춤 화살표가 있는 드롭다운 필드

ARROW_CHAR 속성의 기본값은 Android에서는 \u25BC (▼)이고 그렇지 않은 경우 \u25BE (▾)입니다.

전역 속성이므로 설정하면 모든 드롭다운 필드가 수정됩니다.

Blockly.FieldDropdown.MAX_MENU_HEIGHT_VH 속성을 사용하여 메뉴의 최대 높이를 변경할 수 있습니다. 이는 표시 영역 높이의 백분율로 정의되며 표시 영역이 창으로 정의됩니다.

MAX_MENU_HEIGHT_VH 속성의 기본값은 0.45입니다.

전역 속성이므로 설정하면 모든 드롭다운 필드가 수정됩니다.

접두사/접미사 일치

모든 드롭다운 메뉴 옵션에서 공통 접두사 또는 접미사 단어를 공유하는 경우 이러한 단어는 자동으로 제외되어 정적 텍스트로 삽입됩니다. 예를 들어 다음과 같은 두 가지 방법으로 동일한 블록을 만들 수 있습니다 (첫 번째 방법은 접미사 일치를 사용하지 않고, 두 번째 방법은 접미사 일치 사용).

서픽스 일치 제외:

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'를 감지하여 드롭다운 다음에 표시합니다.

하지만 접두어/접미사 일치가 실패하는 경우도 있습니다. 두 단어가 항상 함께 있어야 하고 접두사를 제외해서는 안 되는 몇 가지 경우가 있습니다. 예를 들어 'drive red car''drive red truck''drive red'가 아닌 'drive'만 인수분해해야 합니다. 접두사/접미사 일치자를 억제하기 위해 정규 공백 대신 유니코드 비 줄바꿈 없는 공간 '\u00A0'를 사용할 수 있습니다. 따라서 위 예는 'drive red\u00A0car''drive red\u00A0truck'로 수정할 수 있습니다.

개별 단어를 공백으로 구분하지 않는 언어에서도 접두사/접미사 일치가 실패합니다. 중국어가 좋은 예입니다. '訪問中國' 문자열은 'visit China'를 의미합니다. 단어 사이에 공백이 없다는 점에 유의하세요. 전체적으로 마지막 두 문자 ('中國')는 'China'를 나타내는 단어이지만 분할할 경우 각각 'centre''country'를 의미합니다. 중국어와 같은 언어에서 접두사/접미사 일치가 작동하도록 하려면 줄바꿈이 필요한 곳에 공백을 삽입하면 됩니다. 예를 들어 '訪問 中國''訪問 美國'"visit [China/USA]"가 되고 '訪問 中 國''訪問 美 國'"visit [centre/beautiful] country"가 됩니다.

드롭다운 검사기 만들기

드롭다운 필드의 값은 언어 중립적인 문자열이므로 모든 검사기는 문자열을 수락하고 사용 가능한 옵션, null, undefined 문자열을 반환해야 합니다.

유효성 검사 도구에서 그 밖의 결과가 반환되면 Blockly의 동작이 정의되지 않으므로 프로그램이 다운될 수 있습니다.

예를 들어 다음과 같이 세 가지 옵션과 검사기가 있는 드롭다운 필드를 정의할 수 있습니다.

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