Campi del menu a discesa

Il campo a discesa memorizza una stringa come valore e una stringa come testo. La è una chiave indipendente dalla lingua che verrà utilizzata per accedere al testo e non verranno tradotti quando Blockly viene cambiato da una lingua all'altra. Il testo è una stringa leggibile che verrà mostrata all'utente.

Creazione

Il costruttore del menu a discesa include un generatore di menu e un'opzione facoltativa strumento di convalida. Il generatore di menu offre molti flessibilità, ma si tratta essenzialmente di una serie di opzioni, ciascuna delle quali contiene una parte leggibile e una stringa indipendente dal linguaggio.

Menu a discesa di testo semplici

Apri il menu a discesa con due opzioni di testo

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

Mantenere le informazioni leggibili separatamente dalla chiave indipendente dalla lingua. consente di mantenere l'impostazione del menu a discesa tra le lingue. Per Ad esempio, una versione inglese di un blocco può definire [['left', 'LEFT'], ['right', 'RIGHT]], mentre una versione tedesca dello stesso blocco può definire [['links', 'LEFT'], ['rechts', 'RIGHT]].

Menu a discesa di immagini

Le opzioni di un menu a discesa possono anche essere immagini anziché testo. Gli oggetti immagine vengono specificato con le proprietà src, width, height e alt.

Tieni presente che, sebbene un menu a discesa possa contenere una combinazione di opzioni di testo e immagini, una singola opzione al momento non può contenere sia un'immagine che un testo.

Campo a discesa contenente immagini e testo

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

Menu a discesa dinamici

Campo a discesa con i giorni della settimana

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

Questo viene fatto usando un file 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;
  }
};

È anche possibile fornire un menu a discesa con una funzione anziché un elenco di opzioni dinamiche, in modo che le opzioni siano dinamiche. La funzione deve restituire un array di opzioni nello stesso [human-readable-value, language-neutral-key] come opzioni statiche. Ogni volta che l'utente fa clic sul menu a discesa, la funzione viene e le opzioni vengono ricalcolate.

Serializzazione

JSON

Il codice JSON di un campo a discesa è simile al seguente:

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

dove FIELDNAME è una stringa che fa riferimento a un campo a discesa e il valore è il valore da applicare al campo. Il valore deve essere un tasto di opzione indipendente dalla lingua.

XML

L'XML per un campo a discesa ha il seguente aspetto:

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

In cui l'attributo name del campo contiene una stringa che fa riferimento a un menu a discesa e il testo interno è il valore da applicare al campo. La parte interna deve essere una chiave di opzione valida e indipendente dalla lingua.

Personalizzazione

La proprietà Blockly.FieldDropdown.ARROW_CHAR può essere utilizzata per modificare Carattere Unicode che rappresenta la freccia del menu a discesa.

Campo a discesa con freccia personalizzata

Per impostazione predefinita, la proprietà ARROW_CHAR è \u25BC (▼) su Android e \u25BE (▾) negli altri casi.

Questa è una proprietà globale, quindi modifica tutti i campi del menu a discesa quando viene impostata.

La proprietà Blockly.FieldDropdown.MAX_MENU_HEIGHT_VH può essere utilizzata per modificare l'altezza massima del menu. Viene definita come percentuale dell'area visibile in cui l'area visibile è la finestra.

Il valore predefinito della proprietà MAX_MENU_HEIGHT_VH è 0,45.

Questa è una proprietà globale, quindi modifica tutti i campi del menu a discesa quando viene impostata.

Corrispondenza di prefisso/suffisso

Se tutte le opzioni del menu a discesa condividono un prefisso e/o un suffisso comuni queste parole vengono automaticamente escluse e inserite come testo statico. Ad esempio, ecco due modi per creare lo stesso blocco (il primo senza la corrispondenza dei suffissi e la seconda con):

Senza corrispondenza del suffisso:

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 corrispondenza dei suffissi:

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 a discesa con

Un vantaggio di questo approccio è che il blocco è più facile da tradurre in in altre lingue. Il codice precedente ha le stringhe 'hello', 'world' e 'computer', mentre il codice rivisto ha le stringhe 'hello world' e 'hello computer'. Per tradurre le frasi è molto più facile che i traduttori le parole in isolamento.

Un altro vantaggio di questo approccio è che l'ordine delle parole spesso cambia lingue diverse. Immagina una lingua che utilizza 'world hello' e 'computer hello'. L'algoritmo di corrispondenza dei suffissi rileverà il valore 'hello' comune e lo mostrerà dopo il menu a discesa.

Tuttavia, a volte la corrispondenza del prefisso/suffisso non va a buon fine. Ci sono alcuni casi in cui due parole devono sempre andare insieme e il prefisso non deve essere escluso. Ad esempio, 'drive red car' e 'drive red truck' dovrebbero probabilmente solo è stato escluso 'drive', non 'drive red'. Il modello Unicode lo spazio '\u00A0' può essere usato al posto di uno spazio regolare per eliminare per corrispondenze di prefisso/suffisso. Di conseguenza, l'esempio precedente può essere corretto con 'drive red\u00A0car' e 'drive red\u00A0truck'.

Un altro caso in cui la corrispondenza di prefisso/suffisso non riesce è nelle lingue che non separa le singole parole con uno spazio. Il cinese ne è un buon esempio. La stringa '訪問中國' significa 'visit China'. Nota l'assenza di spazi tra le parole. Collettivamente, gli ultimi due caratteri ('中國') sono la parola per 'China', ma se suddivisi significano rispettivamente 'centre' e 'country'. Per rendere l'abbinamento di prefisso/suffisso funziona in lingue quali cinese, basta inserire uno spazio nel punto in cui dovrebbe essere l'interruzione. Ad esempio '訪問 中國' e '訪問 美國' genererebbe "visit [China/USA]", mentre '訪問 中 國' e '訪問 美 國' genererà "visit [centre/beautiful] country".

Creazione di uno strumento di convalida del menu a discesa

Il valore di un campo a discesa è una stringa indipendente dalla lingua, quindi tutti gli strumenti di convalida devono accettare una stringa e restituire una stringa che è un'opzione disponibile, null oppure undefined.

Se lo strumento di convalida restituisce qualcos'altro, il comportamento di Blockly è indefinito il programma potrebbe arrestarsi in modo anomalo.

Ad esempio, puoi definire un campo a discesa con tre opzioni e un di convalida come questo:

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 restituisce sempre il valore passato, ma chiama l'assistente funzione updateConnection che aggiunge o rimuove input in base al menu a discesa valore:

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