Задержки и ожидание загрузки

Intro.js предоставляет гибкий способ создания интерактивных подсказок для веб-приложений, но часто требуется контролировать момент появления подсказок, особенно если элементы страницы подгружаются динамически. Важнейшие инструменты для этого — свойства delay, обработчики событий и асинхронные проверки состояния элементов.


Использование задержек с помощью delay

Каждый шаг в Intro.js может быть настроен с опцией delay, которая задаёт время в миллисекундах перед показом подсказки:

intro.addStep({
  element: '#button',
  intro: 'Это кнопка запуска.',
  delay: 500 // пауза 500 мс перед отображением подсказки
});

Особенности:

  • delay применяется только к конкретному шагу.
  • Если последовательность шагов автоматически переключается (next), задержка действует перед каждым новым шагом.
  • Можно комбинировать с setTimeout для сложной логики появления.

Асинхронное ожидание загрузки элементов

В реальных веб-приложениях элементы могут загружаться через AJAX или рендериться динамически. Intro.js предлагает использовать обработчик onbeforechange для проверки готовности элемента:

intro.setOptions({
  steps: [
    {
      element: '#dynamic-element',
      intro: 'Элемент загрузился!'
    }
  ]
});

intro.onbeforechange(function(targetElement) {
  return new Promise((resolve) => {
    if (document.querySelector('#dynamic-element')) {
      resolve();
    } else {
      const observer = new MutationObserver(() => {
        if (document.querySelector('#dynamic-element')) {
          observer.disconnect();
          resolve();
        }
      });
      observer.observe(document.body, { childList: true, subtree: true });
    }
  });
});

intro.start();

Ключевые моменты:

  • onbeforechange может возвращать Promise. Подсказка будет показана только после выполнения resolve.
  • Использование MutationObserver позволяет ждать динамически добавленные элементы без постоянного опроса через setInterval.
  • Такой подход гарантирует, что Intro.js не “потеряет” шаги из-за отсутствующих элементов.

Комбинирование delay и асинхронной проверки

Для более точного контроля последовательности шагов удобно комбинировать задержку и проверку готовности:

intro.onbeforechange(function(targetElement) {
  return new Promise((resolve) => {
    function checkAndDelay() {
      const el = document.querySelector('#async-button');
      if (el) {
        setTimeout(resolve, 300); // дополнительная задержка
      } else {
        requestAnimationFrame(checkAndDelay);
      }
    }
    checkAndDelay();
  });
});

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


Использование setTimeout для глобальных пауз

Для вставки задержек между шагами всей последовательности можно использовать событие onafterchange:

intro.onafterchange(function() {
  intro._options.nextStepTimeout = setTimeout(() => {
    intro.nextStep();
  }, 700); // переход к следующему шагу через 700 мс
});

Важно:

  • Это ручной способ управления переходом к следующему шагу.
  • Не рекомендуется использовать одновременно с автоматическим управлением через delay на каждом шаге, чтобы не возникли конфликты.

Практические советы

  1. Для динамических страниц всегда проверять наличие элемента через onbeforechange.
  2. Для сложных анимаций можно использовать delay или собственные Promise с setTimeout.
  3. Не использовать блокирующие циклы (например while) — это заморозит интерфейс.
  4. Объединять MutationObserver и delay для лучшего контроля последовательности подсказок при асинхронной загрузке элементов.

Пример комплексного использования

const intro = IntroJs();

intro.setOptions({
  steps: [
    { element: '#step1', intro: 'Первый шаг' },
    { element: '#step2', intro: 'Второй шаг' },
    { element: '#step3', intro: 'Третий шаг, динамический' }
  ]
});

intro.onbeforechange((target) => {
  if (target.id === 'step3') {
    return new Promise((resolve) => {
      const observer = new MutationObserver(() => {
        if (document.querySelector('#step3')) {
          observer.disconnect();
          setTimeout(resolve, 500); // дополнительная задержка
        }
      });
      observer.observe(document.body, { childList: true, subtree: true });
    });
  }
});

intro.start();

В этом примере шаг #step3 появится только после динамической загрузки элемента и с небольшой паузой для плавного отображения.


Итоговое понимание

  • delay — простой способ добавить паузу перед шагом.
  • onbeforechange + Promise — гарантирует наличие элемента перед показом.
  • MutationObserver — отслеживает динамическую подгрузку элементов без постоянного опроса.
  • Комбинация этих инструментов позволяет точно управлять временем появления подсказок и обеспечивать корректную работу интерактивных туров даже на сложных страницах.