Обновить настраиваемое поле

В июле 2019 года ( выпуск 2.20190722 ) был добавлен более систематизированный API для работы с полями. Он призван обеспечить максимальную обратную совместимость. Это означает, что если вы создали настраиваемое поле до июля 2019 года, оно, скорее всего, продолжит работать. Прежде чем решить, нужно ли обновлять настраиваемое поле, ознакомьтесь с разделом « Опасные зоны» и тщательно протестируйте его.

Из-за отсутствия стандартизации между областями до июля 2019 года сложно охватить все изменения, которые может потребоваться внести разработчику. В этом документе рассматриваются все возможные изменения, но если в нём нет информации о том, что вас интересует, ознакомьтесь с разделом о получении помощи с обновлением .

Опасные зоны

Опасные зоны — это известные места, где API изменился, и ваше поле может быть сломано.

Blockly.Field.register

Поля больше не регистрируются через Blockly.Field.register(); Теперь для регистрации используется пространство имён fieldRegistry .

Blockly.Field.register('my_field_name', myFieldClass);

Становится:

Blockly.fieldRegistry.register('my_field_name', myFieldClass);

setText

Функция setText больше не вызывается ядром Blockly, поэтому, если ваша функция setText содержит логику, ее необходимо переместить в набор функций обработки значений , функцию getText и функции рендеринга (в зависимости от того, что именно делает ваша функция setText ).

CustomFields.UpgradeField.prototype.setText = function(newText) {
  // Do validation.
  if (typeof newText != 'string' || newText === this.text_) {
    return;
  }

  // Fire event.
  if (this.sourceBlock_ && Blockly.Events.isEnabled()) {
    Blockly.events.fire(new Blockly.Events.BlockChange(
        this.sourceBlock_, 'field', this.name, this.text_, newText
    ));
  }

  // Update text value.
  this.text_ = 'prefix' + newText;

  // Rerender.
  this.size_.width = 0;
};

Становится:

CustomFields.UpgradeField.prototype.doClassValidation_ = function(newValue) {
  if (typeof newValue != 'string') {
    return null;
  }
  return newValue;
};

CustomFields.UpgradeField.prototype.getText = function() {
  return  'prefix' + this.value_;
}

Blockly автоматически обрабатывает:

  • Проверка того, отличается ли новое значение от старого.
  • Обновление значения.
  • Запуск событий изменения.
  • Повторная визуализация поля.

Вам необходимо будет справиться с:

Рекомендуемые обновления касаются случаев, когда API поля был изменен, но если вы решите не вносить изменения, ваше поле, скорее всего, все равно будет работать.

СЕРИАЛИЗУЕМЫЙ

Дополнительные сведения о свойствах EDITABLE и SERIALIZABLE см. в разделе Редактируемые и сериализуемые свойства .

CustomFields.UpgradeField.prototype.SERIALIZABLE = true;

Предупреждение ниже можно игнорировать, но его можно устранить, определив свойство SERIALIZABLE :

Detected an editable field that was not serializable. Please define
SERIALIZABLE property as true on all editable custom fields. Proceeding
with serialization.

Предупреждение выше означает, что Blockly считает, что вы хотите сериализовать поле (поскольку свойство EDITABLE имеет значение true), но не может быть уверен в этом, пока вы не определите свойство SERIALIZABLE . Если вы оставите это без изменений, всё будет работать корректно, и ваше поле будет сериализовано, но вы получите предупреждения в консоли.

размер_.ширина

this.size_.width = 0;

Становится:

this.isDirty_ = true;

Предупреждение ниже можно игнорировать, но его можно устранить, установив свойство isDirty_ вместо свойства size_.width :

Deprecated use of setting size_.width to 0 to rerender a field. Set
field.isDirty_ to true instead.

Предупреждение выше означает, что Blockly обнаружил, что вы используете старый метод повторной обработки поля, и предлагает вам использовать новый метод.

Дополнительную информацию о свойстве isDirty_ см. в разделе isDirty_ .

инициализация

Функция init была преобразована в шаблонную функцию для уменьшения дублирования кода в подклассах.

CustomFields.UpgradeField.prototype.init = function() {
  if (this.fieldGroup_) {
    // Already initialized once.
    return;
  }

  // Call superclass.
  CustomFields.UpgradeField.superClass_.init.call(this);

  // Create DOM elements.
  this.extraDom_ = Blockly.utils.dom.createSvgElement('image',
      {
        'height': '10px',
        'width': '10px'
      });
  this.extraDom_.setAttributeNS('http://www.w3.org/1999/xlink',
      'xlink:href', 'image.svg');
  this.extraDom_.style.cursor = 'pointer';
  this.fieldGroup_.appendChild(this.extraDom_);

  // Bind events.
  this.mouseOverWrapper_ =
    Blockly.browserEvents.bind(
        this.getClickTarget_(), 'mouseover', this, this.onMouseOver_);
  this.mouseOutWrapper_ =
    Blockly.browserEvents.bind(
        this.getClickTarget_(), 'mouseout', this, this.onMouseOut_);

  // Render.
  this.setValue(this.getValue());
};

Становится:

CustomFields.UpgradeField.prototype.initView = function() {
  CustomFields.UpgradeField.superClass_.initView.call(this);

  this.extraDom_ = Blockly.utils.dom.createSvgElement('image',
      {
        'height': '10px',
        'width': '10px'
      });
  this.extraDom_.setAttributeNS('http://www.w3.org/1999/xlink',
      'xlink:href', 'image.svg');
  this.extraDom_.style.cursor = 'pointer';
  this.fieldGroup_.appendChild(this.extraDom_);
};

CustomFields.UpgradeField.prototype.bindEvents_ = function() {
  CustomFields.UpgradeField.superClass_.bindEvents_.call(this);

  this.mouseOverWrapper_ =
    Blockly.bindEvent_(
        this.getClickTarget_(), 'mouseover', this, this.onMouseOver_);
  this.mouseOutWrapper_ =
    Blockly.bindEvent_(
        this.getClickTarget_(), 'mouseout', this, this.onMouseOut_);
};

Это означает, что Blockly теперь автоматически обрабатывает:

  • Проверка того, инициализировано ли поле.
  • Создание fieldGroup_ .
  • Визуализация поля.
  • Привязка подсказок и событий редактора показа.

Вам необходимо будет справиться с:

onMouseDown_

CustomFields.UpgradeField.prototype.onMouseDown_ = function(e) {
  // ...
};

Становится:

CustomFields.UpgradeField.prototype.showEditor_ = function() {
  // ...
}

Мы рекомендуем вам переопределить функцию showEditor_ для обработки щелчков мыши, а не функцию onMouseDown_ , поскольку это позволяет передавать входные данные через систему жестов.

Более подробную информацию о редакторах см. в разделе Редакторы .

setValue

Функция setValue теперь является шаблонной функцией для уменьшения дублирования кода в подклассах. Если ваша функция setValue содержит логику, рассмотрите возможность её рефакторинга в соответствии с путями обработки значений, описанными в разделе Обработка значений .

текст_

Мы рекомендуем никогда не обращаться к свойству text_ поля напрямую и не обновлять его. Вместо этого используйте функцию getText для доступа к тексту поля, доступному для чтения пользователем, и функцию setValue для обновления сохранённого значения поля.

Дополнительную информацию о значении поля и его тексте см. в разделе Анатомия поля .

Получение помощи по обновлению

Что предоставить

Обращаясь за помощью, лучше всего задавать конкретные вопросы:

Не рекомендуется: «Что не так с этим полем?»

Также не рекомендуется: «Помогите мне обновить это поле».

Рекомендуется: «Текст поля обновляется неправильно».

Также необходимо предоставить ресурсы тем, кто вам помогает. Эти файлы должны быть простыми в использовании.

Не рекомендуется:

  • Изображения кода.
  • Неполный код.

Рекомендуется:

  • Полный код поля в текстовом формате.
  • Изображения gif плохого поведения поля.
  • Действия по воспроизведению плохого поведения поля.
  • Версия Blockly, с которой вы выполняете обновление.

Где разместить

Вопросы по обновлению можно задать на форуме разработчиков Blockly .

Если вы уверены, что проблема связана с ядром Blockly, вы также можете опубликовать сообщение об ошибке на GitHub Blockly. Если вы решите опубликовать сообщение об ошибке, пожалуйста, заполните всю необходимую информацию.