FrameWarp – jQuery плагин для вывода страницы в модальном окне / JS iframe

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

Сложность

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

  • Легкий - он создан специально для отображения страниц, а не изображений;
  • Нет интерфейса, так что страница будет отображаться как в обычном окне;
  • Страница имеет функцию закрытия и отправки сообщения в родительское окно;
  • Может использовать кэш для ускорения последующей загрузки страницы;
  • Использует JavaScript и CSS анимацию;

Идея

При нажатии по ссылке или кнопке, плагин, который мы назвали FrameWarp, определит местоположение этого элемента и вызовет CSS анимацию расширяющегося прямоугольника в центре окна. Плагин передает URl целевой страницы и загружает JS Iframe. Если страница ведет на тот же сайт с которого открывается, то FrameWarp также добавит два полезных метода к js iframe – первый - кнопка закрытия модального окна, второй - отправка данных в родительское окно.

Используем jQuery ++, это набор инструментов для jQuery, который преобразует метод animate() в библиотеку, для использования CSS transition на поддерживаемых браузерах. Это делает сложную анимацию довольно простой.

Анимация

Хитрость в том, что мы анимируем ширину и рамки элементов, а высота остается 0. Левая и правая рамка – прозрачные. Кроме того, вы можете сделать это в 3D на CSS transform, но не будет работать в старых браузерах.

Плагин

Перейдем к созданию плагина. Добавим весь код в отдельную функцию. В действительности все переменные и вспомогательные функции доступны только для этого плагина.

assets/framewarp/framewarp.js

(function($){
 
// частные переменные
 var body = $('body'),
win = $(window),
popup, popupBG; var frameCache = {};
var frameCacheDiv = $('<div class="frameCacheDiv">').appendTo('body');
var currentIframe; $.fn.frameWarp = function(settings){ // Основной код плагина }; // функции помошника function hide(){ // удаляем открывающийся темный фон из страницы } function setUpAPI(iframe, settings){ // в этой функции мы сделаем два API метода доступными для фрейма,
// если эта страница от того же домена.
} function sameOrigin(url){ // определяем домен
} function getOrigin(url){ // функция помошника для того что бы генерировать строку
// из типа: https://www.google.com
// это определяет протокол и хост.
} })(jQuery);

Плагин создает контейнер с классом frameCacheDiv, для отображения js iframe. Еще два контейнера мы добавили с помощью плагина – .popup и .popupBG, которые мы обсудим чуть позже. Теперь давайте рассмотрим функции помощника.

function hide(){

	if(currentIframe){
		currentIframe.hide();
		currentIframe = null;
	}

	popupBG.remove();
	popup.remove();
}

function setUpAPI(iframe, settings){

	if(sameOrigin(settings.url)){

		// минимум API в iFrame
		iframe[0].contentWindow.frameWarp = {
			hide: hide,
			sendMessage:function(param){
				return settings.onMessage(param);
			}
		};
	}
}

function sameOrigin(url){

	// определение url,
	// относится к локальному сайту или к удаленному

	return (getOrigin(url) == getOrigin(location.href));
}

function getOrigin(url){

	// Использование элемента привязки 
	// для разбора URL

	var a = document.createElement('a');
	a.href = url;

	return a.protocol+'//'+a.hostname;
}

В браузерах присутствует функция защиты под названием  “same origin policy” , которая ограничивает веб-сайт получить доступ к DOM другого сайта. По этой причине, у нас есть вспомогательная функция, которая сравнивает адрес JS IFRAME с адресом текущей страницы. Только когда и домен и соответствие протокола определенны, мы получим доступ к DOM iframe и добавим API методы для отправки сообщений и закрытия окна.

Приступам к написанию плагина frameWarp!

$.fn.frameWarp = function(settings){
 
// Настройки по умолчанию
 settings = $.extend({
cache: true,
url: '',
width:600,
height:500,
closeOnBackgroundClick: true,
onMessage:function(){},
onShow:function(){}
}, settings); this.on('click',function(e){ e.preventDefault(); var elem = $(this),
offset = elem.offset(); // Центральная кнопка
var buttonCenter = {
x: offset.left - win.scrollLeft() + elem.outerWidth()/2,
y: offset.top - win.scrollTop() + elem.outerHeight()/2
}; // Центр окна
var windowCenter = {
x: win.width()/2,
y: win.height()/2
}; // Если не определено ни одного URL, используйте атрибут href. if(!settings.url && elem.attr('href')){
settings.url = elem.attr('href');
} // Темный фон popupBG = $('<div>',{'class':'popupBG'}).appendTo(body); popupBG.click(function(){ if(settings.closeOnBackgroundClick){
hide();
} }).animate({ // jQuery++ CSS3 анимация
'opacity':1
},400); // Всплывающее окно popup = $('<div>').addClass('popup').css({
width : 0,
height : 0,
top : buttonCenter.y,
left : buttonCenter.x - 35
}); // Добавление в страницу и вызов CSS3 анимации
popup.appendTo(body).animate({
'width' : settings.width,
'top' : windowCenter.y - settings.height/2,
'left' : windowCenter.x - settings.width/2,
'border-top-width' : settings.height,
'border-right-width' : 0,
'border-left-width' : 0
},200,function(){ popup.addClass('loading').css({
'width': settings.width,
'height': settings.height
}); var iframe; // Если этот IFRAME уже существует в кэше
if(settings.cache && settings.url in frameCache){
iframe = frameCache[settings.url].show();
}
else{ iframe = $('<iframe>',{
'src' : settings.url,
'css' : {
'width' : settings.width,
'height' : settings.height,
}
}); // Если кэш включен, добавить к нему фрейм
if(settings.cache){
frameCache[settings.url] = iframe;
iframe.data('cached',true);
settings.onShow();
}
else{ // Удаление некэшируемых фреймов
frameCacheDiv.find('iframe').each(function(){
var f = $(this);
if(!f.data('cached')){
f.remove();
}
});
} iframe.ready(function(){
frameCacheDiv.append(iframe);
setUpAPI(iframe, settings);
settings.onShow();
});
} currentIframe = iframe; }); }); return this;
};

Как я упоминал в самом начале, мы используем jQuery ++, для улучшения функции jQuery animate(), которая поддерживает CSS animate. Благодаря этому, нам не потребуется писать кучу CSS кода, а также, у нас будет полная совместимость с браузерами которые не поддерживают CSS анимацию.

После завершения первой анимации, мы загружаем класс .popup. Новый класс добавляет анимированный прелоадер gif на всплывающих окнах и мягкие тени окна, это можно увидеть в assets/framewarp/framewarp.css.

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

Чтобы использовать плагин, подключите assets/framewarp/framewarp.css и assets/framewarp/framewarp.js к основной странице.

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

assets/js/script.s

$(function(){

	// Если никакое свойство URL не будет передано, 
	// то будет использоваться атрибут href

	$('#b1').frameWarp();

	$('#b2').frameWarp({
		onMessage: function(msg){
			$('#messages').append('Message Received: '+ msg+'
');
		}
	});

	// Кэш включен по умолчанию
	$('#b3').frameWarp({
		url : 'http://www.cnn.com/'
	});

	// Отключение кэширования
	$('#b4').frameWarp({
		url : 'http://www.cnn.com/',
		cache:false
	});
});

Перевод статьи FrameWarp - jQuery plugin for displaying pages in a neat overlay

Тэги: pluginiframe

Вход

Уважаемый пользователь! Мы обнаружили, что вы используете AdBlock и вынуждены скрыть часть материалов на нашем сайте. Siteacademy существует и развивается за счет доходов от рекламы. Просим внести наш сайт в список исключений или отключить Блокировщик рекламы на нашем сайте.