Дата и время публикации:
Назначение и применение
1. Назначение
Вид визуальной формы, блокирующий и/или останавливающей работу приложения до тех пор, пока пользователь не закончит c ней работу. При этом такой метод визуализации интерфейса пользователя называют модальным, а вид графического интерфейса – модальное или диалоговое окно.
Диалоговые окна относятся к специальным элементам графического интерфейса, который является "конечной точкой" реализации человеко-машинного интерфейса (ЧМИ) (англ. Human-machine interface, HMI) и обеспечивающего интерактивное взаимодействие оператора(пользователя) с программно-аппаратной средой (вычислительной системой).
Таким образом, использование диалогового окна в модальном режиме позволяет информировать пользователя о важных событиях в "жизни" приложения и/или системы в целом с временным или полным остановом, в т.ч. для ввода пользователем необходимых данных.
Простым примером, такого взаимодействия будет вывод окна сообщения (англ. message box, англ. alert box), которое выводит одну или несколько строк текста и требует от пользователя подтвердить, что он был им прочитано.
2. Реализация
2.1 Суть использования технологий WEB
В документах WEB реализация, вернее её имитация, вывода окна диалога с текстовым сообщением и кнопкой "Закрыть" производится с использованием языка гипертекстовой разметки (англ. HyperText Markup Language), стилей каскадных таблиц CSS и мультипарадигменного языка программирования JavaScript.
2.2 стилей каскадных таблиц CSS
Несмотря на грозные названия перечисленных технологии информационной среды, с помощью которых реализуется данный интерактивный интерфейс, сама реализация достаточна проста, и заключается в отрисовки элемента DIV "поверх" всех остальных элементов документа DOM, которая случится после нажатия кнопки "".
2.2 Использование CSS
Создадим отдельный файл <style/modal.css> в корневой директории сайта класса .modal, как показано в листинге 2.2.1
Листинг 2.2.1
/* Задник модального окна */ .modal { display: none; /* не отображать по умолчанию */ padding-top: 5%; /* и установить ориентацию ящика */ left: 0; /* при этом */ top: 0; bottom: 0; right: 0; position: fixed; /* фиксируем положение */ z-index: 1000; /* поверх всех */ width: 100%; /* Раскрыть в ширину */ height: 100%; /* Раскрыть по высоте */ overflow: auto; /* разрешить прокрутку по необходимости */ background-color: rgb(0,0,0); /* Фон полностью белый Fallback color */ background-color: rgba(0,0,0,0.9); /* с оттенками черного */ /* свойство transform */ transform: scale(1.1); /* параметры трансформации элемента */ -ms-transform: scale(1.1); /* по ширине, т.к. значение больше единицы, */ -moz-transform: scale(1.1); /* поэтому элемент будет увеличен */ -o-transform: scale(1.1); -webkit-transform: scale(1.1); /* свойство transition */ -o-transition: visibility 0s ease 0.25s, opacity 0.25s 0s, transform 0.25s; -moz-transition: visibility 0s ease 0.25s, opacity 0.25s 0s, transform 0.25s; -ms-transition: visibility 0s ease 0.25s, opacity 0.25s 0s, transform 0.25s; -webkit-transition: visibility 0s ease 0.25s, opacity 0.25s 0s, transform 0.25s; transition: visibility 0s ease 0.25s, opacity 0.25s 0s, transform 0.25s; }
Как следует из описания класса .modal, элемент DIV будет привязан к указанной в свойствах padding-top, left и top точке на экране и не изменит своего положения при прокрутке страницы документа. При этом оно (модальное окно) будет находится "поверх" всех остальных его элементов, так как свойству z-index назначается большое значение по сравнению с другими его элементами, у которых обычно оно меньше или равно нулю.
В конце указывается свойство transition, которое позволяет устанавливать значения времени, "частоты" анимации других свойств CSS. В данном случае устанавливаются значения visibility, ease, opacity и transform, которые задают ход изменения прозрачности фона, темпа отображения и времени всех трансформаций модального окна соответственно.
Как показано в листинге 2.2, модальное окно отображается согласно описанию класса .modal-dialog.
Листинг 2.2.2
.modal-dialog { margin: 1% auto; /* берем 1 процент от верха с центрированием и*/ border: 3px solid #1f4649; /* рамкой, которая нужна для смягчения */ border-radius: 5px; /* краев диалога, поэтому цвет у рамки и*/ background-color: #1f4649; /* заднего вида одинаковый. */ color: #413f26; vertical-align: center; }
Класс .modal-head отвечает за оформление и геометрию "заголовка" и текстовый надписи, как показано в листинге 2.2.3.
Листинг 2.2.3
.modal-head{ margin: 1% auto; /* центрируем по середине с отступом */ padding: 0; /* на 1% от краев окна диалога */ color: #c5cbcb; /* устанавливаем свойства шрифта и */ word-wrap: break-word; /* и выравнивание текста */ font-size: 1.4em; font-weight: bold; font-style: italic; font-stretch: condensed; font-family: Geneva, Arial, Helvetica, sans-serif; }
Соответственно, .modal-content отвечает за оформление и позиционирование содержимого, например текста, внутри окна диалога, как показано в листинге 2.2.4.
Листинг 2.2.4
.modal-content { overflow: auto; /* полосы прокрутки будут автоматически включаться, */ display: block; /* если содержимое блока будет меньше чем его размер */ margin-top: 0; padding: 1% 1%; font-size: 1.2em; font-family: Georgia, 'Times New Roman', Times, serif; color: #413f26; background-color: #ffffe0; border-radius: 5px; }
Давайте для лучшего восприятия зависимостей перечисленных классов, взглянем на макет модального окна, который показан на рисунке 2.2.1
Рисунок 2.2.1
На нем показана геометрия модального окна и расположение элементов согласно их значений, указанных в свойствах border, padding и margin классов .modal, .modal-dialog, .modal-head и .modal-content.
2.3 Использование JavaScript и HTML
После нажатия кнопки "" будет запущена функция openModalDlg() и сгенерировано (после отпускания левой клавиши "мышки") событие onclick для элемента button, объявление которых в документе HTML показано в листинге 2.3.1 .
Листинг 2.3.1
. . . < button id="modal-btn-id" onclick="openModalDlg(this.id,'Некоторый техт в модальном окне...')">Модальное окно</button> . . .
Из которого видно, что функции openModalDlg(), текст которой приводится в листинге 2.3.2, передаются два аргумента: идентификатор "modal-btn-id" элемента button и текстовое сообщение в качестве содержимого модального окна.
Листинг 2.3.2
. . . 006 /* Объявление глобальных переменных */ 007 var mdlTmOutId; 008 var modalId = null; 009 var btnContext = undefined; 010 011 function openModalDlg(ident,msg) { 012 var body = document.body || document.getElementsByTagName("body")[0]; 013 var headName = document.getElementById(ident); 014 var modal = document.getElementById('open-'+ident); 015 016 console.log( getUnixMSecs()+' click '+ident ); 017 018 if ( modal ) { 019 var content = modal.getElementsByClassName('modal-content')[0]; 020 content.innerHTML = '<p>'+msg+'</p>'; 021 console.log( getUnixMSecs()+' Modify modal...' ); 022 }else{ 023 body.innerHTML = ' \ 024 <!-- The Modal behind--> \ 025 <div id="'+'open-'+ident+'" class="modal"> \ 026 <!-- Modal dialog --> \ 027 <div class="modal-dialog"> \ 028 <!-- Dialog header --> \ 029 <div class="modal-head"><span class="close">×</span>'+( ( headName && headName.innerHTML ) || 'Модальное окно')+' </div> \ 030 <!-- Dialog content --> \ 031 <div class="modal-content"> \ 032 <p>'+msg+'</p> \ 033 </div> \ 034 </div> \ 035 </div>' + body.innerHTML; 036 console.log( getUnixMSecs()+' create modal...' ); 037 } 038 039 mdlTmOutId = setTimeout( setEventsToModalCallback('open-'+ident), 300 ); 040 } . . .
В строках 006-007
Объявление глобальных переменных, содержащие:
- числовой идентификатор таймера mdlTmOutId, используемый в дальнейшем для сборса таймера в функции setEventsToModalCallback(),
- текстовый идентификатор модального окна modalId, указывающий на последнее выбранное модальное окно,
- переменная btnContext незадействована и объявлена для дальнейшего использования.
В строках 012-014
Объявление внутренних переменных, содержащие:
- элемент body, в начало которого будем вставлять код модального окна,
- текст заголовка headName, указывающей на текст вызываемой кнопки,
- само модальное окно modal, если оно было создано, определяется по текстовому идентификатору кнопки, который передается в аргументе ident рассматриваемой функции, и префиксу "open-", что в дальнейшем выливается в текстовый идентификатор модального окна.
В строке 016
Печатаем в консоль браузера информационное сообщение, что кнопка в нем изволила быть нажатой.
В строках 019-021
Модифицируем содержимое модального окна и печатаем об этом событии в ту же консоль.
В строках 023-036
Создаем модальное окно, добавляя его в начало элемента body, и печатаем об этом событии опять же в консоль.
В строке 039
Делаем трюк с таймером, чтобы браузер успел добавить обновку в редактируемый элемент, при срабатывании оного управление передается функции setEventsToModalCallback(), текст которого приводится в листинге 2.3.3 .
Листинг 2.3.3
. . . 042 function setEventsToModalCallback( ident, onClickModal ) { 043 var modal = document.getElementById(ident); 044 console.log( getUnixMSecs()+' try to update modal('+ident+')' ); 045 if ( modal ) { 046 var span = modal.getElementsByClassName("close")[0]; 047 modal.style.display = "block"; 048 modalId = ident; 049 resizeModalWindow (event); 050 span.onclick = function() { 051 modal.style.display = "none"; 052 } 053 if ( onClickModal && onClickModal == true ) 054 window.onclick = function(event) { 055 if (event.target == modal) { 056 modal.style.display = "none"; 057 } 058 } 059 060 window.onresize = function(event) { 061 resizeModalWindow (event); 062 } 063 console.log( getUnixMSecs()+' clear timeout!' ); 064 clearTimeout( mdlTmOutId ); 065 } 066 } . . .
В строках 042-044
Выборка по символьному идентификатору ident, переданного в первом аргументе, элемента modal модального окна и печатаем в консоль браузера о попытке его обновления. При этом второй аругумент onClickModal в настоящее время незадейстован, также как текст в строках 053-058.
В строках 050-052
Осуществляется назначение обработчика событию click, которое испускается при нажатии на символ закрытия модального окна, обозначаемое символом × в заголовке модального окна, который был определен ранее в строке 29 листинга 2.3.2 (создание элемента SPAN).
В строках 060-064
Назначается обработка событию resize, испускаемое при изменении размера модального окна, и печать на консоль браузера сообщения о процедуре удаления таймера, о которой говорилось ранее. Указанная операция производится с помощью встроенной функции clearTimeout().
Листинг 2.3.4
. . . 068 function resizeModalWindow (event) { 069 var modal = document.getElementById(modalId); 070 var wPrcnt = parseFloat(window.innerWidth || 071 document.documentElement.clientWidth || 072 document.body.clientWidth || 200.0 )/100.0; 073 var hPrcnt = parseFloat(window.innerHeight || 074 document.documentElement.clientHeight || 075 document.body.clientHeight || 150.0)/100.0; 076 var wDlgPrcnt = (wPrcnt * 50.0) / 100.0; 077 var hDlgPrcnt = (hPrcnt * 50.0) / 100.0; 078 079 var dlg = modal.getElementsByClassName("modal-dialog")[0]; 080 var head = modal.getElementsByClassName("modal-head")[0]; 081 var ctnt = modal.getElementsByClassName("modal-content")[0]; 082 if ( event ) 083 console.log( getUnixMSecs()+' event resize occured( geometry: '+wPrcnt+' X '+hPrcnt+' ).' ); 084 else 085 console.log( getUnixMSecs()+' update events( geometry: '+widthPrcnt+' X '+heightPrcnt+' ).' ); 086 087 dlg.style.width = wDlgPrcnt * 100.0; 088 dlg.style.height = hDlgPrcnt * 100.0; 089 090 head.style.width = wDlgPrcnt * 98.0; 091 head.style.height = hDlgPrcnt * 10.0; 092 093 ctnt.style.width = wDlgPrcnt * 98.0; 094 ctnt.style.height = hDlgPrcnt * 70.0; 095 096 } . . .
Как показано в листинге 2.3.4, функция resizeModalWindow() производит перерасчет геометрии модального окна и его элементов в процентном соотношении от половины размера текущей геометрии главного окна документа, которое устанавливется в строках 69-77. Процентные соотношения модальному окну и его элементов – в строках 087-094.
2.4 Пример вывода модального окна и сообщений в консоль
Показан на рисунке 2.4.1
Рисунок 2.4.1
3. Библиография
[1] Толкование слово модальный
[2] Модальное окно
[3] Диалоговое окно
[4] Человеко-машинный интерфейс
[7] How To Create a Modal Popup Box
[10]CSS3 transitions using visibility and delay
[11]MDN web docs. CSS transition
[12]How to find the width of a div using raw javascript