В сложных интерактивных турах далеко не все шаги являются критически важными. Часть из них носит справочный характер, поясняет дополнительные функции интерфейса или предназначена для продвинутых пользователей. В таких случаях возникает необходимость гибкого управления последовательностью — предоставления возможности пропуска отдельных шагов без нарушения логики тура.
Библиотека Intro.js поддерживает несколько подходов к реализации пропуска шагов:
Наиболее простой способ — не включать необязательные шаги в массив
steps.
introJs().setOptions({
steps: [
{
intro: "Добро пожаловать!"
},
{
element: document.querySelector('#main-feature'),
intro: "Основной функционал"
}
// необязательные шаги просто не добавлены
]
});
Такой подход подходит, если заранее известно, какие шаги не нужны. Однако он не обеспечивает гибкости при изменении поведения во время выполнения.
Часто используется логика с флагами, определяющими необходимость отображения шага.
const showAdvanced = false;
const steps = [
{
intro: "Базовое описание"
},
showAdvanced && {
element: document.querySelector('#advanced'),
intro: "Дополнительные возможности"
}
].filter(Boolean);
introJs().setOptions({ steps }).start();
Особенности:
filter(Boolean) удаляет false из
массиваIntro.js предоставляет API для управления переходами между шагами.
goToStepПозволяет перескочить на конкретный шаг:
introJs().goToStep(5);
nextStepМожно вызывать вручную, пропуская текущий шаг:
introJs().nextStep();
Одним из наиболее мощных инструментов является использование событий Intro.js.
onbeforechangeСрабатывает перед отображением шага:
introJs().onbeforechange(function(targetElement) {
if (targetElement.id === 'optional-step') {
this.nextStep();
}
});
Здесь происходит:
В реальных приложениях часто требуется дать пользователю выбор: проходить шаг или пропустить его.
introJs().onafterchange(function() {
const skipBtn = document.createElement('button');
skipBtn.innerText = "Пропустить";
skipBtn.oncl ick = () => {
introJs().nextStep();
};
document.querySelector('.introjs-tooltipbuttons').appendChild(skipBtn);
});
Особенности:
Иногда требуется пропустить не один, а несколько шагов.
introJs().onbeforechange(function(targetElement) {
const skipGroup = ['step-3', 'step-4', 'step-5'];
if (skipGroup.includes(targetElement.id)) {
this.goToStep(6);
}
});
Преимущества:
Пропуск может зависеть от:
const isAdmin = false;
introJs().onbeforechange(function(targetElement) {
if (targetElement.id === 'admin-panel' && !isAdmin) {
this.nextStep();
}
});
Если элемент отсутствует в DOM, шаг становится бесполезным.
introJs().onbeforechange(function(targetElement) {
if (!targetElement) {
this.nextStep();
}
});
Или более явно:
const element = document.querySelector('#dynamic-element');
if (!element) {
// шаг не добавляется
}
Для удобства можно маркировать необязательные шаги прямо в HTML.
<div id="feature" data-optional="true"></div>
introJs().onbeforechange(function(targetElement) {
if (targetElement.dataset.optional === "true") {
this.nextStep();
}
});
Иногда шаг должен отображаться только один раз.
const seenSteps = new Set();
introJs().onbeforechange(function(targetElement) {
if (seenSteps.has(targetElement.id)) {
this.nextStep();
} else {
seenSteps.add(targetElement.id);
}
});
Для сохранения выбора пользователя используется
localStorage.
const skipAdvanced = localStorage.getItem('skipAdvanced') === 'true';
introJs().onbeforechange(function(targetElement) {
if (targetElement.id === 'advanced' && skipAdvanced) {
this.nextStep();
}
});
Запись значения:
localStorage.setItem('skipAdvanced', 'true');
Можно управлять шагами централизованно:
function createSteps(options) {
const steps = [
{ intro: "Начало" }
];
if (options.includeAdvanced) {
steps.push({
element: '#advanced',
intro: "Расширенные функции"
});
}
return steps;
}
introJs().setOptions({
steps: createSteps({ includeAdvanced: false })
});
Важно учитывать поведение при переходе назад:
introJs().onbeforechange(function(targetElement) {
const skipped = ['step-3'];
if (skipped.includes(targetElement.id)) {
this.nextStep();
}
});
Без дополнительной логики шаг может снова появиться при возврате.
Бесконечный цикл переходов
this.nextStep();
Если условие всегда истинно — произойдет зацикливание.
Неверная индексация шагов
Метод goToStep использует индексацию с 1, а не с 0.
Отсутствие проверки элемента
Попытка пропуска без проверки может вызвать ошибки:
if (!targetElement) return;
onbeforechange) как основной
механизм контроляОбучающие туры:
Административные панели:
Адаптивные интерфейсы:
Персонализация:
Наиболее эффективный вариант — сочетание методов:
const steps = getSteps().filter(step => !step.optional);
introJs()
.setOptions({ steps })
.onbeforechange(function(targetElement) {
if (shouldSkip(targetElement)) {
this.nextStep();
}
})
.start();
Такой подход обеспечивает: