Форма регистрации в модальном окне Bootstrap / Формы / Сниппеты Bootstrap | BootstrapТема

Почему следует использовать модальность?

Модальные экраны решают простую проблему. И состоит она в следующем — пользователи легко отвлекаются, поэтому иногда приходится привлекать их полное внимание на какой-то определенный блок информации (

). Модальный экран делает именно это — требует, чтобы люди сосредоточились на одной задаче, прежде чем продолжить работу в основном потоке приложения.

«Модальность создает фокусировку, не давая людям заниматься другими делами, прежде чем они не завершат задачу или не отклонят вызванное в модальном окне представление» — Apple

<dialog>

Для различных диалогов, уведомлений и прочих перекрывающих документ элементов существует тег <dialog>. Его вы и должны использовать. К огромному сожалению, его поддержка не самая лучшая:

Так что для этих браузеров нужно подгружать polyfill:

if (!document.createElement('dialog').showModal) {
  // Браузер нативно не поддерживает элемент dialog

  import('/dist/dialog-polyfill.js') // Подгружаем polyfill
    .then(dialogPolyfill =>
      document.querySelectorAll('dialog')
        .forEach(dialogPolyfill.registerDialog) // Применяем его для всех элементов на странице
    )
}

Вы, конечно, можете использовать и другой элемент для реализации диалогового окна, например так:

но тогда вам придётся самостоятельно реализовывать всё поведение описанное далее. В то время как с <dialog> большую часть браузер реализует из коробки.

Dispose

Уничтожает элемент модальное окно. (Удаляет сохраненные данные в элементе DOM)

Getinstance

Статический метод, позволяющий получить модальный экземпляр, связанный с элементом DOM.

Getorcreateinstance

Статический метод, который позволяет вам получить модальный экземпляр, связанный с элементом DOM, или создать новый, если он не был инициализирован.

Handleupdate

Вручную скорректируйте положение модального окна, если высота модального окна изменяется, пока он открыт (то есть в случае появления полосы прокрутки).

Json ответы от devise

В геме

devise

за ошибки связанные со входом отвечает

. При возникновении ошибки в

SessionsController

‘е, который отрабатывает запросы на вход, вызывается

, где с помощью

Passing options

Активирует Ваш контент как модальное окно. Принимает необязательные параметры object.

Toggle

Вручную переключает модальное окно. Возврат к вызывающей стороне до того, как модальное окно было фактически показано или скрыто (т.е. до того, как произойдет событие shown.bs.modal или hidden.bs.modal).

W3.css modal

Модальное окно всегда отображается поверх текущей страницы.

W3.CSS включает в себя следующие классы:

КлассОпределение
w3-modalМодальный контейнер
w3-modal-contentСодержимое модального окна

В качестве содержимого модального окна может быть использован любой HTML-элемент (блок div, header, абзац, изображение, и т.д.).

Пример:

Посмотреть демо

Чтобы открыть модальное окно на CSS, можно использовать любой HTML-элемент. Чаще всего это кнопка или ссылка. Добавьте атрибут onclick и укажите идентификатор модального окна (в нашем примере это id01), используя метод document.getElementById().

Чтобы закрыть модальное окно, добавьте класс w3-closebtn к элементу с атрибутом onclick, указывающим на идентификатор модального окна (id01). Также можно закрыть модальное окно, кликнув мышкой за его пределами (смотрите пример, приведенный ниже).

Совет: значок (;) представляет собой HTML-объект, который более предпочтителен для использования в качестве кнопки закрытия, чем буква “х”.

Используйте классы w3-container для создания различных разделов внутри модального контента:

Пример:

Посмотреть демо

Чтобы отобразить модальное окно как карточку, добавьте класс w3-card- * к контейнеру w3-modal-content:

Пример:

Посмотреть демо

Используйте любой из классов w3-animate-zoom|top|bottom|right|left,чтобы при открытии модальное окно двигалось в определенном направлении:

Пример:

Посмотреть демо

Кроме этого можно сделать так, чтобы модальное окно JavaScript постепенно появилось на заднем фоне, добавив класс w3-animate-opacity в элемент с классом w3-modal.

Пример:

Посмотреть демо

Пример:

Посмотреть демо

Пример:

Посмотреть демо

В этом примере создается форма обратной связи в модальном окне:

Пример

В этом примере создается модальное окно с вкладками.

Пример

В приведенных выше примерах мы используем кнопку, чтобы закрыть модальное окно. Однако применив JavaScript, можно закрыть модальное окно, кликнув мышкой за его пределами:

Пример:

Посмотреть демо

Расширение: Lightbox (модальная галерея изображений)

Этот пример показывает, как добавить слайд-шоу в модальные окна, чтобы создать Lightbox:

Посмотреть демо

Дайте знать, что вы думаете по этой теме в комментариях. За комментарии, подписки, отклики, дизлайки, лайки низкий вам поклон!

Внутри диалога

Особенность модального окна в том, что оно перекрывает собой весь документ не давая возможность с ним взаимодействовать.

Чтобы блокировать указатель обычно документ накрывается полупрозрачным блоком.

Но этого недостаточно, так как остаётся ещё и навигация клавишами Tab / Shift Tab. Также это могут быть клавиши громкости на смартфонах или специальные клавиши на дополнительных инструментах подключенных по USB/Bluetooth. Этот способ навигации тоже должен быть заблокирован.

После попадания фокуса в модальное окно пользователь может перебирать интерактивные элементы внутри этого окна, но не должен выходить за его пределы. Другими словами, такое диалоговое окно работает как ловушка для фокуса. Это поведение встроено в <dialog>, так что от вас никаких действий не требуется. А вот используя другой элемент с role=”dialog” его нужно реализовывать самостоятельно средствами JavaScript.

Всплывающие подсказки и всплывающие окна

Всплывающие подсказки и всплывающие подсказки могут быть помещены в модальные окна по мере необходимости. Когда модальные окна закрываются, любые всплывающие подсказки и всплывающие окна также автоматически закрываются.

Запустите демо модального окна

Динамические высоты

Если высота модального окна изменяется, пока он открыт, Вы должны вызвать myModal.handleUpdate(), чтобы скорректировать положение модального окна в случае появления полосы прокрутки.

Дополнительные размеры

Модальные окна имеют три необязательных размера, доступных через классы модификаторов, которые помещаются в .modal-dialog. Эти размеры действуют в определенных контрольных точках, чтобы избежать горизонтальных полос прокрутки на более узких окнах просмотра.

Наш модальный класс по умолчанию без модификатора представляет собой модальное окно «среднего» размера.

Очень большое модальное окно

Доступность

Не забудьте добавить aria-labelledby=”…”, ссылаясь на Заголовок модального окна, в .modal. Кроме того, Вы можете дать описание Вашего модального диалога с помощью aria-describedby в .modal. Обратите внимание, что Вам не нужно добавлять role=”dialog”, поскольку мы уже добавляем его через JavaScript..

Живая демонстрация

Переключите рабочую модальную демонстрацию, нажав кнопку ниже. Он будет скользить вниз и исчезать из верхней части страницы.

Запустите демо модального окна

Заголовок обязателен

У модального окна, как у любой обычной страницы, должен быть свой заголовок. Короткий, точно описывающий его предназначение. Наличие заголовка намного упрощает восприятие пользователем.

Настоятельно рекомендуется использовать для заголовка тег <h1>-<h6>.

Но просто добавить заголовок в диалоговое окно недостаточно. Их нужно ещё и логически “связать”. Сделать это можно с помощью атрибута aria-labelledby следующим образом:

Теперь, при попадании пользователя в диалоговое окно, в случае с экранным диктором, будет зачитан не только факт наличия диалога, но и его заголовок.

Изменение анимации

Переменная $modal-fade-transform определяет состояние преобразования .modal-dialog перед модальной плавной анимацией, переменная $modal-show-transform определяет преобразование .modal-dialog в конец модальной плавной анимации.

Если Вам нужна, например, анимация с увеличением, Вы можете установить $modal-fade-transform: scale(.8).

Изменяющееся модальное содержимое

У Вас есть несколько кнопок, которые запускают одно и то же модальное окно с немного разным содержимым? Используйте event.relatedTarget и HTML data-* атрибуты, чтобы изменять содержимое модального окна в зависимости от какая кнопка была нажата.

Ниже представлена живая демонстрация, за которой следуют примеры HTML и JavaScript. Для получения дополнительной информации прочтите документацию по модальным событиям для получения подробной информации о relatedTarget.

Инициализируем jquery bootstrap плагин modal при помощи javascript

Итак, давайте изменим несколько строк в предыдущем примере.

Интерактивные элементы связывать не нужно

Есть другой сценарий, когда содержимое вашего окна состоит из формы без предшествующего ей текста. В таком случае нет необходимости связывать форму с окном:

Элементы формы являются интерактивными. И они будут озвучены скринридером, когда пользователь начнёт с ними взаимодействовать.

Если скомбинировать и статический текст и форму:

Использование

Модальный плагин переключает ваш скрытый контент по запросу с помощью атрибутов данных или JavaScript. Он также переопределяет поведение прокрутки по умолчанию и генерирует .modal-backdrop, чтобы предоставить область клика для отклонения отображаемых модальных окон при щелчке вне модального окна.

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

Используйте сеточную систему Bootstrap в модальном окне, вложив .container-fluid в .modal-body. Затем используйте обычные классы системы сетки, как и везде.

Запустите демо модального окна

Как следует использовать модальность?

К настоящему времени надеюсь что возникло общее понимание того, когда использовать модальность. Остается только один вопрос: «Как мы спроектируем модальность?». Вот быстрый чеклист для использования модальных экранов:

Форма регистрации в модальном окне Bootstrap / Формы / Сниппеты Bootstrap | BootstrapТема

Когда следует использовать модальность?


Теперь, когда мы знаем, как выглядит модальный экран. Как же сравнить его с немодальным экраном и какова его цель? Прежде всего мы должны спросить себя: «В какой ситуации мы должны его использовать?»

Давайте представим, что мы создаем «гениальный и инновационный» стартап под названием «Purrrfect». Это база данных котят, которая позволяет пользователям загружать, просматривать и комментировать GIF-изображения милых котяток.

Упрощенный пользовательский поток нашего приложения может выглядеть следующим образом: пользователь открывает приложение и входит в одну из нескольких доступных вкладок (наша база данных о котятах), затем нажимает на одного из котят (входит в подробное представление одного котёнка) и затем нажимает на раздел комментариев (входит в раздел комментариев представления котёнка).

Форма регистрации в модальном окне Bootstrap / Формы / Сниппеты Bootstrap | BootstrapТема
Пользовательский поток приложения «Purrrfect»

Кроме того, пользователь может выполнять дополнительные действия на каждом из этапов. Например, он может добавить другого котёнка в базу данных на экране списка котят. Или он может редактировать данные на экране подробностей котенка.

А теперь надо понять, какой из этих экранов является модальным, а какой нет? Классификация в данном случае вызывает сложность, но вот моё личное эмпирическое правило:

Используйте модальные экраны для автономных процессов, а немодальные экраны для всего остального.«Автономный процесс» — это конкретное действие, которое имеет четкую начальную и конечную точку в процессе.

В течение ограниченного периода времени этого действия он выводит пользователя из общего потока пользователя, позволяя ему сосредоточиться на действии и затем возвращает его в ту точку потока, откуда он начал это действие.

Google формулирует это правило следующим образом:

Используйте модальные экраны (диалоги) для отображения «критической информации, которая требует конкретной пользовательской задачи, её решения или подтверждения» — Google

В случае нашего приложения «Purrrfect» это означает, что основной поток пользователя (используемый для исследования приложения) не является модальным. Однако специальные ограниченные по времени действия, такие как добавление котят, редактирование котят и написание комментариев, являются модальными.

Все модальные действия могут быть отменены либо успешно завершены, прежде чем пользователь вернется в основной поток. По этой причине модальные экраны используют кнопки «Отмена» и «Сохранить» (или другие подобные подтверждения действия) вместо кнопки «Назад».

Однако верно и следующее утверждение: если два разных действия, таких как «Отмена» и «Сохранить», не имеют смысла на вашем модальном экране (потому что они вызовут одно и то же действие), вы можете переключиться на немодальное представление. В этом случае основная навигация (например, панель вкладок) также должна оставаться видимой на экране.

Давайте вернемся к нашему приложению. Возможный интерфейс для «Purrrfect» может выглядеть так:

Форма регистрации в модальном окне Bootstrap / Формы / Сниппеты Bootstrap | BootstrapТема
Пользовательский интерфейс «Purrrfect»

Многоступенчатые модальные окна

Все становится сложнее, как только модальное диалоговое окно состоит из нескольких шагов или дочерних экранов. По умолчанию, кнопка продолжения действия отображается в правом верхнем углу. Экран второго шага не откроет новый модальный экран, но вместо этого остается внутри первого модального экрана и отображается как немодальный дочерний экран (так как не имеет возможности быть отменённым) существующего модального наложения в виде первого шага модального окна.

При размещении основного действия («сохранить», «применить» или «продолжить») в нижней части экрана (как было рекомендовано ранее) в верхней правой области второго шага модального блока всегда освобождается место для дополнительной кнопки отмены. Хотя перемещение выглядит более логичным слева направо, это размещение все же лучше для модального окна, чем отсутствие возможности закрывать модальный экран на дочерних (предшествующих) экранах.

Модальные компоненты

Ниже приведен пример статического модального окна (это означает, что его position и display были переопределены). Включены модальный заголовок, модальное тело (требуется для padding) и модальный нижний колонтитул (необязательно).

Модальные окна для форм

В формах нету ничего примечательного — используем стандартные

devise

‘овские сделав их

remote

и поменяв формат на

json

. Дальше делаем их модальными, обернув в соответствующие классы

bootstrap

‘а. В итоге получились такие

partial

‘ы:

app/views/shared/_sign_in.html.erb

Отклонение

Отклонение может быть достигнуто с помощью атрибута data на кнопке внутри modal, как показано ниже:

или на кнопке за пределами modal с помощью data-bs-target, как показано ниже:

Параметры

Параметры могут передаваться через атрибуты данных или JavaScript. Для атрибутов данных добавьте имя параметра к data-bs-, как в data-bs-backdrop=””.

НаименованиеТипПо умолчаниюОписание
backdropboolean or the string 'static'trueВключает элемент модального фона. В качестве альтернативы укажите static для фона, который не закрывает модальное окно при нажатии.
keyboardbooleantrueЗакрывает модальное окно при нажатии клавиши выхода.
focusbooleantrueПри инициализации фокусируется на модальном окне.

Полноэкранное модальное окно

Другое переопределение – это возможность вывести модальное окно, охватывающее область просмотра пользователя, доступное через классы модификаторов, которые помещаются в .modal-dialog.

КлассДоступность
.modal-fullscreenВсегда
.modal-fullscreen-sm-downМеньше 576px
.modal-fullscreen-md-downМеньше 768px
.modal-fullscreen-lg-downМеньше 992px
.modal-fullscreen-xl-downМеньше 1200px
.modal-fullscreen-xxl-downМеньше 1400px

При закрытии диалога

При закрытии диалогового окна фокус должен быть перемещён туда, где он был в момент открытия. Это поведение не является частью <dialog> и браузер полностью оставляет это на усмотрение разработчика.

Но и тут есть одно исключение: если элемент более не доступен, тогда фокус нужно вернуть туда, откуда наиболее логично для пользователя продолжить работу.

При открытии диалога

Во время открытия диалогового окна фокус должен быть перемещён на элемент внутри него. На какой именно — зависит от содержания.

В общем случае фокус перемещается на первый интерактивный элемент. Именно так ведет себя нативный <dialog> в браузере. Но нельзя делать сам элемент окна фокусируемым и перемещать фокус на него.

Например, для диалога с формой первый интерактивный элемент это первый <input>. Если ваше диалоговое окно носит чисто информативный характер, например, уведомление об успешной подписке, тогда первым и единственным элементом будет кнопка закрывающая диалог.

Но есть и несколько исключений:

  1. Запрос подтверждения чего-либо. Если ваш диалог запрашивает у пользователя подтверждения перед выполнением каких-то необратимых действий (удаление чего-то или выполнение финансовых операций), тогда фокус автоматически должен ставится на кнопку “отмены” этих действий, независимо от её расположения.
  2. Ситуации, когда в диалоговом окне много статического контента и первый интерактивный элемент не помещается в видимую область. Проблема тут в том, что в таком случае браузер автоматически проскролит вниз к кнопке в фокусе. Это вынудит пользователя скролить обратно вверх, а потом снова вниз. Для таких случаев есть два подхода:
    1. Переместить или продублировать интерактивные элементы так, чтобы первый из них был в видимой части экрана. Например, выполнить кнопку закрыть в виде крестика и закрепить в верхней части диалогового окна.
    2. Заголовок или первый абзац текста нужно сделать фокусируемым при помощи tabindex="-1" и перемещать фокус на него. Но при этом подходе некоторые программы чтения с экрана могут озвучивать заданный текст дважды: сначала как заголовок и описание окна, а потом как содержание выделенного элемента.

Управлять куда именно попадёт фокус при открытии модального окна можно с помощью атрибута autofocus:

Пример

Предлагаю разобрать на примере. Представим систему из трех диалоговых окон:

  1. Сообщает пользователю об наличии подписки. В нем две кнопки: “Условия подписки” и “Подписаться”
  2. Отображается по клику на “Условия подписки”. Открывается поверх первого.
  3. Отображается по клику на “Подписаться”. Заменяет собой первое.

В примерах ниже я специально пропустил дополнительные атрибуты и элементы, для упрощения кода.

Итак, у нас есть стартовая кнопка.

По нажатию на неё открывается первый диалог. Фокус автоматически перемещается на первый интерактивный элемент. А закрытие диалога должно возвращать фокус назад.

┌►<button>Рассылка</button>
│
└─  <dialog open>
        <button>Подписаться</button> <!-- in focus -->
        <button>Условия подписки</button>
    </dialog>

Далее пользователь перемещает фокус на “Условия подписки” и нажимает. Открывается второй диалог поверх первого. Фокус перемещается в него, а возвращаться должен на эту же кнопку в первом диалоге:

┌►<button>Рассылка</button>
│
└─  <dialog open>
        <h2>Рассылка</h2>

        <button>Подписаться</button>
┌────►  <button>Условия подписки</button>
│   </dialog>
│
└─  <dialog open>
        <h2>Условия подписки</h2>

        <button>Ок</button> <!-- in focus -->
    </dialog>

После закрытия второго диалога ваш JavaScript должен вернуть фокус на кнопку “Условия подписки” в первом.

┌►<button>Рассылка</button>
│
└─  <dialog open>
        <button>Подписаться</button> 
        <button>Условия подписки</button> <!-- in focus -->
    </dialog>

После чего пользователь нажимает кнопку “Подписаться”. По условиям нашей задачи открывается третий диалог. Фокус автоматически перемещается в него. А первый диалог закрывается:

┌►<button>Рассылка</button>
│
└─  <dialog>
        <h2>Рассылка</h2>

┌────×  <button>Подписаться</button>
│       <button>Условия подписки</button>
│   </dialog>
│
│   <dialog>
│       <h2>Условия подписки</h2>
│
│       <button>Ок</button>
│   </dialog>
│
└─  <dialog open>
        <h2>Введите email</h2>

        <button>Подтвердить</button> <!-- in focus -->
    </dialog>

И вот проблема: третье окно должно вернуть фокус на кнопку в первом, но первое окно больше не доступно. В таких случаях фокус нужно вернуть туда, куда указывал закрытый диалог — на кнопку “Рассылка” с которой пользовать начал.

┌►<button>Рассылка</button>
│
│   <dialog>
│       <h2>Рассылка</h2>
│
│       <button>Подписаться</button>
│       <button>Условия подписки</button>
│   </dialog>
│
│   <dialog>
│       <h2>Условия подписки</h2>
│
│       <button>Ок</button>
│   </dialog>
│
└─  <dialog open>
        <h2>Введите email</h2>

        <button>Подтвердить</button> <!-- in focus -->
    </dialog>

Безусловно, в вашем конкретном случае может быть более логичное поведение для возвращения фокуса. Например, у вас диалог создания новой записи в таблице. В таком случае, может быть логичнее возвращать фокус на только что созданную запиcь.

Помните, как во время установки программы в Windows можно просто нажимать Enter? Так вот это пример хорошей работы с фокусом: каждый раз, при переходе на новый экран в фокус ставится элемент, с которым вы скорее всего будете взаимодействовать — кнопка “Далее” или “Обзор”.

Примечание

Приложение писалось на rails 4, но отличия для 3.2 будут минимальны: запустится

bundle install

при создании приложения, нужно будет удалить

public/index.html

а также путь на главную будет выглядеть чуть иначе:

config/routes.rb

root to: 'welcome#index'

Прокрутка длинного контента

Когда модальные окна становятся слишком длинными для области просмотра или устройства пользователя, они прокручиваются независимо от самой страницы. Попробуйте демонстрацию ниже, чтобы понять, что мы имеем в виду.

Запустите демо модального окна

Вы также можете создать прокручиваемое модальное окно, которое позволяет прокручивать модальное тело, добавляя .modal-dialog-scrollable к .modal-dialog.


Запустите демо модального окна

Способы закрыть окно

Внутри диалогового окна обязана быть кнопка чтобы его закрыть. Не <div>, не <span> не <a>, не любой другой тег. Исключительно <button>. Это самый надежный способ гарантировать, что любой пользователь сможет закрыть диалоговое окно. Вы же не любите модальные окна которые невозможно закрыть?

Дополнительно, в зависимости от вашей логики, вы можете позволить пользователю закрыть диалог кликнув за его пределами или нажав Escape (встроено в <dialog> из коробки).

Но:

  1. Не рассчитывайте, что пользовать всегда может нажать на оверлей и так закрыть диалог.
    1. Как я писал ранее, во многих случаях диалоговое окно может занимать всю или большую часть экрана. Таким образом попасть в него может быть сложно или невозможно.
    2. Такой оверлей семантически не считается интерактивным элементом. Он не может быть в фокусе и на него невозможно “нажать” клавишами.
  2. Не рассчитывайте, что у пользователя под рукой есть клавиатура, чтобы нажать Escape.
  3. Существует множество устройств, программ и различных инструментов, способных читать веб-сайты и давать пользователю взаимодействовать с ними, но не так как в браузере. Во многих случаях единственным рабочим вариантом остаётся кнопка внутри.

Простейшая реализация кнопки закрывающей родительский диалог:

А если вы делаете кнопку с иконкой, то не забывайте про подпись, чтобы передать ёё назначение:

Статический контент должен быть связан с окном

Если в вашем диалоговом окне есть какое-то не интерактивное содержание, например, абзац текста, его стоит связать с диалогом подобно заголовку. Иначе, в некоторых случаях программы чтения с экрана не будут озвучивать такой контент.

Делается это атрибутом aria-describedby:

Если в вашем диалоговом окне много контента, тогда стоит обернуть его в один <div> и связать элемент диалога уже с ним:

Важно! Заголовок и любые кнопки не относящиеся к содержимому, а служащие для управления диалоговым окном, не должны быть включены в элемент на который указывает aria-describedby. Они должны быть вынесены отдельно:

Статический фон

Если фон установлен на статический, модальное окно не закроется при нажатии вне его. Нажмите кнопку ниже, чтобы попробовать.

Запустить модальное окно со статическим фоном

Существует два типа экранов:

  1. Модальные экраны
  2. Немодальные экраны

А теперь позвольте объяснить это утверждение. Практически каждый экран, который мы можем себе представить, попадает в одну из этих двух категорий. Чтобы понять, чем отличается модальный экран от немодального экрана, мы сначала должны перейти к определению понятия модального экрана.

Теги и атрибуты

Интерактивным элементом для открытия диалогового окна должна выступать кнопка. Не <div>, не <span> не <a>, не любой другой тег. Исключительно <button>. И касается не только диалоговых окон, <button> — самый надежный и доступный способ создавать интерактивные элементы на странице.

Простейшая реализация кнопки открывающая диалог по его id:

Удаление анимации

Для модальных окон, которые просто появляются, а не исчезают при просмотре, удалите класс .fade из Вашей модальной разметки.

Форма регистрации в модальном окне bootstrap / формы / сниппеты bootstrap | bootstrapтема


Центрование по вертикали

Добавьте .modal-dialog-centered к .modal-dialog для вертикального центрирования модального окна.


Вертикально центрированное модальное окно

Вертикально центрированное прокручиваемое модальное окно

Через javascript

Создайте модальное окно с одной строкой JavaScript:

Заключение

Многие дизайнеры разрабатывают продукты, основываясь на своих чувствах. И иногда интуиция важнее нормы, потому что в этом зачастую и есть суть творчества. Однако имеет смысл знать общие стандарты модальности, чтобы в нужный момент подстраивать их под основной пользовательский поток в приложении.

Похожее:  Бинбанк онлайн личный кабинет — вход для физических лиц

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *