Авторазмеры контролов

Часто отображение одного контрола зависит от размеров другого, связанного с ним.

Например, полоса прокрутки появляется/уходит с изменением высоты списка. То есть, контейнер списка должен каким-то образом узнавать про изменение высоты списка, чтобы отрисовать или спрятать полосу прокрутки. Таким образом, в задаче изменения размеров и отображения можно выделить два вида контролов.

Контрол-инициатор изменяет собственный размер и, тем самым, инициирует изменение отображения контролов, которые вовлечены в этот процесс. Далее на схемах контрол-инициатор обозначен как ResizeInitiatorControl.

Контрол-наблюдатель отслеживает возможный процесс изменения размера у контрола-инициатора. Определенным образом контрол-наблюдатель должен быть оповещён о происшедших изменениях контрола-инициатора и перестроиться соответствующим образом. Далее на схемах контрол-наблюдатель обозначен как ResizeObserverControl.

В зависимости от уровня вложенности контрола-инициатора, задача изменения размеров и отображения контролов на странице укладывается в реализацию двух возможных схем.

Схема 1. Контрол-инициатор находится на некотором уровне вложенности контрола-наблюдателя

Пример

Изменение размеров списка (контрол-инициатор) влечёт изменение в отображении и в размерах полосы прокрутки в контейнера такого списка (контрол-наблюдатель).

Рис. 1. Списочный контрол является контрол-инициатором. Контейнер списочного контрола является контролом-наблюдателем.

Решение

  1. В этом случае контрол-инициатор оповещает контролы-наблюдатели об изменении размеров. Для этого публикуется всплываемое событие controlResize.
    • JavaScript
      self._notify('controlResize', [], {bubbling: true});
  2. В контролах-наблюдателях, которые должны отреагировать на событие controlResize, создаются обработчики события.
    • WML
      <MyControl on:controlResize="_myHandler()" />

Рис. 2. Оповещение и обработка события controlResize.

Реализация в платформенных контролах

Описанный механизм по умолчанию внедрен в следующих платформенных контролах.

Схема 2: контрол-наблюдатель находится на некотором уровне вложенности контрола-инициатора.

Пример

Документ (ResizeInitiatorControl) изменил ширину, и, соответственно, изменилось отображение хлебных крошек (ResizeObserverControl) в документе.

Рис. 3. Отображение хлебных крошек в зависимости от изменения ширины документа.

Решение

Рис. 4. Оповещение и обработка события controlResize.

  1. В ResizeInitiatorControl помещаем Controls/event:Register (далее по тексту Register) — контрол, регистрирующий все вложенные Controls/event:Listener (далее по тексту Listener) и генерирующий событие об изменении размеров ResizeInitiatorControl.
    • Внимание: Listener регистрируется только у ближайшего Register. При создании собственного Register убедитесь о своевременном оповещении зарегистрированных Listener (см. п.7).
  2. Для Register в опцию register передаём название генерируемого события, например controlResize.
    <!-- WML -->
    <Controls.event:Register
        register="controlResize" /> 
  3. Внутрь Register помещаем ResizeObserverControl.
  4. В ResizeObserverControl помещаем Listener.
  5. В Listener описываем обработчик события.
    Например, на событие controlResize создаётся обработчик _myResizeHandler.
    <!-- WML -->
    <Controls.event:Listener
        event="controlResize"
        on:controlResize="_myResizeHandler()" />
  6. Обработчик этого события объявляем в ResizeObserverControl.
    // JavaScript
    _myResizeHandler: function(event) {
       // Здесь прикладной разработчик пересчитываем размеры и меняет отображение ResizeObserverControl.
       ...
    },
  7. В ResizeInitiatorControl создаём метод, например myControlResize, вызываемый каждый раз при изменении размеров самого ResizeInitiatorControl. В методе для Register вызываем start(), чтобы оповестить зарегистрированные Listener.
    // JavaScript
    myControlResize: function() {
       ...
       myRegister.start();
    }

Реализация в платформенных контролах

Описанный механизм по умолчанию внедрен в следующих платформенных контролах.

Controls/Application при изменении окна браузера оповещает о событии все дочерние контролы, сверху вниз. Таким образом, если стоит задача подписки на событие изменения окна, можно использовать схему 2.