jqModal. Создание модальных окон и не только

Вроде бы по созданию и использованию модальных и всплывающих (pop-up) окон в LS публикации уже были, но видимо, то ли информации мало, то ли преподнесена она слишком кратко — вопросы опять появились.
Этим топиком я «убиваю сразу двух зайцев» — и свой багаж знаний пополню и у для кого-то текущие и будущие вопросы возможно помогу решить

Немного теории

Для отображения модальных окон в LS используется JQuery плагин jqModal.
Плагин jqModal поможет вам вывести предупреждения, диалоговые и модальные окна. Плагин гибок в настройках и является хорошей базой для показа всплывающих окон.
Основные свойства:
— Легкость настройки – использование ваших HTML-структуры и стилей (CSS)
— Легко перевести интерфейс
— Легко изменять – расширяемость функционала через callbacks-функции, что позволяет делать приложения разной сложности (слайд-шоу галереи, видео-презентации и т.д.)
— Простая поддержка подгрузки содержимого ( «AJAX»)
— Поддержка нескольких окон одновременно (в том числе окно-в-окне)

Для работы плагина jqModal необходимо подключить скрипт и файл стилей.

Добавления окна
Чтобы добавить диалоговое окно, фрейм или любое другое окно на сайт нужно добавить на страницу контейнер для всплывающих окон. В роли контейнера можно использовать скрытый <див>. CSS использутся для настройки внешнего вида и позиционирования. Этот блок будет отображен при наступление заданного события. Содержимое блока(текст/картинки/другое) может быть размещено в нем сразу (непосредственно в HTML) или может быть добавлено через ajax, в момент показа блока.
Инициализация
jqModal может быть вызван для любого скрытого элемента при помощи функции $.jqm(). Вы можете настроить ваше окно передавая параметры при инициализации плагина, на пример:
$('#dialog').jqm({modal: true, trigger: 'a.showDialog'})
Вызов окна
Окно будет автоматически вызвано после клика по указанному элементу. Вы также можете показать окно вызвав функцию $.jqmShow()

А что в реальности?

В LiveStreet не так и много модальных окон. Список можно увидеть в templates/skin/new-jquery/js/main.js (здесь и далее для шаблона new-jquery):
jQuery(document).ready(function($){
	// Всплывающие окна
	$('#login_form').jqm({trigger: '#login_form_show'});
	$('#blog_delete_form').jqm({trigger: '#blog_delete_show'});
	$('#add_friend_form').jqm({trigger: '#add_friend_show'});
	$('#form_upload_img').jqm();
	$('#userfield_form').jqm();
Назначение этих окон я думаю можно понять по идентификаторам элементов, например login_form, form_upload_img. Три окна имеют триггеры (ID элементов) — login_form_show, blog_delete_show, add_friend_show — по клику, на которые и будет показаны эти окна.
Исходные стили для всех используемых окон — templates/skin/new-jquery/css/jquery.jqmodal.css
Сам скрипт jqModal можно посмотреть — engine/lib/external/jquery/jquery.jqmodal.js.
Например, шаблон окна входа (login) можно увидеть в templates/skin/new-jquery/window_login.tpl
{if !$oUserCurrent}
	<div class="login-form jqmWindow" id="login_form">
		<a href="#" class="close jqmClose"></a>
		
		<form action="{router page='login'}" method="POST">
			<h3>{$aLang.user_authorization}</h3>

			{hook run='form_login_popup_begin'}

			<p><label>{$aLang.user_login}:<br />
			<input type="text" class="input-text" name="login" id="login-input"/></label></p>
			
			<p><label>{$aLang.user_password}:<br />
			<input type="password" name="password" class="input-text" /></label></p>
			
			<label class="label-remember"><input type="checkbox" name="remember" class="checkbox" checked />{$aLang.user_login_remember}</label>

			{hook run='form_login_popup_end'}

			<input type="submit" name="submit_login" class="button" value="{$aLang.user_login_submit}" /><br /><br />
			
			<a href="{router page='login'}reminder/">{$aLang.user_password_reminder}</a><br />
			<a href="{router page='registration'}">{$aLang.user_registration}</a>
		</form>
	</div>
{/if}
Основа этого окна:
<div class="login-form jqmWindow" id="login_form">
Классы стилей для окна и внутренних элементов: login-form, jqmWindow и идентификатор самого окна id=«login_form».
Если стили jqmWindow находятся в templates/skin/new-jquery/css/jquery.jqmodal.css, то стили для login-form и других окон можно найти в templates/skin/new-jquery/css/popups.css. Например стили для login-form:
/* Login popup */
.login-form { width: 400px; margin-left: -200px; left: 50%; top: 60px; background: #fff; display: none; }
.login-form p { margin-bottom: 15px; }
.login-form a { color: #555; }
.login-form label.label-remember { position: relative; top: 3px; }
.login-form input.input-text { border: 1px solid #ccc; width: 386px; padding: 4px 6px; font-size: 18px; font-family: Arial, sans-serif; }
.login-form .button{ float: right; }
.login-form .checkbox-label { color: #333; }
.login-form .checkbox { position: relative; top: 2px; margin-right: 5px; }

Обязательно окно до его вызова должно быть скрыто display: none;
.login-form { ... display: none; }

Перейдем к практике

Для создания нового модального (всплывающего, pop-up) окна пойдем простым путем — на основание формы регистрации создадим ее аналог в окне.
Для начало создадим заготовку
{if !$oUserCurrent}
	<div class="registration-form jqmWindow" id="registration_form">
		
	</div>
{/if}
и запишем в templates/skin/new-jquery/window_registration.tpl
Далее я взял из templates/skin/new-jquery/actions/ActionRegistration/index.tpl форму
<form action="{router page='registration'}" method="POST">
		<h2>{$aLang.registration}</h2>

		{hook run='form_registration_begin'}

		<p><label>{$aLang.registration_login}<br />
		<input type="text" name="login" value="{$_aRequest.login}" class="input-text input-wide" /><br />
		<span class="note">{$aLang.registration_login_notice}</span></label></p>

		<p><label>{$aLang.registration_mail}<br />
		<input type="text" name="mail" value="{$_aRequest.mail}" class="input-text input-wide" /><br />
		<span class="note">{$aLang.registration_mail_notice}</span></label></p>

		<p><label>{$aLang.registration_password}<br />
		<input type="password" name="password" value="" class="input-text input-wide" /><br />
		<span class="note">{$aLang.registration_password_notice}</span></label></p>

		<p><label>{$aLang.registration_password_retry}<br />
		<input type="password" value="" id="repass" name="password_confirm" class="input-text input-wide" /></label></p>

		{$aLang.registration_captcha}<br />
		<img src="{cfg name='path.root.engine_lib'}/external/kcaptcha/index.php?{$_sPhpSessionName}={$_sPhpSessionId}" onclick="this.src='{cfg name='path.root.engine_lib'}/external/kcaptcha/index.php?{$_sPhpSessionName}={$_sPhpSessionId}&n='+Math.random();" />

		<p><input type="text" name="captcha" value="" maxlength="3" class="input-text input-100" /></p>

		{hook run='form_registration_end'}

		<input type="submit" name="submit_register" class="button" value="{$aLang.registration_submit}" />
	</form>
и вставил в внутри блока registration_form в нашей заготовке.
Теперь стили — добавим в templates/skin/new-jquery/css/popups.css
.registration-form { width: 400px; margin-left: -200px; left: 50%; background: #fff; display: none;}
.registration-form p { margin-bottom: 15px; }
.registration-form a { color: #555; }
.registration-form input.input-text { border: 1px solid #ccc; width: 386px; padding: 4px 6px; font-size: 18px; font-family: Arial, sans-serif; }
.registration-form .button{ float: right; }
#registration_form {top: 50%; margin-top: -275px;}
стили скопированы из login-form ( для своих нужно можете настроить сами). Единственная уловка, к которой пришлось прибегнуть — это указание вертикального положения окна адресно для #registration_form. Вертикальное положение окна top:25% указано в engine/lib/external/jquery/jquery.jqmodal.js и попытка его переопределить в .registration-form {top: 50%; margin-top: -275px; } не пройдет. Причина в том что стили jqmWindow «прописываются» для окна позже стилей registration-form ( почему так? время будет разберусь)

Ну что — окно формы «нарисовали», теперь осталось сделать его показ.

В шаблоне templates/skin/new-jquery/header_top.tpl находим блок
<div class="auth">
	<a href="{router page='login'}" id="login_form_show" class="login-link">{$aLang.user_login_submit}</a> {$aLang.or} 
	<a href="{router page='registration'}">{$aLang.registration_submit}</a>
</div>
добавляем триггер id=«reg_form_show» для ссылки на регистрацию
<div class="auth">
	<a href="{router page='login'}" id="login_form_show" class="login-link">{$aLang.user_login_submit}</a> {$aLang.or} 
	<a href="{router page='registration'}" id="reg_form_show">{$aLang.registration_submit}</a>
</div>


В знакомом уже templates/skin/new-jquery/js/main.js добавляем инициализацию формы $('#registration_form').jqm({trigger: '#reg_form_show'});
// Всплывающие окна
	$('#login_form').jqm({trigger: '#login_form_show'});
	$('#blog_delete_form').jqm({trigger: '#blog_delete_show'});
	$('#add_friend_form').jqm({trigger: '#add_friend_show'});
	$('#form_upload_img').jqm();
	$('#userfield_form').jqm();
	$('#registration_form').jqm({trigger: '#reg_form_show,#login_reg_form_show'});

Причем триггеров для окна можно указывать несколько. В данном случает я реализовал показ окна регистрации из модального формы входа (login_form).

Ну вроде все и нет ничего сложного.
Т.о. для создания модального окна в LS потребуется:
1. Создать шаблон окна и определить его содержимое и стили. Назначить ID окна для первого видимого элемента.
2. Разместить триггер для вызова окна — атрибут ID элемента активации.
3. Инициализировать окно по его ID и/или для ID триггера.

Возможно нужно сделать ещё один пример — диалог выхода или что-то посложнее.

16 комментариев

avatar
хороший пост!
avatar
Очень полезная инфа, однозначно в избранное.
avatar
Небольшая опечатка в тексте:
В шаблоне templates/skin/new-jquery/header_top.js tpl находим блок
avatar
Спасибо. Поправил
avatar
Спасибо, все работает, проблема была что я забыл про компиляцию js файлов, цсс отрубил давно, а про это забыл.
avatar
Пожалуйста, подскажите, будет ли работать (появляться login popup), если я укажу id id=«login_form_show_N» (где N-порядковый номер) нескольким объектам? И пропишу
$('#login_form').jqm({trigger: '#login_form_show','#login_form_show_N'});
Мне нужно, чтобы всплывающее окно авторизации появлялось по клику на некоторые ссылки на странице, сейчас такая конструкция не работает (поп-ап не выскакивает нигде, даже там где всегда раньше выскакивал) Я хочу понять, это в принципе не работает или я что-то упустила? Спасибо!
avatar
модальное окно перекрывает title (всплывающую подсказку) — может кто то подскажет как поправить.
avatar
А как сделать появление всплывающего окна при создании пользователем нового топика? Сценарий такой: пользователь создаёт топик, нажимает кнопку «опубликовать», страница перезагружается и тут должно появится всплывающее окно типа «Ваш новый пост опубликован. Теперь Вы можете поделиться им с друзьями...».
Какое должно произойти событие, чтобы модалка появлялась при создании топика?

Для чего это всё нужно? Думаю что таким образом удастся привлечь к новым постам дополнительное внимание и привлечь новых пользователей.
avatar
У jqModal мне не хватает одной полезной штуки — возможности прокручивания страницы диалога, вместо прокрутки страницы «под» диалоговым окном — как только высота диалога превышает высоту окна — все, беда.
avatar
мы отказались от jqModal в пользу своего решения, там этой проблемы нет
avatar
Ждем-с :) Или можно считать это решение продакшн и качать с гитхаба?
avatar
сейчас оно вполне рабочее, например, уже используется на этом сайте
avatar
на гитхабе сделали базовый шаблон окон.
Теперь все окна наследуются от него, если в начало файла вставить
{extends file='modals/modal_base.tpl'}

Достаточно задать контентную часть окна, все остальное прилепится само.
Это поможет, если в будущем будет меняться шаблон родителя, то вам не надо будет копипастить его код в свое модальное окно.

{block name='modal_options'}
Здесь можете объявлять ваши переменные
{/block}

{block name='modal_class'}
данный блок пропишется в class модального окна
{/block}

{block name='modal_id'}
id модального окна
{/block}
{block name='modal_attributes'}
атрибуты тега модального окна
{/block}
	
{block name='modal_title'}
Собственно заголовок, если его нет, то header модального окна не появится 
{/block}
	
{block name='modal_header_after'}доп блок{/block}
	
{block name='modal_content' hide}
Сама контентная часть, скроется весь блок при ее отутствии		
{/block}
	
{block name='modal_content_after'}доп блок{/block}

	{* Footer *}
{block name='modal_footer'}здесь можно переопределить весь footer. Частично можно это сделать в следующих двух вложенных блоках{/block}
		
	{block name='modal_footer_begin'}доп блок{/block}

	{block name='modal_footer_cancel'}по умолчанию тут кнопка закрытия окна{/block}
	
	
{block name='modal_footer_after'}доп блок{/block}
avatar
Можно ли сделать окна подвижными (перетаскиевыми)?
avatar
либо юзайте html5: атрибут тега draggable=«true»
либо подключайте jQueryUI DragNDrop или отдельный jQuery плагин
avatar
инициализировал, добавил вид блока с айдишником в шабл, при клике на сылку не выводит окно.
livestreet.ru/blog/17963.html
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.