Условные переходы

Shepherd.js предоставляет мощные возможности для создания интерактивных пошаговых туров на веб-странице. Одной из таких возможностей являются условные переходы, которые позволяют изменять логику следования шагов в зависимости от действий пользователя или состояния приложения.

Определение и синтаксис условных переходов

В Shepherd.js условные переходы реализуются через функции обратного вызова и условные параметры в конфигурации шага. Основные механизмы:

  1. when и beforeShowPromise

    • beforeShowPromise — промис, который выполняется перед отображением шага. Можно использовать для проверки условий и динамического изменения шага.
    • Пример использования:
tour.addStep({
  id: 'step-conditional',
  text: 'Этот шаг появится только если выполнено условие',
  beforeShowPromise: function() {
    return new Promise((resolve, reject) => {
      if (window.userLoggedIn) {
        resolve();
      } else {
        reject(); // шаг не отображается
      }
    });
  }
});
  1. Динамический выбор следующего шага через advanceOn

    • Свойство advanceOn позволяет автоматически переходить к следующему шагу при наступлении определённого события.
    • Можно использовать для условного перехода, комбинируя с логикой внутри обработчика:
tour.addStep({
  id: 'step-advance',
  text: 'Выберите действие, чтобы перейти',
  attachTo: { element: '#button', on: 'bottom' },
  advanceOn: {
    selector: '#button',
    event: 'click',
    condition: () => window.hasPermission // условие перехода
  }
});
  1. Методы tour.next() и tour.back() с проверками

    • Внутри обработчиков событий можно вызывать tour.next() только при выполнении определённых условий:
document.querySelector('#nextBtn').addEventListener('click', () => {
  if (formIsValid()) {
    tour.next();
  } else {
    alert('Сначала заполните форму');
  }
});

Использование логики ветвления

Shepherd.js позволяет создавать ветвления, где один шаг может вести к разным следующим шагам в зависимости от состояния:

tour.addStep({
  id: 'step-choice',
  text: 'Выберите путь',
  buttons: [
    {
      text: 'Путь А',
      action: () => tour.show('stepA')
    },
    {
      text: 'Путь B',
      action: () => tour.show('stepB')
    }
  ]
});

tour.addStep({
  id: 'stepA',
  text: 'Вы выбрали путь А'
});

tour.addStep({
  id: 'stepB',
  text: 'Вы выбрали путь B'
});

Ключевой момент: метод show(stepId) позволяет перепрыгивать на любой шаг вне стандартного линейного порядка.

Динамическая модификация шагов

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

tour.addStep({
  id: 'step-dynamic',
  text: 'Стартовый текст',
  buttons: [
    {
      text: 'Далее',
      action: () => tour.next()
    }
  ],
  beforeShowPromise: function() {
    return new Promise((resolve) => {
      if (userHasPremium) {
        this.updateStepOptions({
          text: 'Вы обладаете премиум-доступом! Продолжаем тур.',
          buttons: [
            { text: 'Следующий шаг', action: () => tour.show('premiumStep') }
          ]
        });
      }
      resolve();
    });
  }
});

Реализация сложных сценариев

  1. Проверка состояния приложения перед каждым шагом

    • Использовать beforeShowPromise для динамического отображения шагов.
    • Состояние может храниться в глобальных переменных, Redux store или контексте приложения.
  2. Выбор шага на основе пользовательского ввода

    • Кнопки с разными action() позволяют создавать интерактивные ветвления.
    • Комбинировать с логикой в beforeShowPromise для более гибкой адаптации тура под пользователя.
  3. Пропуск шагов

    • Если шаг не удовлетворяет условию, можно просто не вызывать resolve(), или сразу вызывать tour.next() для пропуска.

Советы по организации условных переходов

  • Для читаемости и поддержки кода рекомендуется разбивать тур на модули или отдельные функции, особенно если ветвлений много.
  • Все динамические проверки лучше оформлять через отдельные функции, возвращающие булевы значения.
  • Для отладки полезно временно логировать вызовы beforeShowPromise и action() кнопок, чтобы видеть, какие условия выполняются.

Пример комплексного условного тура

const tour = new Shepherd.Tour({ defaultStepOptions: { cancelIcon: { enabled: true } } });

tour.addStep({
  id: 'welcome',
  text: 'Добро пожаловать!',
  buttons: [{ text: 'Далее', action: () => tour.next() }]
});

tour.addStep({
  id: 'user-check',
  text: 'Проверка доступа...',
  beforeShowPromise: function() {
    return new Promise((resolve) => {
      if (window.userRole === 'admin') {
        this.updateStepOptions({ text: 'Вы администратор, продолжим!' });
        resolve();
      } else {
        tour.show('guest-step');
      }
    });
  }
});

tour.addStep({
  id: 'guest-step',
  text: 'Вы обычный пользователь, ограничения применены',
  buttons: [{ text: 'Завершить тур', action: () => tour.complete() }]
});

tour.start();

В этом примере реализован ветвящийся тур, где следующий шаг выбирается на основе роли пользователя, а шаги динамически модифицируются с использованием updateStepOptions() и beforeShowPromise.

Заключение по подходам

Использование условных переходов в Shepherd.js позволяет создавать адаптивные интерактивные туры, гибко реагирующие на состояние приложения и действия пользователя. Основные инструменты: beforeShowPromise, advanceOn, tour.show(stepId) и динамическая модификация шагов через updateStepOptions(). Их комбинация обеспечивает построение туров любой сложности, включая ветвления, пропуски шагов и интерактивные выборы.