В библиотеке Shepherd.js селекторы являются ключевым механизмом привязки шагов тура к конкретным элементам интерфейса. Каждый шаг (step) описывает, к какому DOM-элементу он должен «прикрепиться», чтобы подсказка корректно отображалась рядом с нужной частью страницы.
Основное свойство, отвечающее за это — attachTo. Оно
определяет:
attachToСтруктура:
attachTo: {
element: 'селектор',
on: 'позиция'
}
element — CSS-селектор или DOM-элементon — положение подсказки относительно элементаПример:
{
id: 'step-1',
text: 'Это кнопка отправки формы',
attachTo: {
element: '.submit-button',
on: 'bottom'
}
}
Shepherd.js использует стандартные CSS-селекторы, поэтому доступны все привычные варианты:
element: '.menu-item'
element: '#main-header'
element: 'button'
element: '.form-container input[type="email"]'
element: 'li:first-child'
Вместо строки-селектора можно передать уже найденный элемент:
element: document.querySelector('.submit-button')
Преимущества:
Недостаток:
В сложных интерфейсах элементы могут появляться не сразу (например, после AJAX-запроса или открытия модального окна). В таких случаях селектор может быть функцией:
attachTo: {
element: () => document.querySelector('.dynamic-element'),
on: 'right'
}
Это позволяет:
Если элемент не найден, Shepherd.js:
Рекомендуемые подходы:
if (document.querySelector('.target')) {
tour.start();
}
beforeShowPromise{
id: 'step-async',
text: 'Динамический элемент',
attachTo: {
element: '.async-element',
on: 'left'
},
beforeShowPromise: function() {
return new Promise(resolve => {
setTimeout(resolve, 500);
});
}
}
on)Свойство on определяет, где будет отображаться
подсказка:
topbottomleftrighttop-start, bottom-end и
др.Пример:
attachTo: {
element: '.profile-avatar',
on: 'right-start'
}
Если селектор находит несколько элементов:
element: '.item'
Shepherd.js использует первый найденный элемент
(querySelector).
Для выбора конкретного:
element: '.item:nth-child(3)'
или:
element: document.querySelectorAll('.item')[2]
Предпочтительно:
element: '#submit-btn'
Менее надежно:
element: 'button'
Плохо:
element: '.container > div > ul > li:nth-child(2)'
Хорошо:
element: '.menu-item-settings'
Наиболее устойчивый подход:
<button data-tour="submit">Отправить</button>
element: '[data-tour="submit"]'
Преимущества:
В одностраничных приложениях (React, Vue, Angular):
Рекомендации:
element: () => document.querySelector('[data-tour="step1"]')
Запуск тура после рендера:
setTimeout(() => tour.start(), 0);
или через lifecycle-хуки (например, useEffect в
React)
Если элемент находится внутри модального окна:
beforeShowPromisebeforeShowPromise: () => {
return new Promise(resolve => {
openModal();
setTimeout(resolve, 300);
});
}
Если элемент вне зоны видимости:
scrollToНастройка:
scrollTo: true
или более гибко:
scrollTo: {
beh * avior: 'smooth',
block: 'center'
}
element: '.non-existent'
Результат: шаг не отображается корректно
display: none)Shepherd не может корректно позиционировать подсказку
Решение:
beforeShowPromiseЕсли интерфейс меняется:
Полезные методы:
document.querySelector('.selector')
document.querySelector('.selector').style.outline = '2px solid red';
Селекторы в Shepherd.js — это не просто способ найти элемент, а фундамент точного и устойчивого позиционирования шагов тура в реальном интерфейсе.