Campos desplegables

El campo desplegable almacena una cadena como su valor y una cadena como su texto. El es una clave neutral en cuanto al idioma que se usará para acceder al texto y no se traducirán cuando Blockly cambie de idioma. El texto es una cadena legible que se le mostrará al usuario.

Creación

El constructor de menú desplegable toma un generador de menús y un validador. El generador de menú tiene muchas flexibilidad, pero, en esencia, es un array de opciones, en el que cada opción contiene un legible por humanos y una cadena neutral en el lenguaje.

Menús desplegables de texto simples

Abrir menú desplegable con dos opciones de texto

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

Mantener la información legible por humanos separada de la clave neutra de lenguaje permite conservar la configuración del menú desplegable en los distintos idiomas. Para Por ejemplo, la versión en inglés de un bloque podría definir [['left', 'LEFT'], ['right', 'RIGHT]] y una versión alemana del mismo bloque definiría [['links', 'LEFT'], ['rechts', 'RIGHT]].

Menús desplegables de imágenes

Las opciones de un menú desplegable también pueden ser imágenes en lugar de texto. Los objetos de imagen son Se especifica con las propiedades src, width, height y alt.

Ten en cuenta que, aunque un menú desplegable puede tener una combinación de opciones de texto y de imágenes, En este momento, una opción individual no puede contener una imagen y texto.

Campo desplegable que contiene imágenes y texto

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

Menús desplegables dinámicos

Campo desplegable con los días de la semana

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

Esto se hace usando un archivo JSON extensión.

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

También se puede proporcionar un menú desplegable con una función en lugar de una lista de elementos opciones, lo que permite que las opciones sean dinámicas. La función debería mostrar un array de opciones en el mismo [human-readable-value, language-neutral-key] como opciones estáticas. Cada vez que se hace clic en el menú desplegable, se activa la función se ejecutan y se vuelven a calcular las opciones.

Serialización

JSON

El JSON para un campo desplegable se ve así:

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

Donde FIELDNAME es una cadena que hace referencia a un campo de menú desplegable. el valor es el valor que se aplicará al campo. El valor debe ser una tecla de opción independiente del idioma.

XML

El XML para un campo desplegable se ve así:

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

En el que el atributo name del campo contiene una cadena que hace referencia a un menú desplegable y el texto interno es el valor que se aplicará al campo. El interior el texto debe ser una clave de opción válida sin lenguaje.

Personalización

La propiedad Blockly.FieldDropdown.ARROW_CHAR se puede usar para cambiar la carácter Unicode que representa la flecha desplegable.

Campo desplegable con flecha personalizada

La propiedad ARROW_CHAR se establece de forma predeterminada en \u25BC (▼) en Android y \u25BE (▾) de lo contrario.

Esta es una propiedad global, por lo que modificará todos los campos del menú desplegable cuando se establezca.

Se puede usar la propiedad Blockly.FieldDropdown.MAX_MENU_HEIGHT_VH para cambiar la altura máxima del menú. Se define como un porcentaje del viewport altura, el viewport es la ventana.

El valor predeterminado de la propiedad MAX_MENU_HEIGHT_VH es 0.45.

Esta es una propiedad global, por lo que modificará todos los campos del menú desplegable cuando se establezca.

Coincidencia de prefijos y sufijos

Si todas las opciones del menú desplegable comparten un prefijo o sufijo en común palabras, estas se excluyen automáticamente y se insertan como texto estático. Por ejemplo, aquí hay dos formas de crear el mismo bloque (esta primero sin coincidencia de sufijo y la segunda con):

Sin coincidencia de sufijo:

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

Con coincidencia de sufijo:

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

Campo desplegable con

Una ventaja de este enfoque es que el bloque es más fácil de traducir otros idiomas. El código anterior tiene las cadenas 'hello', 'world' y 'computer', mientras que el código revisado tiene las cadenas 'hello world' y 'hello computer' A los traductores les resulta mucho más fácil traducir frases palabras aisladas.

Otra ventaja de este enfoque es que el orden de las palabras a menudo cambia entre idiomas. Imagina un lenguaje que usara 'world hello' y 'computer hello'. El algoritmo de coincidencia de sufijos detectará el 'hello' común y lo mostrará después del menú desplegable.

Sin embargo, a veces la coincidencia del prefijo o sufijo falla. En algunos casos, dos palabras siempre deben ir juntas y el prefijo no debe excluirse. Por ejemplo, podría decirse que 'drive red car' y 'drive red truck' solo deberían ser se incluyen 'drive', no 'drive red'. El concepto de no separación de Unicode Se puede usar el espacio '\u00A0' en lugar de un espacio regular para suprimir la comparador de prefijos y sufijos. Por lo tanto, el ejemplo anterior se puede corregir con 'drive red\u00A0car' y 'drive red\u00A0truck'.

Otro lugar en el que la coincidencia de prefijo o sufijo falla es en idiomas que no separar palabras individuales con espacios. El chino es un buen ejemplo. La cadena '訪問中國' significa 'visit China'. Ten en cuenta la falta de espacios entre las palabras. En conjunto, los dos últimos caracteres ('中國') son la palabra para 'China', pero, si se divide, significarían 'centre' y 'country', respectivamente. Para hacer la coincidencia de prefijo y sufijo funciona en idiomas como el chino, solo inserte un espacio donde debería estar la pausa. Por ejemplo, '訪問 中國' y '訪問 美國' daría como resultado "visit [China/USA]", mientras que '訪問 中 國' y '訪問 美 國' daría como resultado "visit [centre/beautiful] country".

Crea un validador de menú desplegable

El valor de un campo desplegable es una cadena neutral en cuanto al lenguaje, por lo que los validadores deben aceptar una cadena y mostrar una cadena que sea una opción disponible, null, o undefined

Si el validador devuelve algo más, el comportamiento de Blockly no está definido y tu programa puede fallar.

Por ejemplo, podrías definir un campo desplegable con tres opciones y una validador de la siguiente manera:

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 siempre muestra el valor que se pasó, pero llama al asistente. función updateConnection, que agrega o quita entradas en función del menú desplegable valor:

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