Как изменить iframe родительской стороны на всю высоту дочерней стороны SAPUI5?

Моя цель — реализовать мой веб-сайт SAPUI5 в iframe, размер которого изменяется до полной высоты содержимого iframe. Веб-сайт, содержащий iframe, находится на другом сервере.

Как передать всю высоту веб-сайта родительской странице? В примерах используется сайт localhost вместо исходного. Используемая версия платформы SAPUI5 — 1.120.

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

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

Родительская сторона:

<script>        
    window.addEventListener('message', receiveMessage, false);

    function receiveMessage(size){
        resizeIFrameToFitContent(size.data);
    }
                
    function resizeIFrameToFitContent(size){
        document.getElementById("exampleFrame").style.height = size;
    }
</script>

Детская сторона:

function postPageSize(){
    size = window.document.body.scrollHeight + "px";
    window.parent.postMessage(size, '*');
}

-- Была также попытка использования интервала и более или менее «динамического» изменения размера страницы. Здесь я получаю сообщение об ошибке «Uncaught DOMException: доступ к свойству «документ» объекта перекрестного происхождения запрещен», которая в настоящее время неразрешима для меня.

Родительская сторона:

<script>
setInterval(function(){
    var pageHeight = document.getElementById("exampleFrame").contentWindow.document.body.offsetHeight;
}, 1000)
</script>

-- Последняя попытка была немного более сложной и использовала некоторые собственные функции. Это также возвращает текущий размер iframe. Следует отметить, что этот код работает на более старой веб-странице, созданной с использованием платформы SAP.

Родительская сторона:

<script>
  window.addEventListener('message', e=>{if (e.origin= = "http://localhost"){
        
        var iFr = document.getElementById("exampleFrame")
        if (iFr && iFr.style.height != e.data) iFr.style.height = e.data
    }})
</script>

<iframe src = "http://localhost/path/to/page" id = "exampleFrame" style = "height:500px"></iframe>

Детская сторона:

function ensureIFrameResizingFor(MainCont){
    setInterval(function(){
        var pgId = MainCont.getCurrentPage().getId() //MainCont is our usual App- or Navigation-Container (which holds "Pages")
        var hFrm = 0, hHdr = 0
        
        var hdr = document.querySelector("#" + pgId + " .sapMPageHeader") 
        if (hdr) hHdr = parseInt("0" + getComputedStyle(hdr).getPropertyValue("height"))
 
        var frm = document.querySelector("#" + pgId + " .sapUiSimpleForm") 
        if (!frm){
            hHdr = 3*hHdr
            frm = document.querySelector("#" + pgId + " .sapUiTableVSbContent") //fallback (second attempt, in case the Page is a Listing-Page)
            if (!frm) frm = document.querySelector("#" + pgId + " .sapMListTblCnt") 
        } 
        if (frm) hFrm = parseInt("0" + getComputedStyle(frm).getPropertyValue("height"))
        //console.info(hFrm, hHdr)

        if (hFrm) top.postMessage((hFrm + hHdr + 18) + "px", PostMsg_CallbackURL)
    }, 500)
}

Обновлено: Получил решение. Мне нужно было извлечь «scrollHeight», выполнив поиск, где обрабатывается полоса прокрутки. Затем функция управляется setInterval, поскольку некоторые элементы на сайте изменяются динамически.

Это готовая дочерняя функция:

function sendSizeToParent(){

    if (document.getElementsByClassName("sapMPageEnableScrolling")[0].scrollHeight != null){

        var height = document.getElementsByClassName("sapMPageEnableScrolling")[0].scrollHeight
        if (window.parent){
            window.parent.postMessage(height, '*');
        }
    }
}

Привет, добро пожаловать в ТАК! Вы говорите, что последняя/третья попытка работает для более старой версии фреймворка, но не работает для текущей версии, верно? Если да, можете ли вы объяснить, почему он не работает или его нельзя адаптировать для работы?

Davi 26.08.2024 14:48

@Davi Видимо, это связано с тем, как была реализована старая версия. Старый веб-сайт, похоже, использует sap.m.Table для реализации полосы прокрутки, а новый — нет. В новой версии используется простой sap.m.Page. Я не на 100% знаком со старым кодом. Но это то, что я понял.

Annika 26.08.2024 15:02

Причина моего вопроса заключалась в том, что последняя/третья попытка использовала .postMessage и .addEventListener('message' ...) (т. е. обмен сообщениями между документами, как и ваша первая) для отправки информации от дочернего элемента (iframe) родительскому элементу (странице) - поэтому мне было интересно, Я попробовал попытку 3, если она в принципе сработала и, как таковая, может быть адаптирована (похоже, что она более или менее просто запрашивает DOM и читает стили). Извините за неясность.

Davi 26.08.2024 15:15

@Дави Дави, ок. «.postMessage» и «.addEventListener», похоже, работают так, как задумано. Но «.postMessage» публикует неправильные данные. При расчете высоты страницы рассчитывается не вся высота, а размер текущего размера страницы внутри iframe. Затем родительская страница получает уже реализованный размер iframe. То же самое происходит, когда я пытаюсь получить «scrollHeight».

Annika 26.08.2024 15:31

Хорошо, тогда проблема не в том, как передать информацию из iframe на страницу, а в том, какая информация отправляется. Создается ли содержимое iframe динамически, так что его окончательные размеры нельзя прочитать сразу после возникновения события load iframe?

Davi 26.08.2024 15:56

@Дави Да, это правильно. Вот почему в некоторых из этих попыток я использовал setInterval. Я попытался отправить изменения обратно родителю вскоре после того, как они произошли.

Annika 27.08.2024 08:55
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
6
62
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Судя по вашим комментариям, вам нужен надежный момент времени, когда sap.m.Page завершил рендеринг, чтобы вы могли затем сообщить родительской странице о высоте.

Изучив документацию SAP UI 5, сводка sap.m.Page показывает, что Page имеет возможность добавить метод onAfterRendering, который он заимствует из sap.ui.core.Control. Согласно документации, этот метод автоматически вызывается после завершения процесса рендеринга.

Поэтому я бы предложил:

На родительской странице вы в основном делаете то же, что и до сих пор:

window.addEventListener('message', (event) => {
  document.getElementById('exampleFrame').style.height = `${event.data}px`;
}); 

Код внутри iframe должен использовать .postMessage внутри метода onAfterRendering, тогда:

// please adjust accordingly
onAfterRendering() {
  const height = document.body.scrollHeight;
  if (window.parent) { // only post if placed inside an iframe
    window.parent.postMessage(height, '*');
  }
}

Помните, что вам необходимо определить onAfterRendering в своем экземпляре sap.m.Page. Возможно, вам придется настроить показанный пример кода в соответствии с остальной частью вашего кода, например:

page.onAfterRendering = function() {
  const height = document.body.scrollHeight;
  if (window.parent) { // only post if placed inside an iframe
    window.parent.postMessage(height, '*');
  }
}

К сожалению, я все еще получаю неправильное значение. Функция onAfterRendering работает и продвинула меня немного дальше. Но собранное значение по-прежнему равно размеру самого iframe, а не всей длины страницы.

Annika 28.08.2024 07:57

Итак, мы добились прогресса. Пожалуйста, отредактируйте свой вопрос, включив в него соответствующие стили. Если вы все еще получаете высоту iframe, то я предполагаю, что где-то в вашем CSS есть overflow и height, установленные для элемента <body>, и вы прокручиваете в другом контейнере. К сожалению, я не могу вам помочь, не видя больше вашего кода, и я просто догадываюсь, в чем может быть проблема.

Davi 28.08.2024 08:34

Я решил это. Я нашел элемент, содержащий общую высоту прокрутки. Он был определен в определенном классе, который я некоторое время искал. Изменения описаны в исходном посте.

Annika 28.08.2024 11:23

@Анника, здорово! :)

Davi 28.08.2024 11:26

Другие вопросы по теме