- PVSM.RU - https://www.pvsm.ru -

Bootstrap Modal Iframe Костыль

Bootstrap Modal Iframe Костыль
«Не надо, я сам»
Хромой Итальянец

Постановка задачи

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

Сразу дали понять, что партнёры, хоть и партнёры, но размещать у себя что-либо сложное не будут, то есть про jQuery забыли. Стандартное решение – iframe с минимальной функцией resize [1] на голом JavaScript.

Картинки

Баннер по умолчанию:

Bootstrap Modal Iframe Костыль

Баннер при вызове всплывающего окна:

Bootstrap Modal Iframe Костыль

В качестве backend ASP.NET MVC [2] всё в Azure [3], картинки в Storage, таблички в SQL. Последнее время Редмонд [4] активно рекомендует в качестве frontend шаблон Bootstrap [5]. Собственно, никто и не против, так как по сравнение с тем, что предлагалось раньше, Bootstrap [5] это просто праздник.

Основная проблема реализации – всплывающее окно из iframe перекрывающее по высоте родителя. На своём сайте можно спокойно вызвать Modal [6] через parent iframe’а, но в данном случает домен у iframe другой и браузер будет защищаться. То есть CORS [7]. Партнёры весело и дружно правящие конфигурации на своих веб серверах постановкой задачи не предполагаются.
Если нельзя трогать партнёрские сайты, то можно трогать наш iframe.

Решение

Костыль: в фоне под открывшимся Modal окошком увечить высоту iframe так, чтобы Modal помещался целиком или почти целиком.

Реализация

На HTML5 API window.postMessage [8]. Есть несколько библиотек [9] на jQuery, декларирующих динамический resize ifram’а. Но, во-первых, это предполагает подключение библиотек на стороне партнёрских сайтов, во-вторых в данной задаче надо совсем немного, а в-третьих, при проверки эти библиотеки не справились с учётом Modal окошка.

HTML нашего iframe’a

<div class="container" id="mainContent">
    <div class="row"><h1>Some iframe</h1></div>
    …
    <a href="#" class="btn btn-default" id="openBtn">Open modal</a>
</div>
<!--Большое Modal окно-->
<div id="myModal" class="modal fade" tabindex="-1" role="dialog">
    <div class="modal-dialog">
        <div class="modal-content" id="myModalContent">
            …
        </div>
    </div>
</div>

JavaScript iframe’a onLoad

//Запуск Modal окошка
    $('#openBtn').click(function () {
        $('#myModal').modal({ show: true })
    });
//При открытии Modal окна отправляется сообщение с высотой Modal окна
    $('#myModal').on('shown.bs.modal', function (e) {
/*Звёздочку * здесь надо ставить, так как домен партнёрской страницы нам не известен и передаётся не секретная высота окна*/        
parent.postMessage($("#myModalContent").height(), "*");
    });
//При закрытии Modal окна отправляется сообщение с высотой без Modal окна
    $('#myModal').on('hidden.bs.modal', function (e) {
        parent.postMessage($("#mainContent").height() + 1, "*");
    });
//Установка начальной высоты iframe (+1 – на поля)
    parent.postMessage($("#mainContent").height() + 1, "*");

Полный код для iframe на Bootply [10]

HTML на стороне партнёров

<iframe id="myIframe" src="http://bootply.com/render/112265" width="100%" scrolling="no"></iframe>

JavaScript на стороне партнёров вот тут товарищ сделал компактно [11]


var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
eventer(messageEvent, function (e) {
//проверка на соответствие домена    
if (e.origin !== "http://www.bootply.com")
 retrurn;
//непосредственно resize
document.getElementById('myIframe').style.height = e.data + 'px';
}, false);

Полный код на стороне партнёров на Jsfiddle [12]
Bootstrap Modal Iframe Костыль
На Jsfiddle подгружается iframe из Bootply, но Bootply заворачивает в ещё один iframe, который надо убрать (см. рисунок).

Неплохо также добавить общий resize:

$(window).resize(function () {
//но с проверкой на открытый Modal
if ($('#myModal').hasClass('in') == false)
parent.postMessage($("#mainContent").height() + 1, "*");
});

Автор: CrackedSapphire

Источник [13]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/54844

Ссылки в тексте:

[1] iframe с минимальной функцией resize: http://stackoverflow.com/questions/9975810/make-iframe-automatically-adjust-height-according-to-the-contents-without-using?lq=1

[2] ASP.NET MVC: http://www.asp.net/mvc

[3] Azure: http://www.windowsazure.com/

[4] Редмонд: http://www.microsoft.com/

[5] Bootstrap: http://getbootstrap.com/

[6] Modal: http://getbootstrap.com/javascript/#modals-usage

[7] CORS: http://ru.wikipedia.org/wiki/Cross-origin_resource_sharing

[8] HTML5 API window.postMessage: http://javascript.info/tutorial/cross-window-messaging-with-postmessage

[9] библиотек: https://github.com/davidjbradshaw/iframe-resizer

[10] Полный код для iframe на Bootply: http://bootply.com/112265#

[11] тут товарищ сделал компактно: http://davidwalsh.name/window-iframe

[12] Полный код на стороне партнёров на Jsfiddle: http://jsfiddle.net/Vitaliy_Kotov/u2MGv/

[13] Источник: http://habrahabr.ru/post/212347/