Tworzenie nowego typu pola

Przed utworzeniem nowego typu pola zastanów się, czy jedno z pozostałych aby dostosować pola do swoich potrzeb. Jeśli aplikacja musi przechowywać lub utworzyć nowy interfejs dla istniejącego typu, prawdopodobnie trzeba utworzyć nowy typ pola.

Aby utworzyć nowe pole:

  1. Zaimplementuj konstruktor.
  2. Zarejestruj klucz JSON i zaimplementuj fromJson.
  3. Obsługa inicjowania interfejsu i zdarzenia na blokadzie .
  4. Usuwaj detektory zdarzeń (utylizacja przez interfejs jest obsługiwana w przypadku: Ty).
  5. Zaimplementuj obsługę wartości.
  6. Dodaj tekstowe przedstawienie wartości pola, aby ułatwić korzystanie z niej.
  7. Dodaj dodatkowe funkcje, takie jak:
  8. Skonfiguruj dodatkowe aspekty pola, np.:

W tej sekcji zakładamy, że znasz już treść i znasz treść Składnia Pole.

Przykład pola niestandardowego znajdziesz w sekcji Pola niestandardowe wersja demonstracyjna ,

Wdrażanie konstruktora

Konstruktor pola odpowiada za skonfigurowanie początkowej wartości pola i opcjonalnie lokalnego za pomocą walidatora. Niestandardowy konstruktor pola jest wywoływany podczas inicjowania bloku źródłowego niezależnie czy blok źródłowy jest zdefiniowany w pliku JSON czy w JavaScript. Niestandardowy nie ma dostępu do bloku źródłowego podczas budowy.

Ten 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 pobierają wartość i lokalny walidator. Wartość to opcjonalnie, a jeśli nie przekażesz wartości (lub przekażesz wartość, która nie powiedzie się weryfikacji), zostanie użyta domyślna wartość klasy nadrzędnej. W przypadku atrybutu domyślna klasa Field, ta wartość to null. Jeśli nie chcesz korzystać z domyślnego , należy przekazać odpowiednią wartość. Parametr walidatora to tylko występuje w polach możliwych do edytowania i jest zwykle oznaczony jako opcjonalny. Więcej informacji o walidatorach w walidatorach dokumenty.

Struktura

Logika wewnątrz konstruktora powinna być zgodna z tym schematem:

  1. Wywołaj dziedziczony superkonstruktor (wszystkie pola niestandardowe powinny dziedziczyć z Blockly.Field lub jednej z jej podklas), aby prawidłowo zainicjować wartość i ustaw lokalny walidator dla swojego pola.
  2. Jeśli Twoje pole jest serializowalne, ustaw odpowiednią właściwość w polu za pomocą konstruktora. Pola edytowalne muszą być serializowalne, a pola można edytować więc domyślnie należy ustawić dla tej właściwości wartość „true” (prawda), chyba że wiesz, nie może być serializowalny.
  3. Opcjonalnie: zastosuj dodatkowe dostosowania (np. Pola etykiet). pozwalają na przekazanie klasy CSS, która jest następnie stosowana do tekstu).

JSON i rejestracja

W bloku JSON definicje, pola są opisane ciągiem (np. field_number, field_textinput). Blockly obsługuje mapowanie tych ciągów znaków na obiekty pól i wywołania fromJson na odpowiedni obiekt podczas budowy.

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

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

Musisz również zdefiniować funkcję fromJson. Implementacja powinna najpierw usuń odwołanie do dowolnego ciągu tabela referencje za pomocą replaceMessageReferences, a potem przekazać je do konstruktora.

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

Inicjowanie

Gdy pole jest tworzone, zasadniczo zawiera tylko wartość. Inicjacja to miejsce, w którym tworzony jest DOM, a model jest tworzony (jeśli pole posiada model), a zdarzenia są powiązane.

Wyświetlacz przy zablokowanym ekranie

W trakcie tego procesu odpowiadasz za utworzenie wszystkiego, co będzie Ci potrzebne dla wyświetlania w części blokowej.

Domyślne, tło i tekst

Domyślna funkcja initView tworzy element rect w jasnym kolorze i element text. Jeśli chcesz, aby pole zawierało oba te elementy oraz dodatkowe elementy gadżety, wywołaj funkcję initView superklasy przed dodaniem pozostałych elementów DOM. Jeśli chcesz, aby pole zawierało jedno z nich, ale nie oba elementów, możesz użyć funkcji createBorderRect_ lub createTextElement_.

Dostosowywanie konstrukcji DOM

Jeśli pole jest ogólnym polem tekstowym (np. Tekst Wejście), Konstrukcja DOM zostanie wykonana za Ciebie. W przeciwnym razie musisz zastąpić za pomocą funkcji initView do tworzenia elementów DOM, które będą Ci potrzebne i wyrenderowanie pola w przyszłości.

Na przykład pole menu może zawierać zarówno obrazy, jak i tekst. W języku: initView tworzy pojedynczy element graficzny i pojedynczy element tekstowy. Potem w ciągu render_ pokazuje aktywny element, a drugi ukrywa drugi na podstawie typu wybranej opcji.

Elementy DOM można tworzyć za pomocą Blockly.utils.dom.createSvgElement lub tradycyjnego tworzenia modelu DOM. .

Wymagania dotyczące wyłączonego wyświetlania pola:

  • Wszystkie elementy DOM muszą być elementami podrzędnymi elementu fieldGroup_ pola. Pole jest tworzona automatycznie.
  • Wszystkie elementy DOM muszą mieścić się w raportowanych wymiarach pola.

Zobacz Renderowanie .

Dodawanie symboli tekstowych

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

Zdarzenia wejściowe

Domyślnie pola rejestrują zdarzenia etykietki i zdarzenia kursora myszy (wykorzystywane w przypadku Wyświetlanie redaktorami). Jeśli chcesz nasłuchiwać zdarzeń innego typu (np. przeciągając palcem po polu), musisz zastąpić jego funkcję bindEvents_.

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 ze zdarzeniem, użyj zwykle Blockly.utils.browserEvents.conditionalBind . Ta metoda powiązań odfiltrowuje dodatkowe dotknięcia podczas przeciągnięcia. Jeśli chcesz, aby moduł obsługi uruchamiał się nawet w trakcie przeciągania możesz użyć funkcji Blockly.browserEvents.bind .

Utylizacja

Jeśli zostały zarejestrowane jakiekolwiek niestandardowe detektory zdarzeń w sekcji bindEvents_ pola muszą zostać wyrejestrowane w funkcji dispose.

Jeśli komponent został prawidłowo zainicjowany wyświetl swojego pola (dołączając wszystkie elementy DOM do fieldGroup_), następnie DOM pola zostanie automatycznie usunięty.

Obsługa wartości

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

Kolejność weryfikacji

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

Wdrażanie walidatora klas

W polach powinny być akceptowane tylko określone wartości. Na przykład pola liczbowe powinny być Akceptuj liczby, tylko kolory w polach kolorów. Jest to gwarantowane. na zajęciach lekcyjnych i lokalnych walidatorów. Klasa walidator podlega tym samym zasadom co lokalne walidatorzy, ale jest także uruchamiany w konstruktor, i dlatego nie może odwoływać się do bloku źródłowego.

Aby zaimplementować walidator klas pola, zastąp doClassValidation_ .

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

Obsługa prawidłowych wartości

Jeśli wartość przekazana do pola z atrybutem setValue jest prawidłowa, otrzymasz komunikat doValueUpdate_ oddzwonienie. Domyślnie funkcja doValueUpdate_:

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

Jeśli chcesz po prostu zapisać wartość i nie chcesz niczego dostosowywać, nie musisz zastępować parametru doValueUpdate_.

W przeciwnym razie możesz:

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

Musisz zastąpić ustawienie 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 wartością setValue jest nieprawidłowa, otrzymasz komunikat doValueInvalid_ oddzwonienie. Domyślnie funkcja doValueInvalid_ nic. Oznacza to, że domyślnie nieprawidłowe wartości nie będą wyświetlane. Dodatkowo oznacza, że pole nie zostanie wyrenderowane ponownie, ponieważ 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łowa wartość, ustaw isDirty_. do true i zastąp render_ dla wyświetlacza wyłączonego, aby był aktualizowany na podstawie parametru 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że chcieć, aby części były traktowane jak pojedyncze 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 tym przykładzie każda właściwość newValue jest weryfikowana indywidualnie. Potem na końcu funkcji doClassValidation_, jeśli jakaś pojedyncza właściwość jest jest nieprawidłowa, wartość jest zapisywana w pamięci podręcznej właściwości cacheValidatedValue_ przed zwracanie wartości null (nieprawidłowe). Buforowanie obiektu za pomocą indywidualnej weryfikacji umożliwia doValueInvalid_ obsługi ich oddzielnie, po prostu wykonując !this.cacheValidatedValue_.property, zamiast weryfikować je ponownie z poszczególnych usług.

Tego wzoru do weryfikacji wartości wieloczęściowych można też używać w formatach lokalnych walidatorami, Obecnie nie można wyegzekwować tego wzorca.

isDirty_

isDirty_ to flaga używana w setValue. i innych części pola, aby określić, czy pole musi wyrenderowano ponownie. Jeśli wyświetlana wartość pola uległa zmianie, isDirty_ zwykle powinien ustaw na true.

Tekst

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

Jeśli tekst w polu różni się od wartości w polu, należy zastąp Funkcja getText , aby wpisać właściwy 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 edytora

Jeśli zdefiniujesz funkcję showEditor_, Blockly będzie automatycznie nasłuchiwać kliknięcia i połączenie z numerem showEditor_ w odpowiednim czasie. Możesz wyświetlić dowolny plik HTML w edytorze, dodając do niego jeden z dwóch specjalnych elementów div o nazwie DropDownDiv. i WidgetDiv, które unoszą się nad resztą interfejsu użytkownika Blockly.

DropDownDiv umożliwia dostęp do edytorów, którzy pracują w obrębie skrzynki połączonej do pola. Automatycznie umieszcza się w pobliżu pola, cały czas pozostając w widocznych granicach. Selektor kąta i selektor kolorów to dobre przykłady DropDownDiv.

Obraz selektora kąta

WidgetDiv jest używany do: które nie znajdują się w obrębie skrzynki. W polach liczbowych używane są wartości WidgetDiv, aby uwzględnić pole do wprowadzania tekstu HTML. Choć narzędzie DropDownDiv zajmuje się pozycjonowaniem, natomiast WidgetDiv nie obsługuje. Elementy muszą być: ręcznie ustawić położenie. Układ współrzędnych wyrażony jest we współrzędnych w pikselach w odniesieniu do w lewym górnym rogu okna. Edytor wprowadzania tekstu jest dobrym przykładem funkcji WidgetDiv

Obraz edytora 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);
}

Czyszczenie

Uchwyt DropDownDiv i uchwyt WidgetDiv niszczy kod HTML widżetu elementów, ale musisz ręcznie usunąć wszystkie posiadane detektory zdarzeń 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 w DropDownDiv. Wł. funkcja WidgetDiv jest wywoływana w kontekście obiektu WidgetDiv. W obu przypadkach zalecamy użycie powiąż podczas przekazywania funkcji usuwania, jak pokazano na powyższym przykładzie DropDownDiv i WidgetDiv przykładów.

→ Informacje na temat usuwania niezwiązanych z wycofywaniem redaktorów można znaleźć w Rezygnacja.

Aktualizowanie wyświetlacza blokującego

Funkcja render_ służy do aktualizowania aktywnego wyświetlania pola, aby dopasować swojej wewnętrznej wartości.

Typowe przykłady:

  • Zmiana tekstu (menu)
  • Zmień kolor (kolor)
.

Domyślne

Domyślna funkcja render_ ustawia wyświetlany tekst na wynik funkcji getDisplayText_. . Funkcja getDisplayText_ zwraca właściwość value_ pola jest rzutowana na ciąg znaków po obcięciu w celu zachowania maksymalnej liczby znaków długości.

Jeśli używasz domyślnego wyłączonego wyświetlacza i domyślnego działania tekstu działa w Twoim polu, nie musisz zastępować parametru render_.

Jeśli domyślne działanie tekstu działa w przypadku Twojego pola, ale pole jest zablokowane zawiera dodatkowe elementy statyczne, możesz wywołać domyślną funkcję render_ , ale nadal musisz ją zastąpić, aby zaktualizować rozmiar.

Jeśli domyślne działanie tekstu nie działa w przypadku Twojego pola lub Zawiera on dodatkowe elementy dynamiczne, musisz dostosować render_ .

Schemat blokowy opisujący, jak podjąć decyzję o zastąpieniu reguły renderowania

Dostosowywanie renderowania

Jeśli domyślne renderowanie nie działa w przypadku Twojego pola, konieczne będzie określić niestandardowe zachowanie renderowania. Może to być na przykład ustawienie do wyświetlania tekstu, przez zmianę elementów zdjęcia, po zmienianie kolorów tła.

Wszystkie zmiany atrybutów DOM są zgodne z prawem. Jedyne, o czym należy pamiętać, to:

  1. Tworzenie DOM powinno być realizowane podczas inicjowanie, i zwiększa efektywność.
  2. Należy zawsze zaktualizować size_ .
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_();
}

Aktualizuję rozmiar

Zaktualizowanie właściwości size_ pola jest bardzo ważne, ponieważ dzięki niemu jak umieścić pole. Najlepszy sposób, aby to sprawdzić dokładnie tak powinna wyglądać wartość size_, eksperymentując.

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

Pasujące kolory bloków

Jeśli chcesz, aby elementy pola pasowały do kolorów bloków, musisz zastąpić metodę applyColour. Warto uzyskać dostęp do koloru za pomocą właściwości 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;
  }
}

Aktualizuję możliwość edytowania

Za pomocą funkcji updateEditable można zmienić sposób wyświetlania pola zależnie od tego, czy można go edytować, czy nie. Funkcja domyślna sprawia, że jeśli tło ma lub nie ma opcji najechania kursorem (obramowania), jeśli jest lub nie można jej edytować. Ekran nie powinien zmieniać rozmiaru w zależności od możliwości edycji, 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;
  }
}

Serializacja

Serializacja polega na zapisywaniu swojego pola, aby można było załadować je później do obszaru roboczego.

Stan obszaru roboczego zawsze zawiera wartość pola, ale może też uwzględniać inny stan, np. stan interfejsu użytkownika pola. Jeśli na przykład plik była mapa, którą można powiększać, więc użytkownik mógł wybierać kraje. zserializować również poziom powiększenia.

Jeśli Twoje pole jest serializowalne, musisz ustawić właściwość SERIALIZABLE na true

Blockly udostępnia dwa zestawy punktów zaczepienia serializacji dla pól. 1 para haczyków działa z nowym systemem serializacji JSON, a druga para działa z starego systemu serializacji XML.

saveStateloadState

saveState i loadState to punkty zaczepienia serializacji, które działają z nowym plikiem JSON w systemie serializacji.

W niektórych przypadkach nie trzeba ich podawać, ponieważ domyślnie będą skuteczne. Jeśli (1) pole jest bezpośrednią podklasą podstawy klasa Blockly.Field, (2) Twoja wartość jest serialowalną treścią JSON type i (3) wystarczy zserializować wartość, wówczas implementacja domyślna będzie działać poprawnie.

W przeciwnym razie funkcja saveState powinna zwracać możliwość serializowalności JSON obiekt/wartość reprezentująca stan pola. Oraz loadState funkcja powinna akceptować ten sam zserializowany obiekt/wartość JSON i zastosować ją do w odpowiednim polu.

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 dane kopii zapasowej

Funkcja saveState otrzymuje też opcjonalny parametr doFullSerialization. To jest używane przez pola, które zwykle odwołują się do stanu zserializowanego przez inny serializer (np. zapasowe modele danych). Parametr ten informuje, wskazany stan nie będzie dostępny, gdy blok zostanie deserializowany, więc powinno wykonywać całą serializację. Na przykład dotyczy to sytuacji, pojedynczy blok jest zserializowany lub skopiowany i wklejony.

Są to 2 częste przypadki użycia:

  • Gdy pojedynczy blok jest wczytywany do obszaru roboczego, w którym dane zapasowe model nie istnieje, pole ma wystarczającą ilość informacji w swoim stanie, aby w celu utworzenia nowego modelu danych.
  • Gdy blok jest kopiowany i wklejony, to pole zawsze tworzy nową kopię zapasową model danych zamiast odwoływania się do istniejącego.

Pole, które z niego korzysta, to wbudowane pole zmiennej. Normalnie jest zserializowany identyfikator zmiennej, do której się odwołuje, ale jeśli doFullSerialization ma wartość prawda zserializuje cały swój 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());
}

Za pomocą pola zmiennej dba się o to, aby po wczytaniu do obszaru roboczego jeśli zmienna nie istnieje, może utworzyć nową zmienną, do której będzie się odwoływać.

toXmlfromXml

toXml i fromXml to punkty zaczepienia serializacji, które działają ze starym kodem XML w systemie serializacji. Używaj tych haczyków tylko wtedy, gdy jest to konieczne (np. w starej bazie kodu, która nie została jeszcze przeniesiona), w przeciwnym razie użyj saveState i loadState

Funkcja toXml powinna zwracać węzeł XML reprezentujący stan w odpowiednim polu. A funkcja fromXml powinna akceptować ten sam węzeł XML i stosować swoje umiejętności.

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

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

Edytowalne i serializowalne właściwości

Właściwość EDITABLE określa, czy pole powinno zawierać interfejs wskazujący z którymi można wejść w interakcję. Domyślna wartość to true.

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

Dostosowywanie kursora

Właściwość CURSOR określa kursor, który użytkownicy widzą po najechaniu na niego wskaźnikiem w swoim polu. Powinien to być prawidłowy ciąg kursora CSS. Domyślnym ustawieniem jest kursor. zdefiniowane przez funkcję .blocklyDraggable, czyli kursor myszy.