
Модальные окна это просто
За период своей работы я работал с десятком плагинов по созданию модальных окон, почти все из которых были построены на основе jQuery. Но совсем недавно я осознал, что такие окна самому создать, зачастую, проще. Давайте так и сделаем в стиле Angular.
Требования
Хотелось бы создавать окна при помощи следующего HTML кода:
<modal-dialog show='modalShown' width='750px' height='90%'>
<p>Modal Content Goes here<p>
</modal-dialog>
И иметь следующий набор функций:
- Открывать и закрывать окно при помощи $scope переменной установив её в true или false (переменная в примере - modalShown)
- Указывать размер окна в пикселях или процентах
- Затемнять оставшуюся часть экрана
- Закрывать кликнув на X в углу окна или за пределами окна
Код директивы
Сама директива довольно проста, с функцией в несколько строк в параметре link
. Параметр “show: ‘=’”
в отдельной области видимости создает двойную связку между переменной заданной в атрибуте show
и переменной show
в области видимости. Установка этого параметра в false
и true
открывает или закрывает окно. Также при открытии мы проверяем параметры height
и width
и, если они заданы, то выставляем нужные значения. Наконец, метод hideModal()
просто устанавливает значение переменной show
в false
.
app.directive('modalDialog', function() {
return {
restrict: 'E',
scope: {
show: '='
},
replace: true, // Замените на шаблон
transclude: true, // мы хотим вставлять пользовательский контент внутри директивы
link: function(scope, element, attrs) {
scope.dialogStyle = {};
if (attrs.width) {
scope.dialogStyle.width = attrs.width;
}
if (attrs.height) {
scope.dialogStyle.height = attrs.height;
}
scope.hideModal = function() {
scope.show = false;
};
},
template: '...' // Смотрите ниже
};
});
Шаблон
Сам шаблон также довольно прост. Обратите внимание на атрибут ng-transclude
, он указывает на контейнер для содержимого вашего окна. А атрибут ng-style
переводит объект javascript в инлайновый стиль (style) для элемента html.
<div class='ng-modal' ng-show='show'>
<div class='ng-modal-overlay' ng-click='hideModal()'></div>
<div class='ng-modal-dialog' ng-style='dialogStyle'>
<div class='ng-modal-close' ng-click='hideModal()'>X</div>
<div class='ng-modal-dialog-content' ng-transclude></div>
</div>
</div>
CSS
Не буду досконально углубляться в CSS. Скажу только одно - работать будет только в современных браузерах. Если вы планируете применять эти стили в браузерах ниже IE9, то потребуется изменить способ центрирования окна.
.ng-modal-overlay {
/* полупорозрачный DIV, который охватывает весь экран */
position:absolute;
z-index:9999;
top:0;
left:0;
width:100%;
height:100%;
background-color:#000000;
opacity: 0.8;
}
.ng-modal-dialog {
/* Отцентрированный даилог с тенью */
z-index:10000;
position: absolute;
width: 50%;
/* Центрирование */
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
background-color: #fff;
box-shadow: 4px 4px 80px #000;
}
.ng-modal-dialog-content {
padding:10px;
text-align: left;
}
.ng-modal-close {
position: absolute;
top: 3px;
right: 5px;
padding: 5px;
cursor: pointer;
font-size: 120%;
display: inline-block;
font-weight: bold;
font-family: 'arial', 'sans-serif';
}
Открытие и закрытие окна
И, наконец, чтобы завершить пример, нам понадобится добавить совсем немного кода в HTML страницу и контроллер.
<button ng-click='toggleModal()'>Открыть модальный диалог</button>
<modal-dialog show='modalShown' width='750px' height='60%'>
<p>Содержимое модального окна<p>
</modal-dialog>
app.controller('MyCtrl', function($scope) {
$scope.modalShown = false;
$scope.toggleModal = function() {
$scope.modalShown = !$scope.modalShown;
};
});
Всё вместе
Вот и всё. Автор выложил рабочую версию на JSBin. Усовершенствованный вариант, разместил на GitHub.
Комментарии