Zdefiniuj bloki

Definicje bloków opisują wygląd i zachowanie bloków, w tym tekst, kolor, kształt i inne bloki, z którymi może się łączyć.

Format JSON a JavaScript API

Blockly ma 2 sposoby definiowania bloków: obiekty JSON i funkcje JavaScript. Format JSON ma na celu uproszczenie procesu lokalizacji podczas programowania dla języków o różnej kolejności słów. Preferowaną metodą definiowania bloków jest format JSON.

Format JSON nie umożliwia jednak bezpośredniego definiowania funkcji zaawansowanych, takich jak mutatory czy walidatory. Muszą być one napisane w języku JavaScript, zwykle jako rozszerzenia.

Aplikacje korzystające z pierwotnej implementacji JavaScriptu Blockly mogą też zapisywać definicje bloków bezpośrednio w wywołaniach funkcji interfejsu Blockly API niższego poziomu, jak pokazano w różnych przykładach JavaScriptu poniżej.

JSON

Blockly.defineBlocksWithJsonArray([{
  "type": "string_length",
  "message0": 'length of %1',
  "args0": [
    {
      "type": "input_value",
      "name": "VALUE",
      "check": "String"
    }
  ],
  "output": "Number",
  "colour": 160,
  "tooltip": "Returns number of letters in the provided text.",
  "helpUrl": "http://www.w3schools.com/jsref/jsref_length_string.asp"
}]);

JavaScript

Blockly.Blocks['string_length'] = {
  init: function() {
    this.appendValueInput('VALUE')
        .setCheck('String')
        .appendField('length of');
    this.setOutput(true, 'Number');
    this.setColour(160);
    this.setTooltip('Returns number of letters in the provided text.');
    this.setHelpUrl('http://www.w3schools.com/jsref/jsref_length_string.asp');
  }
};

Funkcja init tworzy kształt bryły. W kontekście tej funkcji słowo kluczowe this oznacza rzeczywisty blok, który jest tworzony.

W obu przykładach wczytuje się ten sam blok „string_length”.

Na stronach internetowych format JSON jest wczytywany za pomocą funkcji initJson. Umożliwia to też połączenie obu formatów na stronach internetowych Blockly. Zalecamy, aby wszędzie tam, gdzie to możliwe, blok był zdefiniowany za pomocą kodu JSON, a kod JavaScriptu powinien być używany tylko w przypadku tych fragmentów definicji bloków, których JSON nie obsługuje.

Poniżej znajduje się przykład bloku zdefiniowanego głównie za pomocą kodu JSON, ale rozszerzonego przy użyciu interfejsu JavaScript API o dynamiczną etykietkę.

JavaScript

var mathChangeJson = {
  "message0": "change %1 by %2",
  "args0": [
    {"type": "field_variable", "name": "VAR", "variable": "item", "variableTypes": [""]},
    {"type": "input_value", "name": "DELTA", "check": "Number"}
  ],
  "previousStatement": null,
  "nextStatement": null,
  "colour": 230
};

Blockly.Blocks['math_change'] = {
  init: function() {
    this.jsonInit(mathChangeJson);
    // Assign 'this' to a variable for use in the tooltip closure below.
    var thisBlock = this;
    this.setTooltip(function() {
      return 'Add a number to variable "%1".'.replace('%1',
          thisBlock.getFieldValue('VAR'));
    });
  }
};

Kolor bloku

Główny kolor bloku jest określany za pomocą właściwości JSON colour, funkcji block.setColour(..) lub za pomocą motywów i określenia stylu bloku.

JSON

{
  // ...,
  "colour": 160,
}

JavaScript

init: function() {
  // ...
  this.setColour(160);
}

Więcej informacji znajdziesz w przewodniku po kolorach bloków.

Połączenia instrukcji

Użytkownicy mogą tworzyć sekwencje bloków za pomocą oprogramowania sprzęgającego nextStatement i previousStatement. W standardowym układzie Blockly te połączenia znajdują się na górze i na dole, a bloki są ułożone pionowo.

Blok z poprzednim oprogramowaniem sprzęgającym nie może mieć złącza wyjściowego i odwrotnie. Termin blok instrukcji odnosi się do bloku bez wartości wyjściowej. Blok instrukcji zwykle zawiera zarówno poprzednie, jak i następne połączenie.

Połączenia nextStatement i previousStatement można wpisywać, ale ta funkcja nie jest używana w standardowych blokach.

Następne połączenie

Tworzy punkt na dole bryły, dzięki czemu można umieszczać pod nim inne instrukcje. Blok z następnym połączeniem, ale bez wcześniejszego połączenia, zwykle reprezentuje zdarzenie i można go skonfigurować tak, aby renderował się za pomocą kapelusza.

JSON

Nietyp:

{
  ...,
  "nextStatement": null,
}

Wpisany (rzadki):

{
  "nextStatement": "Action",
  ...
}

JavaScript

Nietyp:

this.setNextStatement(true);  // false implies no next connector, the default

Wpisane (rzadkie):

this.setNextStatement(true, 'Action');

Poprzednie połączenie

U góry bloku tworzy wycięcie, dzięki któremu można je połączyć w stosunek instrukcji.

Blokady z poprzednim połączeniem nie mogą mieć połączenia wyjściowego.

JSON

Nietyp:

{
  ...,
  "previousStatement": null,
}

Wpisany (rzadki):

{
  "previousStatement": "Action",
  ...
}

JavaScript

Nietyp:

this.setPreviousStatement(true);  // false implies no previous connector, the default

Wpisane (rzadkie):

this.setPreviousStatement(true, 'Action');

Zablokuj dane wyjściowe

Blok może mieć 1 wyjście reprezentowane jako męskie łącznik układanki na pierwszej krawędzi. Dane wyjściowe są połączone z danymi wejściowymi wartości. Blokady z danymi wyjściowymi są zwykle nazywane blokami wartości.

JSON

Nietyp:

{
  // ...,
  "output": null,
}

Wpisano:

{
  // ...,
  "output": "Number",
}

JavaScript

Nietyp:

init: function() {
  // ...
  this.setOutput(true);
}

Wpisano:

init: function() {
  // ...
  this.setOutput(true, 'Number');
}

Bloki z oprogramowaniem sprzęgającym wyjścia nie mogą też mieć poprzedniego wycięcia instrukcji.

Zablokuj wejścia

Blok ma co najmniej 1 wejście, gdzie każde dane wejściowe ma sekwencję pól i może kończyć się połączeniem. Jest kilka rodzajów wbudowanych danych wejściowych.

  • Dane wejściowe wartości: łączy się ze połączeniem wyjściowym bloku wartości. Blok math_arithmetic (dodawanie i odejmowanie) to przykład bloku z 2 wartościami wejściowymi.
  • Dane wejściowe oświadczenia: łączy się z poprzednim połączeniem bloku instrukcji. Przykładem danych wejściowych instrukcji jest zagnieżdżona sekcja pętli instrukcji.
  • Dodatkowe dane wejściowe: nie ma połączenia blokowego. Działa jak nowy wiersz, gdy blok jest skonfigurowany tak, aby używać zewnętrznych danych wejściowych.
  • Dane wejściowe z wiersza końcowego: nie ma połączenia blokowego i zawsze działa jak nowy wiersz.

Możesz też utworzyć niestandardowe dane wejściowe na potrzeby renderowania niestandardowego.

Format JSON i interfejs JavaScript API używają nieco innych modeli do opisywania danych wejściowych.

Dane wejściowe i pola w formacie JSON

Bloki zdefiniowane w formacie JSON mają strukturę sekwencji interpolowanych ciągów komunikatów ( message0, message1, ...), gdzie każdy token interpolacji (%1, %2, ...) to pole lub koniec wejściowe (w którym oprogramowanie sprzęgające dane wejściowe jest renderowane w wiadomości) w pasującej tablicy argsN w formacie JSON. Ten format ułatwia internacjonalizację.

JSON

{
  "message0": "set %1 to %2",
  "args0": [
    {
      "type": "field_variable",
      "name": "VAR",
      "variable": "item",
      "variableTypes": [""]
    },
    {
      "type": "input_value",
      "name": "VALUE"
    }
  ]
}

Tokeny interpolacji muszą być całkowicie zgodne z tablicą args0: brak duplikatów i pominięcia. Tokeny mogą być obecne w dowolnej kolejności, co pozwala różnym językom na zmianę układu bloku.

Tekst po obu stronach tokena interpolacji jest usunięty. Tekst zawierający znak % (np. w odniesieniu do procentu) powinien używać parametru %%, aby nie był on interpretowany jako token interpolacji.

Kształt bloku określa kolejność argumentów i ich typy. Zmiana jednego z tych ciągów może całkowicie zmienić układ bloku. Jest to szczególnie ważne w przypadku języków, w których kolejność słów jest inna niż w języku angielskim. Zastanów się nad hipotetycznym językiem, w którym ciąg "set %1 to %2" (jak użyty w powyższym przykładzie) musi być odwrotny, aby powiedzieć "put %2 in %1". Zmiana tego ciągu (i pozostawienie reszty pliku JSON bez zmian) spowoduje utworzenie takiego bloku:

Funkcja Blockly automatycznie zmieniała kolejność pól, utworzyła przykładowe dane wejściowe i przełączyła dane z zewnętrznych na wewnętrzne.

Blockly automatycznie zastępuje też każdy znak nowego wiersza (\n) w ciągu wiadomości na dane wiersza końcowego.

JSON

{
  "message0": "set %1\nto %2",
  "args0": [
    {
      "type": "field_variable",
      "name": "VAR",
      "variable": "item",
      "variableTypes": [""]
    },
    {
      "type": "input_value",
      "name": "VALUE"
    }
  ]
}

Argi

Każdy ciąg wiadomości jest sparowany z tablicą args o tej samej liczbie. Na przykład message0 łączy się z polem args0. Tokeny interpolacji (%1, %2, ...) odnoszą się do elementów tablicy args. Każdy obiekt ma ciąg znaków type. Pozostałe parametry różnią się w zależności od typu:

Możesz też definiować własne pola niestandardowe i niestandardowe dane wejściowe oraz przekazywać je jako argumenty.

Każdy obiekt może też mieć pole alt. Jeśli Blockly nie rozpoznaje type obiektu, zamiast niego jest używany obiekt alt. Jeśli na przykład do Blockly zostanie dodane nowe pole o nazwie field_time, bloki korzystające z tego pola mogą używać pola alt do zdefiniowania kreacji zastępczej field_input dla starszych wersji Blockly:

JSON

{
  "message0": "sound alarm at %1",
  "args0": [
    {
      "type": "field_time",
      "name": "TEMPO",
      "hour": 9,
      "minutes": 0,
      "alt":
        {
          "type": "field_input",
          "name": "TEMPOTEXT",
          "text": "9:00"
        }
    }
  ]
}

Obiekt alt może mieć własny obiekt alt, co umożliwia tworzenie łańcuchów. Jeśli Blockly nie uda się utworzyć obiektu w tablicy args0 (po wypróbowaniu jakichkolwiek obiektów alt), zostanie on po prostu pominięty.

Przykładowe dane wejściowe zostaną automatycznie dodane na końcu bloku, jeśli ciąg message kończy się tekstem lub polami, które nie należą do danych wejściowych. Jeśli więc ostatnie dane wejściowe w bloku są fikcyjnymi danymi, mogą one zostać pominięte w tablicy args i nie wymagają interpolacji na message. Automatyczne dodanie skróconych przykładowych danych wejściowych umożliwia tłumaczom zmianę właściwości message bez konieczności modyfikowania reszty pliku JSON. Zapoznaj się wcześniej na tej stronie z przykładami "set %1 to %2" (bez fikcyjnych danych wejściowych) i "put %2 in %1" (dodano zastępcze dane wejściowe).

implicitAlign0

W rzadkich przypadkach automatycznie tworzone końcowe dane wejściowe muszą być dopasowane do "RIGHT" lub "CENTRE". Jeśli nie zostanie określona, wartością domyślną jest "LEFT".

W poniższym przykładzie message0 wygląda na "send email to %1 subject %2 secure %3", a blockly automatycznie dodaje fikcyjne dane wejściowe do trzeciego wiersza. Ustawienie wartości implicitAlign0 na "RIGHT" wymusza wyrównanie tego wiersza do prawej. To wyrównanie odnosi się do wszystkich danych wejściowych, które nie są wyraźnie określone w definicji bloku JSON, w tym do danych z końcowego wiersza, które zastępują znaki nowego wiersza ('\n') w wiadomości. Jest też wycofana właściwość lastDummyAlign0, która działa tak samo jak implicitAlign0.

Podczas projektowania bloków dla tekstu RTL (arabskim i hebrajskim) bloki są ułożone w lewo i w prawo. Dzięki temu "RIGHT" wyrówna pola do lewej.

message1, args1, implicitAlign1

Niektóre bloki są naturalnie podzielone na dwie lub więcej osobnych części. Przeanalizujmy ten blok powtórzony z 2 wierszami:

Jeśli ten blok został opisany za pomocą jednego komunikatu, właściwość message0 miałaby wartość "repeat %1 times %2 do %3". Ten ciąg znaków jest niezręczny dla tłumacza i trudno jest wyjaśnić, co oznacza zastępowanie %2. Zastępcze dane wejściowe %2 też mogą być niepotrzebne w przypadku niektórych języków. Może istnieć wiele bloków, które będą chciały udostępnić tekst drugiego wiersza. Lepszym rozwiązaniem jest używanie w formacie JSON więcej niż 1 właściwości wiadomości i argumentów:

JSON

{
  "type": "controls_repeat_ext",
  "message0": "repeat %1 times",
  "args0": [
    {"type": "input_value", "name": "TIMES", "check": "Number"}
  ],
  "message1": "do %1",
  "args1": [
    {"type": "input_statement", "name": "DO"}
  ],
  "previousStatement": null,
  "nextStatement": null,
  "colour": 120
}

W formacie JSON można zdefiniować dowolną liczbę właściwości message, args i implicitAlign z wartością 0 i rosnąco sekwencyjnie. Pamiętaj, że Block Factory nie pozwala na dzielenie wiadomości na kilka części, ale możesz zrobić to ręcznie.

Dane wejściowe i pola w JavaScript

Interfejs JavaScript API obejmuje metodę append dla każdego typu danych wejściowych:

JavaScript

this.appendEndRowInput()
    .appendField('for each')
    .appendField('item')
    .appendField(new Blockly.FieldVariable());
this.appendValueInput('LIST')
    .setCheck('Array')
    .setAlign(Blockly.inputs.Align.RIGHT)
    .appendField('in list');
this.appendStatementInput('DO')
    .appendField('do');
this.appendDummyInput()
    .appendField('end');

Każda metoda dołączania może przyjmować ciąg identyfikatora używany przez generatory kodu. Próbne i wejściowe dane wejściowe w wierszu końcowym rzadko wymagają odwoływania się, a identyfikator zwykle jest nieskonfigurowany.

Interfejs JavaScript API obejmuje też ogólną metodę appendInput do dołączania niestandardowych danych wejściowych. Pamiętaj, że w tym przypadku identyfikator powinien zostać przekazany bezpośrednio do konstruktora danych wejściowych niestandardowych.

JavaScript

this.appendInput(new MyCustomInput('INPUT_NAME'))
    .appendField('an example label')

Wszystkie metody appendInput (ogólne i nieogólne) zwracają obiekt wejściowy, aby można było je dodatkowo skonfigurować za pomocą łańcucha metod. Istnieją 3 wbudowane metody konfigurowania danych wejściowych.

setCheck

JavaScript

input.setCheck('Number');

Ta opcjonalna funkcja służy do sprawdzania typu podłączonych danych wejściowych. Jeśli argument ma wartość null, to dane wejściowe mogą być połączone z dowolnym blokiem. Więcej informacji znajdziesz w sekcji Sprawdzanie typu.

setAlign

JavaScript

input.setAlign(Blockly.inputs.Align.RIGHT);

Ta opcjonalna funkcja służy do wyrównywania pól (patrz poniżej). Istnieją 3 samoopisowe wartości, które można przekazać jako argument do tej funkcji: Blockly.inputs.Align.LEFT, Blockly.inputs.Align.RIGHT i Blockly.inputs.Align.CENTER.

Podczas projektowania bloków dla tekstu RTL (arabskim i hebrajskim) bloki są ułożone w lewo i w prawo. Dzięki temu Blockly.inputs.Align.RIGHT wyrówna pola do lewej.

appendField

Gdy dane wejściowe zostaną utworzone i dołączone do bloku za pomocą appendInput, można opcjonalnie dołączyć do nich dowolną liczbę pól. Pola te są często używane jako etykiety do opisywania przeznaczenia poszczególnych danych wejściowych.

JavaScript

input.appendField('hello');

Najprostszym elementem pola jest tekst. Zgodnie z konwencją Blockly tekst jest pisany małymi literami, z wyjątkiem nazw własnych (np. Google, SQL).

Wiersz wejściowy może zawierać dowolną liczbę elementów pól. Można połączyć kilka wywołań funkcji appendField, aby wydajnie dodać kilka pól do tego samego wiersza danych wejściowych.

JavaScript

input.appendField('hello')
     .appendField(new Blockly.FieldLabel('Neil', 'person'));

Wywołanie appendField('hello') jest skrótem do użycia jawnego konstruktora FieldLabel: appendField(new Blockly.FieldLabel('hello')). Jedynym przypadkiem, w którym warto użyć konstruktora, jest podanie nazwy klasy, aby można było zmieniać styl tekstu za pomocą reguły CSS.

Wewnętrzne a zewnętrzne

Zablokowane dane wejściowe mogą być renderowane jako zewnętrzne lub wewnętrzne.

Definicja bloku może określać opcjonalną wartość logiczną określającą, czy dane wejściowe są wbudowane, czy nie. Jeśli ustawiona jest wartość false, wszystkie dane wejściowe będą zewnętrzne (np. lewy blok). Jeśli ustawiona będzie wartość true, wszystkie dane wejściowe będą wbudowane (np. prawy blok powyżej).

JSON

{
  // ...,
  "inputsInline": true
}

JavaScript

init: function() {
  // ...
  this.setInputsInline(true);
}

Jeśli nie zdefiniujesz tego trybu, Blockly będzie używać algorytmu heurystycznego, aby odgadnąć, który tryb jest najlepszy. Zakładając, że Blockly dokonuje właściwego wyboru, zalecamy pozostawienie tego pola niezdefiniowanego, ponieważ tłumaczenia na różne języki mogą automatycznie uzyskiwać różne tryby. Zapoznaj się wcześniej na tej stronie z przykładem kodu JSON "set %1 to %2" (zewnętrzne dane wejściowe) i "put %2 in %1" (wbudowane dane wejściowe).

Stosuj wbudowane dane wejściowe, gdy blok prawdopodobnie będzie zawierać małe dane, na przykład liczby. Jeśli włączona jest konfiguracja collapse, użytkownik może przełączać tę opcję w menu kontekstowym (wartość domyślna to prawda, jeśli zestaw narzędzi ma kategorie).

Pola

Pola definiują większość elementów interfejsu w bloku. Obejmuje to etykiety ciągów znaków, obrazy oraz dane wejściowe dosłownych danych, np. ciągów tekstowych i liczb. Najprostszym przykładem jest blok math_number, w którym użytkownik może wpisać liczbę za pomocą field_input.

Pola są dołączane do bloku za pomocą appendField.

Blockly udostępnia wiele wbudowanych pól, w tym pola do wprowadzania tekstu, selektory kolorów i obrazy. Możesz też tworzyć własne pola.

→ Więcej informacji o polach wbudowanych.

→ Więcej informacji o tworzeniu pól niestandardowych.

Ikony

Ikony definiują elementy interfejsu w obrębie bloku, które wyświetlają „meta” informacje o bloku.

Ikony są dołączane do bloku za pomocą elementu addIcon.

Blockly ma wiele wbudowanych ikon, w tym ikony komentarzy i ostrzeżeń. Możesz też tworzyć własne ikony.

→ Więcej informacji o tworzeniu ikon niestandardowych.

Etykiety

Etykietka zapewnia natychmiastową pomoc, gdy użytkownik najedzie kursorem na bryłę. Jeśli tekst jest długi, zawija się automatycznie.

JSON

{
  // ...,
  "tooltip": "Tooltip text."
}

JavaScript

init: function() {
  this.setTooltip("Tooltip text.");
}

W interfejsie JavaScript API etykietki można też zdefiniować jako funkcję zamiast statycznego ciągu znaków. Zapewnia to dynamiczną pomoc. Przykład etykietki, która zmienia się w zależności od wybranej opcji menu, znajdziesz w sekcji math_arithmetic.

JavaScript

Blockly.Blocks['math_arithmetic'] = {
  init: function() {
    // ...

    // Assign 'this' to a variable for use in the tooltip closure below.
    var thisBlock = this;
    this.setTooltip(function() {
      var mode = thisBlock.getFieldValue('OP');
      var TOOLTIPS = {
        'ADD': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD,
        'MINUS': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS,
        'MULTIPLY': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY,
        'DIVIDE': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE,
        'POWER': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER
      };
      return TOOLTIPS[mode];
    });
  }
};

Za pomocą interfejsu JavaScript API bloki mogą określać funkcję zamiast statycznego ciągu znaków, który zwraca ciąg etykietki. Umożliwia to wyświetlanie dynamicznych etykietek. Przykład znajdziesz na stronie math_arithmetic.

Dostosowywanie

Wygląd etykiet możesz dostosować, dodając niestandardową funkcję renderowania. Utwórz funkcję, która akceptuje 2 parametry:

  • Pierwszy element to <div>, w którym będziesz renderować treść
  • Po drugie: rzeczywisty element, na który jest najeżdżany kursor myszy, i który pojawia się etykietka

W treści funkcji możesz renderować dowolną treść w elemencie div. Aby uzyskać ciąg etykietki zdefiniowany w obiekcie, na który najeżdżasz kursorem, możesz wywołać Blockly.Tooltip.getTooltipOfObject(element);, gdzie element to drugi parametr powyżej.

Na koniec zarejestruj tę funkcję, aby Blockly mogła ją wywołać w odpowiednim momencie:

Blockly.Tooltip.setCustomTooltip(yourFnHere);

Przykład znajdziesz w prezentacji niestandardowych etykietek.

URL pomocy

Do blokowania może być przypisana strona pomocy. Ta funkcja jest dostępna dla użytkowników Blockly for Web, klikając prawym przyciskiem myszy blok i wybierając „Pomoc” z menu kontekstowego. Jeśli ta wartość to null, menu jest wyszarzone.

JSON

{
  // ...,
  "helpUrl": "https://en.wikipedia.org/wiki/For_loop"
}

JavaScript

init: function() {
  // ...
  this.setHelpUrl('https://en.wikipedia.org/wiki/For_loop');
}

Za pomocą interfejsu JavaScript API bloki mogą określać funkcję zamiast statycznego ciągu znaków, który zwraca ciąg adresu URL, co pozwala uzyskać dynamiczną pomoc.

Zmień detektory i walidatory

Blokady mogą mieć funkcje detektora zmian, które są wywoływane w przypadku każdej zmiany w obszarze roboczym (także tych niezwiązanych z blokiem). Służą one głównie do ustawiania tekstu ostrzeżenia dotyczącego blokowania lub podobnego powiadomienia użytkownika poza obszarem roboczym.

Ta funkcja jest dodawana przez wywołanie setOnChange z użyciem funkcji. Można ją wykonać podczas inicjowania lub za pomocą rozszerzenia JSON, jeśli zamierzasz używać jej na wszystkich platformach.

JSON

{
  // ...,
  "extensions":["warning_on_change"],
}

Blockly.Extensions.register('warning_on_change', function() {
  // Example validation upon block change:
  this.setOnChange(function(changeEvent) {
    if (this.getInput('NUM').connection.targetBlock()) {
      this.setWarningText(null);
    } else {
      this.setWarningText('Must have an input block.');
    }
  });
});

JavaScript

Blockly.Blocks['block_type'] = {
  init: function() {
    // Example validation upon block change:
    this.setOnChange(function(changeEvent) {
      if (this.getInput('NUM').connection.targetBlock()) {
        this.setWarningText(null);
      } else {
        this.setWarningText('Must have an input block.');
      }
    });
  }
}

System wywołuje tę funkcję, przekazując zdarzenie zmiany. Wewnątrz funkcji this odnosi się do instancji bloku.

Funkcja jest wywoływana po każdej zmianie, więc deweloperzy powinni zadbać o to, aby detektor działał szybko. Trzeba też uważać na zmiany w obszarze roboczym, które mogą spływać kaskadowo lub zapętlać się do detektora.

Przykłady znajdziesz w blokach controls_flow_statements, logic_compare i procedures_ifreturn.

Pamiętaj, że pola do edycji mają własne detektory zdarzeń do weryfikacji danych wejściowych i powodując efekty uboczne.

Mutator

Mutatory umożliwiają zaawansowanym blokom zmienianie kształtu, zwłaszcza w wyniku tego, że użytkownicy otwierają okno, w którym mogą dodawać, usuwać i zmieniać kolejność komponentów. Mutatory można dodawać w formacie JSON z kluczem mutator.

JSON

{
  // ...,
  "mutator":"if_else_mutator"
}

Konfiguracja dla poszczególnych bloków

Instancje zablokowanych mają kilka właściwości, które określają sposób ich działania w przypadku użytkownika. Można ich używać do ograniczania obszaru roboczego, aby odzwierciedlić określone właściwości domeny (np. istnieje dokładnie jedno zdarzenie „start”) lub skupić się na czynnościach użytkownika (np. samouczek).

Stan możliwy do usunięcia

block.setDeletable(false);

Jeśli zasada ma wartość Fałsz, użytkownik nie może usunąć blokady. Domyślnie bloki, które można usunąć, w obszarze roboczym z możliwością edytowania.

Każdy blok (nawet niemożliwy do usunięcia) może zostać usunięty automatycznie:

block.dispose();

Edytowalny stan

block.setEditable(false);

Jeśli zasada ma wartość Fałsz, użytkownik nie może zmieniać pól bloku (np. menu ani danych wejściowych). W obszarze roboczym z możliwością edytowania domyślnie można edytować bloki.

Stan mobilny

block.setMovable(false);

Jeśli zasada ma wartość Fałsz, użytkownik nie może bezpośrednio przenieść bloku. Blok nieruchomy będący podrzędną bryłą innej bryły nie może być od niej odłączony, jednak jeśli przesuniesz element nadrzędny, będzie on przesuwał się razem ze swoją bryłą nadrzędną. W obszarze roboczym z możliwością edytowania domyślnie można przenosić bloki.

Każdą bryłę (nawet nieruchomą) można przenieść w sposób zautomatyzowany w obszarze roboczym.

block.moveBy(dx, dy)

Domyślna pozycja blokady w obszarze roboczym to (0, 0).

Blokuj transmisję danych

this.data = '16dcb3a4-bd39-11e4-8dfc-aa07a5b093db';

Dane to opcjonalny i dowolny ciąg tekstowy dołączany do bloku danych. Gdy blok jest zserializowany, ciąg danych jest z nim zserializowany. Dotyczy to też sytuacji, gdy blok został zduplikowany lub skopiowany i wklejony.

Często jest to sposób na powiązanie blokady z zasobem zewnętrznym.

Po zserializowaniu do formatu JSON dane są przechowywane w bloku jako właściwość najwyższego poziomu:

{
  "type": "my_block",
  "data": "16dcb3a4-bd39-11e4-8dfc-aa07a5b093db",
  // etc..
}

W przypadku zserializowania do formatu XML (starego systemu serializacji lodowych) ciąg danych jest przechowywany w tagu <data></data> wewnątrz bloku:

<block type="my_block">
  <data>16dcb3a4-bd39-11e4-8dfc-aa07a5b093db</data>
  <!-- etc... -->
</block>

Zniszczenie

Bloki mają punkt zaczepienia destroy, który jest wywoływany po usunięciu ich z obszaru roboczego. Można go użyć do zniszczenia zapasowych modeli danych/zasobów zewnętrznych powiązanych z blokiem, które nie są już potrzebne.

JSON

{
  // ...,
  "extensions":["destroy"],
}

Blockly.Extensions.registerMixin('destroy', {
  destroy: function() {
    this.myResource.dispose();
  }
});

JavaScript

Blockly.Blocks['block_type'] = {
  destroy: function() {
    this.myResource.dispose();
  }
}

Metoda destroy jest wywoływana po usunięciu elementu nadrzędnego bloku, ale przed usunięciem jego elementów podrzędnych lub pól podrzędnych.

Menu kontekstowe

Domyślnie bloki mają menu kontekstowe dostępne po kliknięciu prawym przyciskiem myszy, które pozwala użytkownikom wykonywać takie czynności jak dodawanie komentarzy czy duplikowanie blokad.

Aby wyłączyć menu kontekstowe poszczególnych bloków, wykonaj te czynności:

block.contextMenu = false;

Możesz też dostosować opcje wyświetlane w menu. Aby dostosować menu wszystkich bloków, zapoznaj się z dokumentacją menu kontekstowych. Aby dostosować menu pojedynczej blokady, możesz zastosować customContextMenu. Ta funkcja pobiera tablicę opcji menu i ją zmienia. Oznacza to, że możesz zarówno dodawać, jak i usuwać pozycje.

Każda opcja menu to obiekt o 3 właściwościach:

  • text to wyświetlany tekst.
  • enabled jest wartością logiczną. Gdy opcja jest wyłączona, opcja jest widoczna, ale z szarym tekstem.
  • callback to funkcja, która jest wywoływana po kliknięciu opcji.