Tworzenie pola niestandardowego

Zanim utworzysz nowy typ pola, zastanów się, czy nie wystarczy Ci jedna z innych metod dostosowywania pól. Jeśli aplikacja musi przechowywać nowy typ wartości lub chcesz utworzyć nowy interfejs dla istniejącego typu wartości, prawdopodobnie musisz utworzyć nowy typ pola.

Aby utworzyć nowe pole:

  1. Wdróż konstruktor
  2. Zarejestruj klucz JSON i wdroż interfejs fromJson.
  3. Obsługa inicjowania interfejsu i detektorów zdarzeń w przypadku blokowania.
  4. Obsługa usuwania detektorów zdarzeń (usuwanie interfejsu jest obsługiwane za Ciebie).
  5. Wdrożenie obsługi wartości
  6. Dodaj tekstową reprezentację wartości pola, aby ułatwić dostęp.
  7. Dodawanie dodatkowych funkcji, takich jak:
  8. Skonfiguruj dodatkowe aspekty pola, takie jak:

W tej sekcji zakładamy, że znasz już treść artykułu Anatomia pola.

Przykład pola niestandardowego znajdziesz w demonstracji pól niestandardowych.

Implementowanie konstruktora

Konstruktor pola odpowiada za ustawienie wartości początkowej pola i opcjonalnie za skonfigurowanie lokalnego walidatora. Konstruktor pola niestandardowego jest wywoływany podczas inicjowania bloku źródłowego niezależnie od tego, czy blok źródłowy jest zdefiniowany w JSON czy w JavaScript. Dlatego podczas tworzenia pole niestandardowe nie ma dostępu do bloku źródłowego.

Poniższy przykładowy kod tworzy pole niestandardowe o nazwie GenericField:

class GenericField extends Blockly.Field {
  constructor(value, validator) {
    super(value, validator);

    this.SERIALIZABLE = true;
  }
}

Sygnatura metody

Konstruktory pól zwykle przyjmują wartość i lokalny weryfikator. Wartość jest opcjonalna. Jeśli nie podasz wartości (lub podasz wartość, która nie przejdzie weryfikacji klasy), zostanie użyta wartość domyślna superklasy. W przypadku domyślnej klasy Field wartość ta wynosi null. Jeśli nie chcesz używać tej domyślnej wartości, podaj odpowiednią wartość. Parametr weryfikatora występuje tylko w przypadku pól edytowalnych i jest zwykle oznaczony jako opcjonalny. Więcej informacji o walidatorach znajdziesz w dokumentacji dotyczącej walidatorów.

Struktura

Logika w konstruktorze powinna przebiegać w ten sposób:

  1. Wywołaj odziedziczony superkonstruktor (wszystkie pola niestandardowe powinny dziedziczyć z klasy Blockly.Field lub jednej z jej podklas), aby prawidłowo zainicjować wartość i ustawić lokalny walidator dla pola.
  2. Jeśli pole można serializować, ustaw odpowiednią właściwość w konstruktorze. Pola, które można edytować, muszą być serializowane, a pola są domyślnie edytowalne, więc prawdopodobnie należy ustawić tę właściwość na wartość true, chyba że wiesz, że nie powinna być serializowana.
  3. Opcjonalnie: zastosuj dodatkowe dostosowanie (np. pola etykiet umożliwiają przekazanie klasy CSS, która jest następnie stosowana do tekstu).

JSON i rejestracja

W definicjach bloków JSON pola są opisywane za pomocą ciągu znaków (np. field_number, field_textinput). Blockly utrzymuje mapę tych ciągów znaków do obiektów pól i podczas tworzenia wywołuje fromJson na odpowiednim obiekcie.

Wywołaj funkcję Blockly.fieldRegistry.register, aby dodać typ pola do tej mapy, przekazując klasę pola jako drugi argument:

Blockly.fieldRegistry.register('field_generic', GenericField);

Musisz też zdefiniować fromJson funkcję. Implementacja powinna najpierw usunąć odwołania do tokenów lokalizacji za pomocą funkcji replaceMessageReferences, a następnie przekazać wartości do konstruktora.

GenericField.fromJson = function(options) {
  const value = Blockly.utils.parsing.replaceMessageReferences(
      options['value']);
  return new CustomFields.GenericField(value);
};

Inicjowanie

Gdy pole jest tworzone, zawiera ono tylko wartość. Podczas inicjowania tworzony jest DOM, model (jeśli pole ma model) i powiązania zdarzeń.

Wyświetlanie na bloku

Podczas inicjowania musisz utworzyć wszystko, co będzie potrzebne do wyświetlania bloku pola.

Wartości domyślne, tło i tekst

Domyślna funkcja initView tworzy jasny element rect i element text. Jeśli chcesz, aby pole miało obie te cechy i dodatkowe funkcje, wywołaj funkcję klasy nadrzędnej initView przed dodaniem pozostałych elementów DOM. Jeśli chcesz, aby pole zawierało jeden z tych elementów, ale nie oba, możesz użyć funkcji createBorderRect_ lub createTextElement_.

Dostosowywanie konstrukcji DOM

Jeśli pole jest ogólnym polem tekstowym (np. Text Input), konstrukcja DOM zostanie obsłużona za Ciebie. W przeciwnym razie musisz zastąpić funkcję initView, aby utworzyć elementy DOM, które będą potrzebne podczas przyszłego renderowania pola.

Na przykład pole menu może zawierać zarówno obrazy, jak i tekst. W initView tworzy jeden element obrazu i jeden element tekstowy. Następnie w trakcie render_wyświetla aktywny element i ukrywa pozostałe w zależności od typu wybranej opcji.

Elementy DOM można tworzyć za pomocą metody Blockly.utils.dom.createSvgElement lub tradycyjnych metod tworzenia DOM.

Wymagania dotyczące wyświetlania pola w bloku:

  • Wszystkie elementy DOM muszą być elementami podrzędnymi pola fieldGroup_. Grupa pól zostanie utworzona automatycznie.
  • Wszystkie elementy DOM muszą mieścić się w zgłoszonych wymiarach pola.

Więcej informacji o dostosowywaniu i aktualizowaniu wyświetlania na bloku znajdziesz w sekcji Renderowanie.

Dodawanie symboli tekstowych

Jeśli chcesz dodać symbole do tekstu w polu (np. symbol stopnia w polu Kąt), możesz dołączyć element symbolu (zwykle zawarty w <tspan>) bezpośrednio do textElement_ pola.

Zdarzenia wprowadzania danych

Domyślnie pola rejestrują zdarzenia związane z etykietkami i zdarzenia naciśnięcia przycisku myszy (używane do wyświetlania edytorów). Jeśli chcesz nasłuchiwać innych rodzajów zdarzeń (np. chcesz obsługiwać przeciąganie w polu), zastąp funkcję bindEvents_ pola.

bindEvents_() {
  // Call the superclass function to preserve the default behavior as well.
  super.bindEvents_();

  // Then register your own additional event listeners.
  this.mouseDownWrapper_ =
  Blockly.browserEvents.conditionalBind(this.getClickTarget_(), 'mousedown', this,
      function(event) {
        this.originalMouseX_ = event.clientX;
        this.isMouseDown_ = true;
        this.originalValue_ = this.getValue();
        event.stopPropagation();
      }
  );
  this.mouseMoveWrapper_ =
    Blockly.browserEvents.conditionalBind(document, 'mousemove', this,
      function(event) {
        if (!this.isMouseDown_) {
          return;
        }
        var delta = event.clientX - this.originalMouseX_;
        this.setValue(this.originalValue_ + delta);
      }
  );
  this.mouseUpWrapper_ =
    Blockly.browserEvents.conditionalBind(document, 'mouseup', this,
      function(_event) {
        this.isMouseDown_ = false;
      }
  );
}

Aby powiązać zdarzenie, użyj funkcji Blockly.utils.browserEvents.conditionalBind. Ta metoda wiązania zdarzeń odfiltrowuje dodatkowe dotknięcia podczas przeciągania. Jeśli chcesz, aby funkcja obsługi działała nawet w trakcie przeciągania, możesz użyć funkcji Blockly.browserEvents.bind.

Usuwanie

Jeśli w funkcji bindEvents_pola zarejestrowano jakieś niestandardowe odbiorniki zdarzeń, należy je wyrejestrować w funkcji dispose.

Jeśli prawidłowo zainicjujesz widok pola (dodając wszystkie elementy DOM do fieldGroup_), DOM pola zostanie automatycznie usunięty.

Obsługa wartości

→ Informacje o wartości pola w porównaniu z jego tekstem znajdziesz w artykule Anatomia pola.

Kolejność weryfikacji

Schemat blokowy przedstawiający kolejność uruchamiania walidatorów

Implementowanie walidatora klasy

Pola powinny akceptować tylko określone wartości. Na przykład pola liczbowe powinny akceptować tylko liczby, a pola kolorów – tylko kolory. Zapewniają to walidatory klas i walidatory lokalne. Walidator klasy podlega tym samym regułom co walidatory lokalne, z tym że jest też uruchamiany w konstruktorze i nie powinien odwoływać się do bloku źródłowego.

Aby zaimplementować walidator klasy pola, zastąp funkcję doClassValidation_.

doClassValidation_(newValue) {
  if (typeof newValue != 'string') {
    return null;
  }
  return newValue;
};

Obsługa prawidłowych wartości

Jeśli wartość przekazana do pola z parametrem setValue jest prawidłowa, otrzymasz wywołanie zwrotne doValueUpdate_. Domyślnie funkcja doValueUpdate_:

  • Ustawia właściwość value_ na newValue.
  • Ustawia właściwość isDirty_ na true.

Jeśli chcesz tylko zapisać wartość i nie chcesz wykonywać żadnych niestandardowych działań, nie musisz zastępować funkcji doValueUpdate_.

W przeciwnym razie, jeśli chcesz wykonać czynności takie jak:

  • Niestandardowe miejsce na dane o rozmiarze newValue.
  • Zmień inne właściwości na podstawie newValue.
  • Zapisz, czy bieżąca wartość jest prawidłowa.

Musisz zastąpić doValueUpdate_:

doValueUpdate_(newValue) {
  super.doValueUpdate_(newValue);
  this.displayValue_ = newValue;
  this.isValueValid_ = true;
}

Obsługa nieprawidłowych wartości

Jeśli wartość przekazana do pola z parametrem setValue jest nieprawidłowa, otrzymasz wywołanie zwrotne doValueInvalid_. Domyślnie funkcja doValueInvalid_ nie robi nic. Oznacza to, że domyślnie nieprawidłowe wartości nie będą wyświetlane. Oznacza to również, że pole nie zostanie ponownie wyrenderowane, ponieważ właściwość isDirty_ nie zostanie ustawiona.

Jeśli chcesz wyświetlać nieprawidłowe wartości, zastąp doValueInvalid_. W większości przypadków należy ustawić właściwość displayValue_ na nieprawidłową wartość, ustawić isDirty_ na truezastąpić render_ w przypadku wyświetlania w bloku, aby aktualizować dane na podstawie displayValue_ zamiast value_.

doValueInvalid_(newValue) {
  this.displayValue_ = newValue;
  this.isDirty_ = true;
  this.isValueValid_ = false;
}

Wartości wieloczęściowe

Jeśli pole zawiera wartość wieloczęściową (np. listy, wektory, obiekty), możesz chcieć, aby poszczególne części były traktowane jako osobne wartości.

doClassValidation_(newValue) {
  if (FieldTurtle.PATTERNS.indexOf(newValue.pattern) == -1) {
    newValue.pattern = null;
  }

  if (FieldTurtle.HATS.indexOf(newValue.hat) == -1) {
    newValue.hat = null;
  }

  if (FieldTurtle.NAMES.indexOf(newValue.turtleName) == -1) {
    newValue.turtleName = null;
  }

  if (!newValue.pattern || !newValue.hat || !newValue.turtleName) {
    this.cachedValidatedValue_ = newValue;
    return null;
  }
  return newValue;
}

W powyższym przykładzie każda właściwość newValue jest weryfikowana osobno. Następnie na końcu funkcji doClassValidation_, jeśli którakolwiek z poszczególnych właściwości jest nieprawidłowa, wartość jest zapisywana w pamięci podręcznej we właściwości cacheValidatedValue_ przed zwróceniem wartości null (nieprawidłowa). Buforowanie obiektu z osobno zweryfikowanymi właściwościami umożliwia funkcji doValueInvalid_ oddzielne ich obsługiwanie przez sprawdzenie !this.cacheValidatedValue_.property zamiast ponownego weryfikowania każdej właściwości z osobna.

Ten wzorzec weryfikacji wartości wieloczęściowych można też stosować w lokalnych walidatorach, ale obecnie nie ma możliwości wymuszenia tego wzorca.

isDirty_

isDirty_ to flaga używana w funkcji setValue i innych częściach pola, która informuje, czy pole wymaga ponownego renderowania. Jeśli wartość wyświetlana pola uległa zmianie, zwykle należy ustawić wartość isDirty_ na true.

Tekst

→ Informacje o tym, gdzie jest używany tekst pola i czym różni się od wartości pola, znajdziesz w artykule Anatomia pola.

Jeśli tekst pola różni się od jego wartości, musisz zastąpić funkcję getText, aby podać prawidłowy tekst.

getText() {
  let text = this.value_.turtleName + ' wearing a ' + this.value_.hat;
  if (this.value_.hat == 'Stovepipe' || this.value_.hat == 'Propeller') {
    text += ' hat';
  }
  return text;
}

Tworzenie edytującego

Jeśli zdefiniujesz funkcję showEditor_, Blockly będzie automatycznie nasłuchiwać kliknięć i w odpowiednim momencie wywoływać funkcję showEditor_. W edytorze możesz wyświetlić dowolny kod HTML, umieszczając go w jednym z 2 specjalnych div, zwanych DropDownDivWidgetDiv, które są wyświetlane nad resztą interfejsu Blockly.

Właściwość DropDownDiv służy do udostępniania edytorów, które znajdują się w polu połączonym z innym polem. Automatycznie ustawia się w pobliżu pola, pozostając w widocznych granicach. Selektor kąta i selektor kolorów to dobre przykłady DropDownDiv.

Obraz selektora kąta

Element WidgetDiv służy do udostępniania edytorów, które nie znajdują się w ramce. Pola liczbowe używają tagu WidgetDiv, aby pokryć pole polem wprowadzania tekstu HTML. O ile element DropDownDiv obsługuje pozycjonowanie, o tyle element WidgetDiv nie. Elementy trzeba będzie ustawić ręcznie. Układ współrzędnych jest podawany w pikselach względem lewego górnego rogu okna. Edytor wpisywania tekstu jest dobrym przykładem WidgetDiv.

Obraz przedstawiający edytor wprowadzania tekstu

showEditor_() {
  // Create the widget HTML
  this.editor_ = this.dropdownCreate_();
  Blockly.DropDownDiv.getContentDiv().appendChild(this.editor_);

  // Set the dropdown's background colour.
  // This can be used to make it match the colour of the field.
  Blockly.DropDownDiv.setColour('white', 'silver');

  // Show it next to the field. Always pass a dispose function.
  Blockly.DropDownDiv.showPositionedByField(
      this, this.disposeWidget_.bind(this));
}

Przykładowy kod WidgetDiv

showEditor_() {
  // Show the div. This automatically closes the dropdown if it is open.
  // Always pass a dispose function.
  Blockly.WidgetDiv.show(
    this, this.sourceBlock_.RTL, this.widgetDispose_.bind(this));

  // Create the widget HTML.
  var widget = this.createWidget_();
  Blockly.WidgetDiv.getDiv().appendChild(widget);
}

Czyszczę dane

Zarówno funkcja DropDownDiv, jak i WidgetDiv obsługują usuwanie elementów HTML widżetu, ale musisz ręcznie usunąć wszystkie detektory zdarzeń zastosowane do tych elementów.

widgetDispose_() {
  for (let i = this.editorListeners_.length, listener;
      listener = this.editorListeners_[i]; i--) {
    Blockly.browserEvents.unbind(listener);
    this.editorListeners_.pop();
  }
}

Funkcja dispose jest wywoływana w kontekście null na obiekcie DropDownDiv. Na WidgetDiv jest ona wywoływana w kontekście WidgetDiv. W obu przypadkach najlepiej jest użyć funkcji bind podczas przekazywania funkcji dispose, jak pokazano w przykładach DropDownDivWidgetDiv powyżej.

→ Informacje o utylizacji, które nie dotyczą konkretnie utylizacji edytorów, znajdziesz w artykule Utylizacja.

Aktualizowanie wyświetlania na bloku

Funkcja render_ służy do aktualizowania wyświetlania pola w bloku, aby było zgodne z jego wartością wewnętrzną.

Typowe przykłady:

  • Zmienianie tekstu (menu)
  • Zmiana koloru (kolor)

Domyślne

Domyślna funkcja render_ ustawia tekst wyświetlany na wynik funkcji getDisplayText_. Funkcja getDisplayText_ zwraca właściwość value_ pola przekształconą w ciąg znaków po obcięciu do maksymalnej długości tekstu.

Jeśli używasz domyślnego wyświetlania w bloku i domyślne zachowanie tekstu w przypadku Twojego pola jest odpowiednie, nie musisz zastępować parametru render_.

Jeśli domyślne zachowanie tekstu jest odpowiednie dla Twojego pola, ale jego wyświetlanie w bloku zawiera dodatkowe elementy statyczne, możesz wywołać domyślną funkcję render_, ale nadal musisz ją zastąpić, aby zaktualizować rozmiar pola.

Jeśli domyślne działanie tekstu nie sprawdza się w przypadku Twojego pola lub wyświetlanie w bloku pola zawiera dodatkowe elementy dynamiczne, musisz dostosować funkcję render_.

Schemat blokowy opisujący, jak podjąć decyzję o zastąpieniu funkcji render_

Dostosowywanie renderowania

Jeśli domyślne działanie renderowania nie sprawdza się w przypadku Twojego pola, musisz zdefiniować niestandardowe działanie renderowania. Może to obejmować wszystko, od ustawienia niestandardowego tekstu wyświetlanego po zmianę elementów obrazu i aktualizację kolorów tła.

Wszystkie zmiany atrybutów DOM są prawidłowe. Należy tylko pamiętać o tych 2 rzeczach:

  1. Tworzenie DOM powinno odbywać się podczas inicjowania, ponieważ jest to bardziej wydajne.
  2. Zawsze aktualizuj właściwość size_ tak, aby odpowiadała rozmiarowi wyświetlacza w bloku.
render_() {
  switch(this.value_.hat) {
    case 'Stovepipe':
      this.stovepipe_.style.display = '';
      break;
    case 'Crown':
      this.crown_.style.display = '';
      break;
    case 'Mask':
      this.mask_.style.display = '';
      break;
    case 'Propeller':
      this.propeller_.style.display = '';
      break;
    case 'Fedora':
      this.fedora_.style.display = '';
      break;
  }

  switch(this.value_.pattern) {
    case 'Dots':
      this.shellPattern_.setAttribute('fill', 'url(#polkadots)');
      break;
    case 'Stripes':
      this.shellPattern_.setAttribute('fill', 'url(#stripes)');
      break;
    case 'Hexagons':
      this.shellPattern_.setAttribute('fill', 'url(#hexagons)');
      break;
  }

  this.textContent_.nodeValue = this.value_.turtleName;

  this.updateSize_();
}

Aktualizowanie rozmiaru

Aktualizowanie size_ pola jest bardzo ważne, ponieważ informuje kod renderowania bloku o tym, jak umieścić pole. Najlepszym sposobem na ustalenie, czym dokładnie powinno być size_, jest przeprowadzenie eksperymentu.

updateSize_() {
  const bbox = this.movableGroup_.getBBox();
  let width = bbox.width;
  let height = bbox.height;
  if (this.borderRect_) {
    width += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
    height += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
    this.borderRect_.setAttribute('width', width);
    this.borderRect_.setAttribute('height', height);
  }
  // Note how both the width and the height can be dynamic.
  this.size_.width = width;
  this.size_.height = height;
}

Dopasowywanie kolorów bloków

Jeśli chcesz, aby elementy pola pasowały do kolorów bloku, do którego są dołączone, zastąp metodę applyColour. Kolor będzie dostępny w atrybucie stylu bloku.

applyColour() {
  const sourceBlock = this.sourceBlock_;
  if (sourceBlock.isShadow()) {
    this.arrow_.style.fill = sourceBlock.style.colourSecondary;
  } else {
    this.arrow_.style.fill = sourceBlock.style.colourPrimary;
  }
}

Aktualizowanie możliwości edytowania

Funkcja updateEditable może służyć do zmiany sposobu wyświetlania pola w zależności od tego, czy można je edytować. Domyślna funkcja sprawia, że tło ma lub nie ma reakcji na najechaniu kursorem (obramowanie), jeśli jest lub nie jest edytowalne. Wyświetlanie w bloku nie powinno zmieniać rozmiaru w zależności od możliwości edycji, ale wszystkie inne zmiany są dozwolone.

updateEditable() {
  if (!this.fieldGroup_) {
    // Not initialized yet.
    return;
  }
  super.updateEditable();

  const group = this.getClickTarget_();
  if (!this.isCurrentlyEditable()) {
    group.style.cursor = 'not-allowed';
  } else {
    group.style.cursor = this.CURSOR;
  }
}

Publikacja w odcinkach

Serializacja polega na zapisywaniu stanu pola, aby można go było później ponownie wczytać do obszaru roboczego.

Stan obszaru roboczego zawsze zawiera wartość pola, ale może też zawierać inne informacje, np. stan interfejsu pola. Jeśli na przykład pole było mapą z możliwością powiększania, która umożliwiała użytkownikowi wybór krajów, możesz też serializować poziom powiększenia.

Jeśli pole jest serializowane, musisz ustawić właściwość SERIALIZABLE na wartość true.

Blockly udostępnia 2 zestawy punktów serializacji pól. Jedna para hooków działa z nowym systemem serializacji JSON, a druga z systemem serializacji XML.

saveStateloadState

saveStateloadState to punkty zaczepienia serializacji, które działają z nowym systemem serializacji JSON.

W niektórych przypadkach nie musisz ich podawać, ponieważ domyślne implementacje będą działać. Jeśli (1) Twoje pole jest bezpośrednią podklasą klasy bazowejBlockly.Field, (2) Twoja wartość jest typem serializowalnym w JSON-ie i (3) musisz tylko serializować wartość, domyślna implementacja będzie działać prawidłowo.

W przeciwnym razie funkcja saveState powinna zwracać obiekt lub wartość, którą można przekształcić w ciąg znaków JSON, reprezentującą stan pola. Funkcja loadState powinna akceptować ten sam obiekt lub wartość, które można serializować do formatu JSON, i stosować je do pola.

saveState() {
  return {
    'country': this.getValue(),  // Value state
    'zoom': this.getZoomLevel(), // UI state
  };
}

loadState(state) {
  this.setValue(state['country']);
  this.setZoomLevel(state['zoom']);
}

Pełna serializacja i tworzenie kopii zapasowych danych

saveState otrzymuje też opcjonalny parametr doFullSerialization. Jest to używane przez pola, które zwykle odwołują się do stanu serializowanego przez inny serializator (np. modele danych zaplecza). Parametr sygnalizuje, że przywoływany stan nie będzie dostępny podczas deserializacji bloku, więc pole powinno samodzielnie przeprowadzić całą serializację. Dotyczy to na przykład sytuacji, gdy poszczególne bloki są serializowane lub gdy blok jest kopiowany i wklejany.

Oto 2 typowe przypadki użycia:

  • Gdy pojedynczy blok zostanie wczytany do obszaru roboczego, w którym nie ma modelu danych bazowych, pole ma wystarczająco dużo informacji w swoim stanie, aby utworzyć nowy model danych.
  • Gdy blok jest kopiowany i wklejany, pole zawsze tworzy nowy model danych zamiast odwoływać się do istniejącego.

Jednym z pól, które z niej korzysta, jest pole wbudowanej zmiennej. Zwykle serializuje identyfikator zmiennej, do której się odwołuje, ale jeśli doFullSerialization ma wartość true, serializuje cały jej stan.

saveState(doFullSerialization) {
  const state = {'id': this.variable_.getId()};
  if (doFullSerialization) {
    state['name'] = this.variable_.name;
    state['type'] = this.variable_.type;
  }
  return state;
}

loadState(state) {
  const variable = Blockly.Variables.getOrCreateVariablePackage(
      this.getSourceBlock().workspace,
      state['id'],
      state['name'],   // May not exist.
      state['type']);  // May not exist.
  this.setValue(variable.getId());
}

Pole zmiennej robi to, aby w przypadku wczytania do obszaru roboczego, w którym nie ma zmiennej, można było utworzyć nową zmienną, do której będzie się odwoływać.

toXmlfromXml

toXmlfromXml to punkty serializacji, które działają ze starym systemem serializacji XML. Używaj tych hooków tylko w razie potrzeby (np.jeśli pracujesz nad starym kodem, który nie został jeszcze zmigrowany). W innych przypadkach używaj saveStateloadState.

Funkcja toXml powinna zwracać węzeł XML reprezentujący stan pola. Funkcja fromXml powinna akceptować ten sam węzeł XML i stosować go do pola.

toXml(fieldElement) {
  fieldElement.textContent = this.getValue();
  fieldElement.setAttribute('zoom', this.getZoomLevel());
  return fieldElement;
}

fromXml(fieldElement) {
  this.setValue(fieldElement.textContent);
  this.setZoomLevel(fieldElement.getAttribute('zoom'));
}

Właściwości, które można edytować i serializować

Właściwość EDITABLE określa, czy pole powinno mieć interfejs wskazujący, że można z nim wchodzić w interakcję. Domyślnie jest to true.

Właściwość SERIALIZABLE określa, czy pole powinno być serializowane. Domyślnie jest to false. Jeśli ta właściwość ma wartość true, może być konieczne podanie funkcji serializacji i deserializacji (patrz Serializacja).

Dostosowywanie za pomocą CSS

Możesz dostosować pole za pomocą CSS. W initViewmetodzie dodaj niestandardową klasę do pola fieldGroup_, a następnie odwołaj się do tej klasy w kodzie CSS.

Aby na przykład użyć innego kursora:

initView() {
  ...

  // Add a custom CSS class.
  if (this.fieldGroup_) {
    Blockly.utils.dom.addClass(this.fieldGroup_, 'myCustomField');
  }
}
.myCustomField {
  cursor: cell;
}

Dostosowywanie kursora

Domyślnie klasy rozszerzające FieldInput używają kursora text, gdy użytkownik najedzie kursorem na pole, przeciągane pola używają kursora grabbing, a wszystkie inne pola używają kursora default. Jeśli chcesz użyć innego kursora, ustaw go za pomocą CSS.