Примеры использования модальных окон
Эта страница содержит практические примеры использования модальных окон в различных сценариях.
E-commerce сценарии
1. Быстрый просмотр товара
Создание модального окна для быстрого просмотра товара без перехода на страницу:
<?php
/**
* Добавление кнопки "Быстрый просмотр" к товарам в цикле
*/
add_action('woocommerce_after_shop_loop_item', 'add_quick_view_button');
function add_quick_view_button() {
global $product;
if (!$product) return;
$quick_view_link = \iiko\Modal::create_link('Быстрый просмотр', [
'id' => 'quick_view_' . $product->get_id(),
'title' => $product->get_name(),
'content' => get_quick_view_content($product),
'class' => 'medium',
'link_class' => 'button quick-view-btn'
]);
echo '<div class="quick-view-wrapper">' . $quick_view_link . '</div>';
}
function get_quick_view_content($product) {
ob_start();
?>
<div class="product-quick-view">
<div class="product-image">
<?php echo $product->get_image('medium'); ?>
</div>
<div class="product-details">
<h3><?php echo esc_html($product->get_name()); ?></h3>
<p class="price"><?php echo $product->get_price_html(); ?></p>
<div class="description">
<?php echo wp_kses_post($product->get_short_description()); ?>
</div>
<div class="product-actions">
<?php echo do_shortcode('[add_to_cart id="' . $product->get_id() . '"]'); ?>
<a href="<?php echo esc_url($product->get_permalink()); ?>" class="button view-details">
Подробнее
</a>
</div>
</div>
</div>
<?php
return ob_get_clean();
}2. Модальное окно корзины
Кастомное модальное окно корзины с дополнительной функциональностью:
<?php
/**
* Кастомное модальное окно корзины
*/
add_action('woocommerce_after_mini_cart', 'add_custom_cart_modal');
function add_custom_cart_modal() {
$cart_modal = \iiko\Modal::create([
'id' => 'custom_cart_modal',
'title' => 'Ваша корзина',
'content' => get_custom_cart_content(),
'class' => 'medium',
'display' => false,
'close' => true
]);
}
function get_custom_cart_content() {
ob_start();
?>
<div class="custom-cart-content">
<?php echo do_shortcode('[woocommerce_cart]'); ?>
<div class="cart-extras">
<div class="delivery-info">
<h4>Информация о доставке</h4>
<p>Бесплатная доставка при заказе от 1000 ₽</p>
</div>
<div class="payment-methods">
<h4>Способы оплаты</h4>
<ul>
<li>Наличными при получении</li>
<li>Банковской картой онлайн</li>
<li>СПБ (СБП)</li>
</ul>
</div>
</div>
</div>
<?php
return ob_get_clean();
}3. Модальное окно с вариантами товара
Модальное окно для выбора вариантов товара:
<?php
/**
* Модальное окно выбора вариантов товара
*/
function create_variation_modal($product_id) {
$product = wc_get_product($product_id);
if (!$product || !$product->is_type('variable')) {
return '';
}
$modal = \iiko\Modal::create([
'id' => 'variations_' . $product_id,
'title' => 'Выберите вариант товара',
'content' => get_variations_content($product),
'class' => 'medium',
'display' => false,
'close' => true
]);
return $modal;
}
function get_variations_content($product) {
$variations = $product->get_available_variations();
ob_start();
?>
<div class="variations-modal">
<div class="product-info">
<h3><?php echo esc_html($product->get_name()); ?></h3>
<p class="base-price">Базовая цена: <?php echo $product->get_price_html(); ?></p>
</div>
<div class="variations-list">
<?php foreach ($variations as $variation): ?>
<div class="variation-item" data-variation-id="<?php echo $variation['variation_id']; ?>">
<div class="variation-details">
<h4><?php echo esc_html($variation['attributes']['attribute_pa_size'] ?? 'Стандарт'); ?></h4>
<p class="price"><?php echo wc_price($variation['display_price']); ?></p>
</div>
<button class="select-variation" data-variation="<?php echo $variation['variation_id']; ?>">
Выбрать
</button>
</div>
<?php endforeach; ?>
</div>
<div class="selected-variation-info" style="display: none;">
<h4>Выбранный вариант:</h4>
<div class="selected-details"></div>
<button class="add-to-cart-variation">Добавить в корзину</button>
</div>
</div>
<?php
return ob_get_clean();
}Формы и взаимодействие
4. Форма обратной связи
Модальное окно с формой обратной связи:
<?php
/**
* Модальное окно формы обратной связи
*/
class FeedbackModal {
public static function create_feedback_form() {
$modal = \iiko\Modal::create([
'id' => 'feedback_form',
'title' => 'Обратная связь',
'content' => self::get_feedback_form_html(),
'class' => 'medium',
'display' => false,
'close' => true
]);
return $modal;
}
private static function get_feedback_form_html() {
ob_start();
?>
<form class="feedback-form" id="feedback_form">
<div class="form-group">
<label for="feedback_name">Имя *</label>
<input type="text" id="feedback_name" name="name" required>
</div>
<div class="form-group">
<label for="feedback_email">Email *</label>
<input type="email" id="feedback_email" name="email" required>
</div>
<div class="form-group">
<label for="feedback_phone">Телефон</label>
<input type="tel" id="feedback_phone" name="phone">
</div>
<div class="form-group">
<label for="feedback_subject">Тема</label>
<select id="feedback_subject" name="subject">
<option value="">Выберите тему</option>
<option value="general">Общий вопрос</option>
<option value="order">Вопрос по заказу</option>
<option value="delivery">Доставка</option>
<option value="payment">Оплата</option>
<option value="complaint">Жалоба</option>
<option value="suggestion">Предложение</option>
</select>
</div>
<div class="form-group">
<label for="feedback_message">Сообщение *</label>
<textarea id="feedback_message" name="message" rows="4" required
placeholder="Опишите ваш вопрос или предложение"></textarea>
</div>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" name="agree" required>
<span class="checkmark"></span>
Я согласен с <a href="/privacy-policy" target="_blank">политикой конфиденциальности</a>
</label>
</div>
<button type="submit" class="btn btn-primary">Отправить сообщение</button>
</form>
<div class="feedback-success" style="display: none;">
<div class="success-icon">✓</div>
<h3>Сообщение отправлено!</h3>
<p>Мы свяжемся с вами в ближайшее время.</p>
</div>
<?php
return ob_get_clean();
}
}
// Использование
add_action('wp_footer', function() {
if (is_page('contact') || is_front_page()) {
echo FeedbackModal::create_feedback_form();
}
});5. Модальное окно авторизации
Кастомное модальное окно авторизации:
<?php
/**
* Кастомное модальное окно авторизации
*/
function create_custom_auth_modal() {
if (is_user_logged_in()) {
return '';
}
$modal = \iiko\Modal::create([
'id' => 'custom_auth_modal',
'title' => 'Вход в личный кабинет',
'content' => get_custom_auth_content(),
'class' => 'medium',
'display' => false,
'close' => true
]);
return $modal;
}
function get_custom_auth_content() {
ob_start();
?>
<div class="custom-auth-modal">
<div class="auth-tabs">
<button class="auth-tab active" data-tab="login">Вход</button>
<button class="auth-tab" data-tab="register">Регистрация</button>
</div>
<div class="auth-content">
<!-- Форма входа -->
<div class="auth-form active" id="login-form">
<form class="login-form">
<div class="form-group">
<label for="login_email">Email</label>
<input type="email" id="login_email" name="email" required>
</div>
<div class="form-group">
<label for="login_password">Пароль</label>
<input type="password" id="login_password" name="password" required>
</div>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" name="remember">
<span class="checkmark"></span>
Запомнить меня
</label>
</div>
<button type="submit" class="btn btn-primary">Войти</button>
</form>
<div class="auth-links">
<a href="#" class="forgot-password">Забыли пароль?</a>
</div>
</div>
<!-- Форма регистрации -->
<div class="auth-form" id="register-form">
<form class="register-form">
<div class="form-group">
<label for="register_name">Имя</label>
<input type="text" id="register_name" name="name" required>
</div>
<div class="form-group">
<label for="register_email">Email</label>
<input type="email" id="register_email" name="email" required>
</div>
<div class="form-group">
<label for="register_password">Пароль</label>
<input type="password" id="register_password" name="password" required>
</div>
<div class="form-group">
<label for="register_password_confirm">Подтвердите пароль</label>
<input type="password" id="register_password_confirm" name="password_confirm" required>
</div>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" name="agree_terms" required>
<span class="checkmark"></span>
Я согласен с <a href="/terms" target="_blank">условиями использования</a>
</label>
</div>
<button type="submit" class="btn btn-primary">Зарегистрироваться</button>
</form>
</div>
</div>
</div>
<?php
return ob_get_clean();
}Медиа контент
6. Модальное окно с видео
Модальное окно для отображения видео:
<?php
/**
* Модальное окно с видео
*/
class VideoModal {
public static function create_video_modal($video_id, $title = '', $provider = 'youtube') {
$modal = \iiko\Modal::create([
'id' => 'video_' . $video_id,
'title' => $title ?: 'Видео',
'content' => self::get_video_embed($video_id, $provider),
'class' => 'medium',
'display' => false,
'close' => true
]);
return $modal;
}
private static function get_video_embed($video_id, $provider) {
switch ($provider) {
case 'youtube':
return '<div class="video-container"><iframe src="https://www.youtube.com/embed/' .
esc_attr($video_id) . '?rel=0" frameborder="0" allowfullscreen></iframe></div>';
case 'vimeo':
return '<div class="video-container"><iframe src="https://player.vimeo.com/video/' .
esc_attr($video_id) . '" frameborder="0" allowfullscreen></iframe></div>';
case 'custom':
return '<div class="video-container">' . wp_kses_post($video_id) . '</div>';
default:
return '<div class="video-container">Неподдерживаемый провайдер видео</div>';
}
}
}
// Использование
function add_product_video_button() {
global $product;
if (!$product) return;
$video_id = get_post_meta($product->get_id(), '_product_video_id', true);
$video_provider = get_post_meta($product->get_id(), '_product_video_provider', true);
if ($video_id) {
$video_link = VideoModal::create_link('Смотреть видео', [
'id' => 'product_video_' . $product->get_id(),
'title' => 'Видео: ' . $product->get_name(),
'content' => VideoModal::get_video_embed($video_id, $video_provider),
'link_class' => 'button video-btn'
]);
echo '<div class="product-video">' . $video_link . '</div>';
}
}
add_action('woocommerce_single_product_summary', 'add_product_video_button', 25);7. Галерея изображений
Модальное окно для галереи изображений:
<?php
/**
* Модальное окно галереи изображений
*/
function create_gallery_modal($gallery_images, $title = 'Галерея') {
$modal = \iiko\Modal::create([
'id' => 'gallery_modal',
'title' => $title,
'content' => get_gallery_content($gallery_images),
'class' => 'medium',
'display' => false,
'close' => true
]);
return $modal;
}
function get_gallery_content($gallery_images) {
if (empty($gallery_images)) {
return '<p>Изображения не найдены</p>';
}
ob_start();
?>
<div class="gallery-modal">
<div class="gallery-main">
<img src="<?php echo esc_url($gallery_images[0]['url']); ?>"
alt="<?php echo esc_attr($gallery_images[0]['alt']); ?>"
class="gallery-main-image">
</div>
<div class="gallery-thumbnails">
<?php foreach ($gallery_images as $index => $image): ?>
<div class="gallery-thumb <?php echo $index === 0 ? 'active' : ''; ?>"
data-index="<?php echo $index; ?>">
<img src="<?php echo esc_url($image['sizes']['thumbnail']); ?>"
alt="<?php echo esc_attr($image['alt']); ?>">
</div>
<?php endforeach; ?>
</div>
<div class="gallery-nav">
<button class="gallery-prev" disabled>‹</button>
<span class="gallery-counter">1 из <?php echo count($gallery_images); ?></span>
<button class="gallery-next">›</button>
</div>
</div>
<?php
return ob_get_clean();
}
// Использование для товаров WooCommerce
function add_product_gallery_modal() {
global $product;
if (!$product) return;
$gallery_images = $product->get_gallery_image_ids();
if (!empty($gallery_images)) {
$gallery_data = [];
foreach ($gallery_images as $image_id) {
$gallery_data[] = [
'url' => wp_get_attachment_url($image_id),
'sizes' => [
'thumbnail' => wp_get_attachment_image_url($image_id, 'thumbnail'),
'medium' => wp_get_attachment_image_url($image_id, 'medium'),
'large' => wp_get_attachment_image_url($image_id, 'large')
],
'alt' => get_post_meta($image_id, '_wp_attachment_image_alt', true)
];
}
$gallery_link = \iiko\Modal::create_link('Показать все фото', [
'id' => 'product_gallery_' . $product->get_id(),
'title' => 'Галерея: ' . $product->get_name(),
'content' => get_gallery_content($gallery_data),
'link_class' => 'gallery-link'
]);
echo '<div class="product-gallery-link">' . $gallery_link . '</div>';
}
}
add_action('woocommerce_single_product_summary', 'add_product_gallery_modal', 20);JavaScript для интерактивности
8. AJAX загрузка содержимого
/**
* AJAX загрузка содержимого в модальное окно
*/
class ModalContentLoader {
constructor() {
this.init();
}
init() {
this.bindEvents();
}
bindEvents() {
// Загрузка содержимого по клику
jQuery(document).on('click', '.load-modal-content', this.loadContent.bind(this));
// Обработка форм в модальных окнах
jQuery(document).on('submit', '.modal-form', this.handleFormSubmit.bind(this));
// Закрытие модального окна
jQuery(document).on('click', '.md-close, .md-overlay', this.closeModal.bind(this));
}
loadContent(e) {
e.preventDefault();
const button = jQuery(e.currentTarget);
const modalId = button.data('modal');
const contentUrl = button.data('url');
const loadingText = button.data('loading') || 'Загрузка...';
if (!modalId || !contentUrl) {
console.error('Missing modal ID or content URL');
return;
}
// Показываем модальное окно
jQuery('#' + modalId).addClass('md-show');
// Показываем индикатор загрузки
this.showLoading(modalId, loadingText);
// Загружаем содержимое
jQuery.get(contentUrl, (data) => {
jQuery('#' + modalId + ' .md-content').html(data);
this.hideLoading(modalId);
// Инициализируем загруженный контент
this.initLoadedContent(modalId);
}).fail((xhr, status, error) => {
this.hideLoading(modalId);
this.showError(modalId, 'Ошибка загрузки: ' + error);
});
}
showLoading(modalId, text) {
const modal = jQuery('#' + modalId);
modal.find('.md-content').html(`
<div class="modal-loading">
<div class="spinner"></div>
<p>${text}</p>
</div>
`);
}
hideLoading(modalId) {
jQuery('#' + modalId + ' .modal-loading').remove();
}
showError(modalId, message) {
const modal = jQuery('#' + modalId);
modal.find('.md-content').html(`
<div class="modal-error">
<div class="error-icon">⚠</div>
<h3>Ошибка</h3>
<p>${message}</p>
<button class="button retry-btn">Повторить</button>
</div>
`);
}
initLoadedContent(modalId) {
const modal = jQuery('#' + modalId);
// Инициализируем формы
modal.find('form').each((index, form) => {
this.initForm(jQuery(form));
});
// Инициализируем слайдеры
modal.find('.slider').each((index, slider) => {
this.initSlider(jQuery(slider));
});
// Инициализируем табы
modal.find('.tabs').each((index, tabs) => {
this.initTabs(jQuery(tabs));
});
}
initForm(form) {
form.on('submit', this.handleFormSubmit.bind(this));
// Валидация полей
form.find('input[required], textarea[required]').on('blur', function() {
const field = jQuery(this);
if (!field.val()) {
field.addClass('error');
} else {
field.removeClass('error');
}
});
}
handleFormSubmit(e) {
e.preventDefault();
const form = jQuery(e.currentTarget);
const submitBtn = form.find('button[type="submit"]');
const originalText = submitBtn.text();
// Показываем индикатор отправки
submitBtn.prop('disabled', true).text('Отправка...');
// Собираем данные формы
const formData = new FormData(form[0]);
// Отправляем AJAX запрос
jQuery.ajax({
url: form.attr('action') || window.location.href,
method: 'POST',
data: formData,
processData: false,
contentType: false,
success: (response) => {
this.handleFormSuccess(form, response);
},
error: (xhr, status, error) => {
this.handleFormError(form, error);
},
complete: () => {
submitBtn.prop('disabled', false).text(originalText);
}
});
}
handleFormSuccess(form, response) {
const modal = form.closest('.md-modal');
// Показываем сообщение об успехе
modal.find('.md-content').html(`
<div class="form-success">
<div class="success-icon">✓</div>
<h3>Успешно!</h3>
<p>${response.message || 'Форма отправлена успешно'}</p>
<button class="button close-modal">Закрыть</button>
</div>
`);
// Автоматически закрываем через 3 секунды
setTimeout(() => {
this.closeModal();
}, 3000);
}
handleFormError(form, error) {
// Показываем ошибку
form.find('.form-error').remove();
form.prepend(`
<div class="form-error">
<p>Ошибка: ${error}</p>
</div>
`);
}
closeModal() {
jQuery('.md-modal.md-show').removeClass('md-show');
}
}
// Инициализация
jQuery(document).ready(function() {
new ModalContentLoader();
});CSS стили для примеров
9. Дополнительные стили
/* Стили для модальных окон */
/* Быстрый просмотр товара */
.product-quick-view {
display: flex;
gap: 20px;
}
.product-quick-view .product-image {
flex: 0 0 200px;
}
.product-quick-view .product-image img {
width: 100%;
height: auto;
border-radius: 8px;
}
.product-quick-view .product-details {
flex: 1;
}
.product-quick-view .price {
font-size: 1.2em;
font-weight: bold;
color: #007cba;
margin: 10px 0;
}
.product-quick-view .product-actions {
margin-top: 20px;
display: flex;
gap: 10px;
}
/* Форма обратной связи */
.feedback-form .form-group {
margin-bottom: 20px;
}
.feedback-form label {
display: block;
margin-bottom: 5px;
font-weight: 500;
}
.feedback-form input,
.feedback-form textarea,
.feedback-form select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
}
.feedback-form input:focus,
.feedback-form textarea:focus,
.feedback-form select:focus {
outline: none;
border-color: #007cba;
box-shadow: 0 0 0 2px rgba(0, 124, 186, 0.2);
}
.feedback-form .checkbox-label {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
}
.feedback-form button[type="submit"] {
width: 100%;
padding: 12px;
background: #007cba;
color: white;
border: none;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
transition: background 0.3s;
}
.feedback-form button[type="submit"]:hover {
background: #005a87;
}
/* Галерея изображений */
.gallery-modal {
text-align: center;
}
.gallery-main {
margin-bottom: 20px;
}
.gallery-main-image {
max-width: 100%;
height: auto;
border-radius: 8px;
}
.gallery-thumbnails {
display: flex;
gap: 10px;
justify-content: center;
margin-bottom: 20px;
}
.gallery-thumb {
width: 60px;
height: 60px;
cursor: pointer;
border: 2px solid transparent;
border-radius: 4px;
overflow: hidden;
transition: border-color 0.3s;
}
.gallery-thumb.active {
border-color: #007cba;
}
.gallery-thumb img {
width: 100%;
height: 100%;
object-fit: cover;
}
.gallery-nav {
display: flex;
align-items: center;
justify-content: center;
gap: 20px;
}
.gallery-nav button {
background: #007cba;
color: white;
border: none;
border-radius: 50%;
width: 40px;
height: 40px;
cursor: pointer;
font-size: 18px;
}
.gallery-nav button:disabled {
background: #ccc;
cursor: not-allowed;
}
/* Индикаторы загрузки и ошибок */
.modal-loading,
.modal-error,
.form-success {
text-align: center;
padding: 40px 20px;
}
.modal-loading .spinner {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid #007cba;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.modal-error .error-icon {
font-size: 48px;
color: #dc3545;
margin-bottom: 20px;
}
.form-success .success-icon {
font-size: 48px;
color: #28a745;
margin-bottom: 20px;
}
/* Адаптивность */
@media (max-width: 768px) {
.product-quick-view {
flex-direction: column;
}
.product-quick-view .product-image {
flex: none;
text-align: center;
}
.gallery-thumbnails {
flex-wrap: wrap;
}
.gallery-nav {
flex-direction: column;
gap: 10px;
}
}Заключение
Эти примеры демонстрируют различные способы использования модальных окон в woo2iiko. Они показывают, как создавать интерактивные элементы интерфейса, улучшать пользовательский опыт и интегрировать модальные окна с существующей функциональностью WordPress и WooCommerce.
Для получения дополнительной информации обратитесь к:
- Основной документации по модальным окнам
- API документации
- Руководству по расширению