JavaScript
Flute CMS использует JavaScript для интерактивности. Основные библиотеки: HTMX, jQuery, Notyf.
Подключение скриптов
В теме
Создайте assets/scripts/app.js — он автоматически подключится в макете:
// assets/scripts/app.js
document.addEventListener('DOMContentLoaded', () => {
console.log('Theme loaded');
initMyFeatures();
});
function initMyFeatures() {
// ваш код
}На конкретной странице
@push('scripts')
<script>
document.addEventListener('DOMContentLoaded', () => {
// код для этой страницы
});
</script>
@endpushВнешний файл модуля
@push('scripts')
@at('Modules/Shop/Resources/assets/js/cart.js')
@endpushУведомления (Notyf)
Глобальный объект notyf доступен на всех страницах.
Базовые уведомления
// Успех
notyf.success('Сохранено!');
// Ошибка
notyf.error('Произошла ошибка');Расширенные опции
notyf.open({
type: 'success', // success, error, warning, info
message: 'Сообщение',
duration: 5000, // мс, 0 = не закрывать
dismissible: true, // можно закрыть
position: {
x: 'right', // left, center, right
y: 'top' // top, bottom
}
});Примеры
// После сохранения формы
$('form').on('submit', async function(e) {
e.preventDefault();
try {
await saveData();
notyf.success('Данные сохранены');
} catch (error) {
notyf.error('Ошибка: ' + error.message);
}
});Модальные окна
Открытие/закрытие
// Открыть
openModal('modal-id');
// Закрыть
closeModal('modal-id');Через data-атрибуты
{{-- Открытие --}}
<x-button data-modal-open="my-modal">Открыть</x-button>
{{-- Закрытие изнутри модалки --}}
<x-button data-modal-close="my-modal">Закрыть</x-button>Программно с содержимым
// Открыть модалку и загрузить контент
$('#my-modal .modal-body').load('/api/content', function() {
openModal('my-modal');
});События
// Модалка открыта
window.addEventListener('open-modal', (e) => {
console.log('Opened:', e.detail.modalId);
});
// Модалка закрыта
window.addEventListener('close-modal', (e) => {
console.log('Closed:', e.detail.modalId);
});Tooltips
<!-- Базовый tooltip -->
<button data-tooltip="Подсказка">Наведи</button>
<!-- С позицией -->
<button data-tooltip="Сверху" data-tooltip-placement="top">Наведи</button>
<button data-tooltip="Снизу" data-tooltip-placement="bottom">Наведи</button>
<button data-tooltip="Слева" data-tooltip-placement="left">Наведи</button>
<button data-tooltip="Справа" data-tooltip-placement="right">Наведи</button>
<!-- HTML контент через селектор -->
<button data-tooltip="#tooltip-html">Сложный</button>
<div id="tooltip-html" style="display:none">
<strong>Заголовок</strong>
<p>Описание</p>
</div>Dropdown меню
Базовый
{{-- Кнопка --}}
<button data-dropdown-open="user-menu">
Меню
<x-icon path="ph.regular.caret-down" />
</button>
{{-- Содержимое --}}
<div data-dropdown="user-menu" class="dropdown">
<a href="/profile" class="dropdown__item">
<x-icon path="ph.regular.user" />
Профиль
</a>
<a href="/settings" class="dropdown__item">
<x-icon path="ph.regular.gear" />
Настройки
</a>
<hr class="dropdown__divider">
<a href="/logout" class="dropdown__item dropdown__item--danger">
<x-icon path="ph.regular.sign-out" />
Выйти
</a>
</div>Hover dropdown
<button data-dropdown-open="menu" data-dropdown-hover="true">
Наведи
</button>Подтверждение действий
HTMX подтверждение
<x-button
hx-delete="/api/item/123"
hx-flute-confirm="Удалить этот элемент?"
hx-flute-confirm-type="error"
hx-trigger="confirmed">
Удалить
</x-button>Типы
| Тип | Цвет | Использование |
|---|---|---|
error | Красный | Удаление |
warning | Желтый | Предупреждение |
success | Зеленый | Подтверждение |
info | Синий | Информация |
accent | Accent | Основной |
URL хелпер
// Полный URL
u('/profile') // → https://site.com/profile
u('api/users') // → https://site.com/api/users
u() // → https://site.com/
// Пример использования
fetch(u('api/users'))
.then(r => r.json())
.then(data => console.log(data));Cookie
// Установить cookie
setCookie('theme', 'dark', 365); // на 365 дней
// Получить cookie
const theme = getCookie('theme');
// Удалить cookie
eraseCookie('theme');Переключение темы
// Получить текущую тему
const theme = document.documentElement.getAttribute('data-theme'); // 'light' или 'dark'
// Переключить
const newTheme = theme === 'light' ? 'dark' : 'light';
document.documentElement.setAttribute('data-theme', newTheme);
setCookie('theme', newTheme, 365);
// Или через событие
window.dispatchEvent(new CustomEvent('switch-theme', {
detail: { theme: 'dark' }
}));HTMX
Flute использует HTMX для динамических обновлений без перезагрузки страницы.
Базовые примеры
{{-- GET запрос --}}
<button hx-get="/api/data" hx-target="#result">
Загрузить
</button>
<div id="result"></div>
{{-- POST запрос --}}
<form hx-post="/api/save" hx-target="#result">
<input name="title">
<button type="submit">Сохранить</button>
</form>
{{-- DELETE с подтверждением --}}
<button hx-delete="/api/item/1"
hx-target="closest .item"
hx-swap="outerHTML"
hx-flute-confirm="Удалить?">
Удалить
</button>Навигация без перезагрузки
<a href="/page" hx-boost="true" hx-target="#main" hx-swap="outerHTML transition:true">
Ссылка
</a>Атрибуты
| Атрибут | Описание |
|---|---|
hx-get | GET запрос |
hx-post | POST запрос |
hx-put | PUT запрос |
hx-delete | DELETE запрос |
hx-target | Куда вставить результат |
hx-swap | Как вставить (innerHTML, outerHTML, beforeend…) |
hx-trigger | Когда выполнить (click, change, load…) |
hx-boost | SPA-like навигация |
Реинициализация после HTMX
При динамической подгрузке контента нужно переинициализировать JS:
// После вставки нового контента
htmx.on('htmx:afterSwap', (event) => {
initMyComponents();
initTooltips();
initDropdowns();
});
// После любого запроса
htmx.on('htmx:afterRequest', (event) => {
// обновить счетчики, бейджи и т.д.
});Создание своего модуля
// assets/scripts/my-module.js
class MyModule {
constructor() {
this.init();
}
init() {
this.bindEvents();
}
bindEvents() {
// Делегирование для динамического контента
$(document).on('click', '.my-button', (e) => {
this.handleClick(e);
});
// Реинициализация после HTMX
htmx.on('htmx:afterSwap', () => {
this.refresh();
});
}
handleClick(event) {
event.preventDefault();
const $btn = $(event.currentTarget);
// ...
}
refresh() {
// переинициализация
}
}
// Инициализация
$(document).ready(() => {
window.myModule = new MyModule();
});Глобальные объекты
После загрузки страницы доступны:
app // FluteApp instance
notyf // Notyf (уведомления)
htmx // HTMX
$ // jQueryПолезные функции
// Дождаться загрузки DOM
$(document).ready(() => { });
document.addEventListener('DOMContentLoaded', () => { });
// Делегирование событий (работает с динамическим контентом)
$(document).on('click', '.selector', handler);
// Debounce для поиска
let timeout;
$('#search').on('input', function() {
clearTimeout(timeout);
timeout = setTimeout(() => {
// выполнить поиск
}, 300);
});