Обновление целевых элементов

Driver.js предоставляет возможность динамического выделения элементов интерфейса с помощью последовательностей шагов (steps). Иногда возникает необходимость обновлять целевые элементы на лету, например, если DOM изменяется после первоначальной инициализации тура. Для этого библиотека предлагает несколько подходов, позволяющих изменять или переопределять селекторы элементов без пересоздания Driver.


Использование метода defineSteps

Метод defineSteps позволяет полностью задать или обновить последовательность шагов после создания экземпляра Driver:

const driver = new Driver();

driver.defineSteps([
  {
    element: '#newButton',
    popover: {
      title: 'Новая кнопка',
      description: 'Эта кнопка появилась после AJAX-загрузки',
      position: 'bottom'
    }
  },
  {
    element: '.updatedSection',
    popover: {
      title: 'Обновлённый раздел',
      description: 'Секция была динамически заменена',
      position: 'left'
    }
  }
]);

driver.start();

Ключевой момент: defineSteps полностью заменяет старые шаги на новые, что удобно при динамическом формировании интерфейса.


Обновление конкретного шага

Если нужно изменить только один шаг, Driver.js позволяет получить доступ к шагам через driver.steps и вручную модифицировать объект шага:

driver.steps[1].element = '#dynamicSection';
driver.steps[1].popover.title = 'Обновлённая секция';
driver.steps[1].popover.description = 'Контент изменился';

После этого при следующем показе этого шага будет использоваться новый элемент и новые данные.

Важно: прямое изменение элементов работает только до вызова driver.start(). Если тур уже запущен, требуется рестарт текущего шага с помощью driver.reset() или driver.stop() + driver.start().


Динамическое создание элементов на лету

Driver.js умеет работать с селекторами, которые могут появиться в DOM только после выполнения асинхронных операций. Для этого полезно использовать проверку существования элемента перед вызовом driver.start() или отдельного шага:

function waitForElement(selector, timeout = 3000) {
  return new Promise((resolve, reject) => {
    const start = Date.now();
    const check = () => {
      const el = document.querySelector(selector);
      if (el) resolve(el);
      else if (Date.now() - start > timeout) reject('Элемент не найден');
      else requestAnimationFrame(check);
    };
    check();
  });
}

waitForElement('#lazyButton').then(() => {
  driver.defineSteps([{
    element: '#lazyButton',
    popover: {
      title: 'Поздно загруженная кнопка',
      description: 'Эта кнопка появилась после загрузки данных',
      position: 'top'
    }
  }]);
  driver.start();
});

Преимущество: шаги будут корректно работать даже если элементы создаются динамически после рендера страницы.


Изменение позиции и размеров элементов

Driver.js автоматически вычисляет позицию popover на основе текущего местоположения целевого элемента. Если элемент обновился по размеру или сместился, можно принудительно пересчитать позицию:

driver.reposition();

Метод reposition обновляет координаты текущего шага и гарантирует, что popover останется на правильной позиции. Это особенно полезно после анимаций или изменения DOM.


Обновление элементов без перезапуска тура

В сложных интерфейсах тур может работать непрерывно, а целевые элементы заменяются или исчезают. В этом случае логика обновления шагов может быть такой:

function updateStepElement(stepIndex, newSelector) {
  const step = driver.steps[stepIndex];
  if (!document.querySelector(newSelector)) return;
  step.element = newSelector;
  if (driver.activeStep === stepIndex) {
    driver.reposition();
  }
}

// пример использования
updateStepElement(0, '#newDynamicElement');

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


Советы по управлению динамическими элементами

  • Использовать селекторы, которые уникально идентифицируют элемент, иначе Driver.js может подсветить неверный элемент.
  • Для элементов, создаваемых асинхронно, использовать отложенную инициализацию шагов через Promise или события MutationObserver.
  • Не менять DOM элементов, которые уже подсвечены Driver.js, без вызова reposition(), иначе popover может оказаться неправильно расположен.
  • Для сложных интерфейсов с часто обновляемыми элементами рекомендуется хранить фабрику шагов, которая динамически возвращает актуальный селектор и контент.

Итоговые методы и свойства для обновления целевых элементов

Метод/Свойство Назначение
defineSteps(steps) Полностью задаёт или обновляет все шаги
driver.steps Массив шагов для прямого изменения конкретного шага
driver.reposition() Пересчёт позиции popover относительно элемента
driver.reset() Сброс текущего состояния тура для повторного старта
activeStep Индекс текущего шага, для которого можно обновлять элемент

Эти инструменты позволяют создавать динамические, интерактивные туры, где элементы интерфейса могут меняться, а подсветка и popover остаются актуальными.