Делаем плагин модальных окон на jQuery и CSS3
Ох, я так давно ничего не писал в блог, не так ли. Вот собственно решил исправить ситуацию новым но очень поздним постом. Сегодня расскажу про создание плагина модальных окон на jQuery. Плагин не сверхъестествен, просто отображение любого рода HTML кода в модальном окне.
Шаг первый. Вертска
Ну и как всегда начнем с верстки. Для нашего модального окна нам нужен основной контейнер, заголовок сообщения, контейнер для содержимого и кнопка закрытия окна. Также нам нужен и оверлей для покрытия всех элементов сайта (чтобы юзер не кликал нигде пока не закроет окно).
В результате у нас получается вот такой вот код:
<div id="jm-fader"></div> <div id="jm-container"> <a href="#" class="jm-close"></a> <div class="jm-header">Some title</div> <div class="jm-content">Lorem ipsum!</div> </div>
Этот код вы можете разместить у себя на сайте в конце или в начале элемента BODY, разницы нет.
Шаг второй. Стили
И так, верстка у нас есть теперь нужно чтобы наши элементы красиво выглядели и по умолчанию были скрыты. Долго я не баловался и получился вот такой вот код:
#jm-fader {
background: #888;
display: none;
position: absolute; top: 0; left: 0; right: 0; bottom: 0; z-index: 100;
}
#jm-container {
background-color: #000;
padding: 10px;
width: 400px;
font-family: Ubuntu, Tahoma, Arial;
display: none; overflow: hidden;
position: absolute; top: 0; left: -1000px; z-index: 150;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 3px;
-webkit-box-shadow: 0px 0px 15px #333;
-moz-box-shadow: 0px 0px 15px #333;
-o-box-shadow: 0px 0px 15px #333;
box-shadow: 0px 0px 15px #333;
}
div.jm-header {
font-size: 15px;
color: #fff;
margin: 0px 5px 10px;
}
div.jm-content {
background-color: #fff;
font-size: 13px;
color: #454545;
padding: 10px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
-o-border-radius: 3px;
border-radius: 3px;
}
a.jm-close {
background: url('../images/jm-close.png') center no-repeat;
width: 15px; height: 15px;
display: block; float: right;
margin: 2px 3px 0;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
-o-border-radius: 3px;
border-radius: 3px;
-webkit-opacity: .2;
-moz-opacity: .2;
-o-opacity: .2;
opacity: .2;
}
#jm-container:hover a.jm-close {
-webkit-opacity: 1;
-moz-opacity: 1;
-o-opacity: 1;
opacity: 1;
}
Вот такой вот CSS получился в итоге, конечно же из-за CSS3 красивостей код потолстел в два раза, что не может не огорчать, увы! Но не будем об этом, нам ведь главное чтобы все было красиво :)
Шаг третий. jQuery плагин
Что нам необходимо от небольшого плагина для показа модальных окон? Раз он не большой то нам достаточно лишь показывать его и дать возможность закрывать, для полезности добавим еще колбек-функции на открытие и закрытие. И для удобности сделаем возможность закрывать окно по клавише Escape, а не только по клику на крестик. Я думаю можно добавить еще эффект появления окна из-за границы экрана при откртыии и наоборот. Ну приступим:
(function($) {
$.jModal = function(header, content, options) {
// устанавливаем настройки и смерживаем их с дефолтными
options = $.extend({
width: '400px'
}, options);
// находим все необходимые элементы
var fader = $('#jm-fader');
var container = $('#jm-container').css('width', options.width);
var headerContainer = $('#jm-container > .jm-header');
var contentContainer = $('#jm-container > .jm-content');
var closeButton = $('#jm-container > .jm-close');
// проверяем оверлей и показываем его
if (fader.length) {
fader.css({
opacity: .35,
height: $(document).height()
}).show();
} else {
if (console && console.error) {
console.error('[jModal] #jm-fader контейнер не найден.');
}
return false;
}
// проверяем все ли части модального окна есть
if (!container.length && !headerContainer.length && !contentContainer.length && !closeButton.length) {
if (console && console.log) {
console.error('[jModal] Нехватает некоторых контейнеров модального окна.');
}
return false;
}
// настраиваем модальное окно
headerContainer.text(header);
contentContainer.html(content);
// центрируем и показываем модальное окно
container.show().css({
top: (parseInt($(window).height()) / 2) - (parseInt(container.height()) / 2)
}).animate({left: (parseInt($(document).width()) / 2) - (parseInt(options.width) / 2)}, 350, function () {
// если есть коллбек на открытие, выполняем его
if (typeof options.open != 'undefined') {
options.open.call(container);
}
});
// вешаем закрытие окна на кнопку закрыть
closeButton.one('click', function() {
container.animate({left: '-1000px'}, 350, function() {
this.style.display = 'none';
fader.hide();
// если есть колбек на закрытие, то выполняем
if (typeof options.close != 'undefined') {
options.close.call(container);
}
});
});
// и клавишу Escape
$(document).one('keydown', function(e) {
if (e.keyCode == 27) {
container.animate({left: '-1000px'}, 350, function() {
this.style.display = 'none';
fader.hide();
// если есть колбек на закрытие, то выполняем
if (typeof options.close != 'undefined') {
options.close.call(container);
}
});
}
});
// если пользователь скроллит, тогда перемещаем окно
$(window).scroll(function() {
container.stop(true, false).animate({top: window.scrollY + (parseInt($(window).height()) / 2) - (parseInt(container.height()) / 2)}, 500);
});
return true;
}
})(jQuery);
Ухтышка! У нас получилось! Надеюсь комментариев в коде предостаточно для понимания алгоритма и сти работы скрипта. Если нет, тогда жду вопросы в комментариях :)
Шаг четвертый. Запускаем
Теперь мы запустим скрипт в действие, для проверки его работоспособности. Давайте создадим вот такой код заглушку и подключим все необходимые нам файлы:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>jModal</title>
<link href="css/base.css" rel="stylesheet" />
<link href="css/jmodal.css" rel="stylesheet" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="js/jmodal.js"></script>
<script type="text/javascript">
$(window).ready(function() {
$('#show-jm-first').click(function() {
$.jModal('Обычное сообщение', 'Это просто красивое модальное окошко, ничего больше. Используется для уведомления пользователя о каких либо действиях.');
});
$('#show-jm-second').click(function() {
$.jModal('Сообщение с коллбеками', 'На окна можно вешать коллбек, на открытие и на закрытие.', {
open: function(container) {
$('#show-jm-log').text('Модальное окно открылось!');
},
close: function(container) {
$('#show-jm-log').text('Модальное окно закрылось :)');
}
});
});
});
</script>
</head>
<body>
<div id="wrap">
<a href="#" id="show-jm-first" class="jm-show">Показать обычное модальное окно</a>
<a href="#" id="show-jm-second" class="jm-show">С коллбеками на клик и закрытие</a>
<br />
<div id="show-jm-log" style="text-align: center; color: #666;"></div>
</div>
<div id="jm-fader"></div>
<div id="jm-container">
<a href="#" class="jm-close"></a>
<div class="jm-header">Some title</div>
<div class="jm-content">Lorem ipsum!</div>
</div>
</body>
</html>
Теперь запускаем это в браузере и смотрим результат. Ухты, все работает. Теперь поясню как использовать скрипт.
Вариант первый, указываем только заголовок и содержимое:
$.jModal('Обычное модальное окно', 'Содержимое модального окна.');
Вариант второй, указываем ширину и колбеки:
$('#show-jm-second').click(function() {
$.jModal('Сообщение с коллбеками', 'На окна можно вешать коллбек, на открытие и на закрытие.', {
width: 600,
open: function(container) {
alert('Модальное окно открылось!');
},
close: function(container) {
alert('Модальное окно закрылось :)');
}
});
});
В саму колбек функцию приходит один параметр, это ссылка на основной контейнер модального окна.
Ну вот и все, на этом можно поставить точку и надеяться, что разъяснил как можно проще и доступней, ведь в первую очередь этот пост нацелен на аудиторию новичков в jQuery :)
отличный плагин!!, У меня вот такой немного отходящий вопрос от темы, где взять вот такой вот задний фон как у вас.. я его много где встречаю в многих цветовых гамах. Возможно есть какой то генератор? Не поделитесь ссылочкой:))
Subtle Patterns
Случаем, не знаете, на просторах инета существует подобная замечательная вещь, но только кроссбраузерная?
Эта тоже кроссбраузерная :)
Делаю нечто подобное, но есть одна проблемка если предварительно прокрутить страницу и нажать кнопку то окно не показывается. А если прокрутить обратно вверх то все работает. Пробовал в разных браузерах и в вашем примере такая же проблема. Не подскажите как решить?
Хм, не замечаю, вроде нормально. Можете по подробнее описать проблему?
Аналогичная проблема, после прокрутки не показывается! Кто поможет решить проблему?
Можно подробные шаги, при разных прокрутках (и до и после) у меня нормальный полет.
По шагам захожу на страницу нажимаю кнопку появляется окно, прокручиваю скролл чуть вниз нажимаю кнопку нет окна (затемнение появляется но само окно не вылетает по esc можно убрать затемнение), прокручиваю обратно вверх опять есть окно. Вот такая проблема( во всех браузерах пробовал
Я думаю нужно просто поменять стиль #jm-container {position:absolute} на #jm-container{position:fixed}
=)
У меня точно такая же проблема как у #Павел и #Bumaga!
И еще… Высоту он автоматически определяет и ставится по центру, нужно сделать точно так же и в длину!
top: (parseInt($(window).height()) / 2) — (parseInt(container.height()) / 2)
left: (parseInt($(document).width()) / 2) — (parseInt(options.width) / 2)}, 350
Он и определяет координаты горизонтального центрирования!
Даже у вас демо нажмите Ctrl + Scroll UP а потом покрутите вниз и нажмите на кнопку и увидите!
При изменении размеров он естественно не будет автоматически центрироваться, так как он получает координаты только при показе.
Если вам необходимо, чтобы окошко постоянно обновляло свои координаты, то вам необходимо описать еще логику на событии ресайза окна (onresize).
А как можно сделать модалку анологичную, как у вк с чатом…?
PHP+JS в руки и вперед :)
с php то понятно, а вот с js не дружу пока что =(
Если с PHP все понятно, то тем более проще простого сделать, так как JS всего лишь слушает и показывает сообщения, а выучить JS особо труда не составляет.
Плагин хороший. Все получилось сделать. Но были проблемы с полем select при изменении выделенного объекта программно, в модальном окне не изменялось. Нашла ответ, использовать trigger для вызова события change.