Bootstrap modal в верхней части iframe независимо от положения прокрутки. Как разместить его на экране?

При встраивании приложения Bootstrap в iframe модальные диалоги всегда открываются в верхней части iframe, а не в верхней части экрана. В качестве примера перейдите в http://getbootstrap.com/javascript/ и откройте пример модальной страницы. Затем, используя пример кода ниже, который помещает одну и ту же загрузочную страницу в iframe, найдите модальный файл и откройте его:

<html>
    <head>
    </head>
    <body>
        <table width="100%">
            <tr><td colspan="2" style="height:80px;background-color:red;vertical-align:top">Here some header content I don't control</td></tr>
            <tr><td style="width:230px;height:10080px;background-color:red;vertical-align:top">Here some sidebar content I don't control either</td>
                <td valign="top">
                    <iframe width="100%" height="10000px" 
                        scrolling="no" src="http://getbootstrap.com/javascript/">
                    </iframe>
                </td>
            </tr>
        </table>
    </body>
</html>

Демо в скрипке

Как мне разместить позиционирование модала на экране в этом сценарии?

ОБНОВЛЕНИЕ: К сожалению, мой iFrame не может заполнить экран, и я не могу его устранить, так как он должен вписаться в остальную часть страницы, а сама страница имеет достаточно содержимого для прокрутки. Это не мой дизайн, и я в конечном итоге намерен переработать все это, но сейчас это то, над чем я должен работать. В качестве временного варианта я использую javascript, чтобы сообщить родителям iframe прокручивать вверх, где появляется модальное диалоговое окно. Хотя это приемлемо, это не является желаемым поведением.

Я использую angularjs и библиотеку ui-bootstrap в своем коде, но, как вы можете видеть выше, это проблема с загрузкой.

Ответ 1

Если ваш iframe имеет тот же document.domain, что и родительское окно, или это поддомен, вы можете использовать приведенный ниже код внутри iframe:

    $('#myModal').on('show.bs.modal', function (e) {
        if (window.top.document.querySelector('iframe')) {
            $('#myModal').css('top', window.top.scrollY); //set modal position
        }
    });

show.bs.modal сработает после того, как вы вызовете $ ('# myModal'). show() window.top.scrollY получит позицию scrollY из родительского окна

В случае, если ваш document.domain отличается от родительского, вы можете взломать его, получив позицию onmousedown внутри iframe. Например:

$('#htmlElement').on('mousedown', function (event) {
    event.preventDefault();
    $('#myModal').data('y', event.pageY); // store the mouseY position
    $('#myModal').modal('show');
});
$('#myModal').on('show.bs.modal', function (e) {
    var y = $('#myModal').data('y'); // gets the mouseY position
    $('#myModal').css('top', y);
});

Ответ 2

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

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

TL; DR

  1. Используйте API window.postMessage() - Документация здесь. для связи между родителем и iframe (междоменный)
  2. передать сообщение с currentScrollPosition и позицией Y вашего фрейма
  3. Получать сообщения и обновлять модальные отступы сверху

В моем случае обходным решением было использование API window.postMessage() - Документация здесь. Требуется добавить некоторый дополнительный код к родителю и обработать сообщение в iFrame.

Вы можете добавить EventListener и прослушать событие "прокрутка". Каждый раз, когда вызывается функция обработки события, вы можете получить currentScrollPosition, как document.scrollingElement.scrollTop. Имейте в виду, что ваш iframe может иметь некоторый запас сверху на родительской странице, поэтому вы также должны получить его 'offset'. После этого вы можете опубликовать эти два значения в своем iframe, например ncp_iframe.contentWindow.postMessage(message, '*');

Обратите внимание, что message должен быть строковым значением

После этого в вашем iFrame вам нужно добавить EventListener и прослушать событие message. Функция обработки событий передаст ваше "сообщение" в свойство event.data. Имея это, вы можете обновить модальные отступы. (Выглядит намного лучше, если вы не используете анимацию, например, fade, в классах);

Быстрый пример:

Родитель:

window.addEventListener('scroll', function(event){
  var myIframe = document.querySelector('#myIframe');
  var topOffset = myIframe.getBoundingClientRect().top + window.scrollY;
  var currentScroll = document.scrollingElement.scrollTop;
  myIframe.contentWindow.postMessage(topOffset + ':' + currentScroll, '*');
});

Ответ 3

Это ошибка в большинстве браузеров (IE выглядит отлично), где элементы привязаны к iframe, а не к окну. Как правило, если вам нужно что-то относительно основного документа, оно должно быть в основном документе.

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

HTML

<div class="fixframe">
    <iframe src="http://getbootstrap.com/javascript/"></iframe>
</div>

CSS

.fixframe {
    position: fixed;
    top: 0px;
    left: 0px;
    right: 0px;
    bottom: 0px;    
} 
.fixframe iframe {
   height: 100%;
   width: 100%;  
} 

Рабочая демонстрация в скрипте

См. также:

Ответ 4

Это потому, что класс .modal имеет атрибут position: fixed. Вместо этого попробуйте position: relative.