Обработка iframe Scroll из родительского окна ScrollBar - PullRequest
3 голосов
/ 27 января 2020

Я создаю iframe, который можно использовать в разных доменах. У iframe есть список данных, при достижении нижней части прокрутки он обновляет больше данных.

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

Мой код выглядит следующим образом:

 <html>
   <body >
      <div>Header</div>
      <iframe
         width='100%'
         height='500px'
         onLoad="window.parent.scroll(0,0);"
         id='iframe'
         src="myIframe.com"></iframe>

       <div>Footer</div>
   </body>
   <script type="text/javascript">
     window.addEventListener('message', function (e) {
         document.getElementById("iframe").height = e.data.frameHeight
       });
 </script>
</html>

Прослушивание сообщения от родителя и установка высоты кадра помогают устранить Прокрутка iframe, но мне нужна эта прокрутка для обновления списка при достижении дна.

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

Ответы [ 3 ]

3 голосов
/ 03 февраля 2020

Короткий ответ

https://github.com/davidjbradshaw/iframe-resizer

Более длинный ответ

Способ выше Библиотека делает это с помощью MutationObserver для обнаружения изменений в DOM в iframe, чтобы вызвать пересчет размера страницы. Сложность возникает из-за необходимости определять, когда изображения в недавно загруженной html также были загружены.

function setupBodyMutationObserver() {
    function addImageLoadListners(mutation) {
      function addImageLoadListener(element) {
        if (false === element.complete) {
          log('Attach listeners to ' + element.src)
          element.addEventListener('load', imageLoaded, false)
          element.addEventListener('error', imageError, false)
          elements.push(element)
        }
      }

      if (mutation.type === 'attributes' && mutation.attributeName === 'src') {
        addImageLoadListener(mutation.target)
      } else if (mutation.type === 'childList') {
        Array.prototype.forEach.call(
          mutation.target.querySelectorAll('img'),
          addImageLoadListener
        )
      }
    }

    function removeFromArray(element) {
      elements.splice(elements.indexOf(element), 1)
    }

    function removeImageLoadListener(element) {
      log('Remove listeners from ' + element.src)
      element.removeEventListener('load', imageLoaded, false)
      element.removeEventListener('error', imageError, false)
      removeFromArray(element)
    }

    function imageEventTriggered(event, type, typeDesc) {
      removeImageLoadListener(event.target)
      sendSize(type, typeDesc + ': ' + event.target.src, undefined, undefined)
    }

    function imageLoaded(event) {
      imageEventTriggered(event, 'imageLoad', 'Image loaded')
    }

    function imageError(event) {
      imageEventTriggered(event, 'imageLoadFailed', 'Image load failed')
    }

    function mutationObserved(mutations) {
      sendSize(
        'mutationObserver',
        'mutationObserver: ' + mutations[0].target + ' ' + mutations[0].type
      )

      // Deal with WebKit / Blink asyncing image loading when tags are injected into the page
      mutations.forEach(addImageLoadListners)
    }

    function createMutationObserver() {
      var target = document.querySelector('body'),
        config = {
          attributes: true,
          attributeOldValue: false,
          characterData: true,
          characterDataOldValue: false,
          childList: true,
          subtree: true
        }

      observer = new MutationObserver(mutationObserved)

      log('Create body MutationObserver')
      observer.observe(target, config)

      return observer
    }

    var elements = [],
      MutationObserver =
        window.MutationObserver || window.WebKitMutationObserver,
      observer = createMutationObserver()

    return {
      disconnect: function() {
        if ('disconnect' in observer) {
          log('Disconnect body MutationObserver')
          observer.disconnect()
          elements.forEach(removeImageLoadListener)
        }
      }
    }
  }

  function setupMutationObserver() {
    var forceIntervalTimer = 0 > interval

    // Not testable in PhantomJS
    /* istanbul ignore if */ if (
      window.MutationObserver ||
      window.WebKitMutationObserver
    ) {
      if (forceIntervalTimer) {
        initInterval()
      } else {
        bodyObserver = setupBodyMutationObserver()
      }
    } else {
      log('MutationObserver not supported in this browser!')
      initInterval()
    }
  }

2 голосов
/ 08 февраля 2020

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

HTML

 <!-- added id to the header and footer ->
<div id="header">Header</div>
<iframe width='100%' id='iframe' src="test.html"></iframe>
<div id="footer">Footer</div>

CSS (необязательно)

/ * необязательно, только для презентационных целей * /

#header,
  #footer {
    height: 50px;
    background-color: #f7f7f7;
    text-align: center;
    font-size: 24px;
    font-weight: bold;
    line-height: 50px;
  }

JS

 // Selecting iframe
 var iframe = document.getElementById("iframe");

 // Adjusting the iframe height onload
 iframe.onload = function() {
   iframe.style.height = document.getElementById('iframe').contentWindow.document.body.scrollHeight + 'px';
 }

 // height of the list item going to be append 
 let itemHeight = 54;

 function fetchListData() {
   // add height to ifame for list item
   iframe.style.height = document.getElementById('iframe').contentWindow.document.body.scrollHeight + itemHeight;

   // append list item in a iframe Ul
   $(iframe).contents().find("ul").append('<li style="height:50px;border:2px solid blue"> new item </li>')
 }


 $(window).on('scroll', function() {

   // to get the scroll amout to reach up to bottom edge of iframe
   let bottom_edge_value = $(document).outerHeight() - $(window).outerHeight() - 5;

   if ($(window).scrollTop() >= bottom_edge_value) {
     fetchListData();
   }
 });

Test. html файл (для включения в iframe)

 <html>
 <head>

 </head>
   <body >
  <p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ullamcorper eros nulla, at vulputate lectus vehicula quis. Vestibulum volutpat finibus gravida. Morbi id sapien molestie, congue erat sit amet, consequat elit. Aliquam volutpat nisi a felis pharetra posuere. Aliquam varius vel sapien quis dignissim. Nam nec faucibus eros, eget volutpat orci. Vestibulum vestibulum tortor velit, ac consequat orci ornare eget.
</p>
<p>
Vivamus eleifend, nunc eget commodo sagittis, ante lorem blandit sem, facilisis mollis metus ipsum sed ex. Aenean quis felis enim. Donec sed felis sit amet risus mollis interdum. Proin commodo facilisis bibendum. Nam non accumsan tortor. Sed gravida leo ut dolor aliquet suscipit. Phasellus metus urna, lobortis et metus id, bibendum dignissim augue. Integer vehicula, ante ut efficitur iaculis, nisi mi pulvinar dui, et rhoncus nibh sem at velit. Cras vehicula massa vitae interdum rhoncus. Fusce viverra aliquam diam, ut sagittis ex ultrices in.
</p>
<p>
Fusce finibus leo tincidunt lacus gravida tincidunt. Nunc euismod molestie leo, ac imperdiet massa elementum nec. Fusce nec varius felis. Fusce ac dictum eros. Suspendisse interdum nunc tristique nisi volutpat, in congue risus dapibus. Quisque aliquam leo ut condimentum ullamcorper. Mauris vehicula, ipsum nec faucibus congue, mi ligula lacinia ipsum, ac venenatis urna urna ac nisl. Duis dui erat, dictum et dui ac, pharetra varius elit. Proin rutrum leo enim, et pellentesque nibh ultrices a.
</p>
<p>
Duis risus turpis, iaculis vel lobortis vitae, suscipit sed lectus. Curabitur varius diam a massa auctor gravida. Donec ullamcorper gravida mi, id mollis metus pretium a. Morbi egestas efficitur justo, at tincidunt quam ornare porta. Quisque nec hendrerit lacus, eu consectetur justo. Pellentesque maximus urna et odio dictum, in pulvinar magna placerat. Sed pellentesque nisl eget nunc venenatis, nec lacinia urna pulvinar. Quisque sit amet imperdiet justo. Proin aliquam, nibh eget tincidunt blandit, quam ipsum elementum nisl, id pellentesque est ipsum semper dui.
</p>
<p>
Curabitur dictum ac odio at mattis. Mauris euismod nibh tincidunt, posuere felis in, iaculis enim. Suspendisse non elit arcu. Nunc aliquet urna quis ex auctor, sed efficitur sapien porttitor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur laoreet metus commodo, tempus velit nec, volutpat diam. Mauris elit libero, tincidunt at massa eu, egestas aliquet mauris. Aliquam dignissim egestas massa, faucibus fermentum mauris commodo nec. Aliquam erat volutpat. Maecenas quis mi interdum, imperdiet nisl eu, suscipit ante. Morbi mollis dui non lectus vulputate, id tristique ipsum bibendum. Sed tempor posuere odio, euismod luctus arcu rutrum ac. Cras aliquam vel tellus id egestas. Suspendisse nec dignissim lorem, in aliquet justo.
</p>
<p>
Duis risus turpis, iaculis vel lobortis vitae, suscipit sed lectus. Curabitur varius diam a massa auctor gravida. Donec ullamcorper gravida mi, id mollis metus pretium a. Morbi egestas efficitur justo, at tincidunt quam ornare porta. Quisque nec hendrerit lacus, eu consectetur justo. Pellentesque maximus urna et odio dictum, in pulvinar magna placerat. Sed pellentesque nisl eget nunc venenatis, nec lacinia urna pulvinar. Quisque sit amet imperdiet justo. Proin aliquam, nibh eget tincidunt blandit, quam ipsum elementum nisl, id pellentesque est ipsum semper dui.
</p>
<p>
Curabitur dictum ac odio at mattis. Mauris euismod nibh tincidunt, posuere felis in, iaculis enim. Suspendisse non elit arcu. Nunc aliquet urna quis ex auctor, sed efficitur sapien porttitor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur laoreet metus commodo, tempus velit nec, volutpat diam. Mauris elit libero, tincidunt at massa eu, egestas aliquet mauris. Aliquam dignissim egestas massa, faucibus fermentum mauris commodo nec. Aliquam erat volutpat. Maecenas quis mi interdum, imperdiet nisl eu, suscipit ante. Morbi mollis dui non lectus vulputate, id tristique ipsum bibendum. Sed tempor posuere odio, euismod luctus arcu rutrum ac. Cras aliquam vel tellus id egestas. Suspendisse nec dignissim lorem, in aliquet justo.
</p>


<ul>
<li> item 1</li>
<li> item 2</li>
<li> item 3</li>
<li> item 4</li>
</ul>
   </body>

</html>
1 голос
/ 07 февраля 2020

Поскольку iframe появится на страницах разных доменов, вам необходимо установить sh связь между родителем и ребенком через postMessage .

Как вы уже описали, вы Нужна свиток ребенка, поэтому, прежде всего, вам нужно будет вынуть свиток родителя. Это может быть достигнуто с помощью CSS правила overflow: hidden;, примененного к body. Вам необходимо реализовать код Javascript для iframe, который отправляет некоторые команды, которые получает родитель. Вам также необходимо внедрить код Javascript в родительском объекте, который получает команды и действует соответствующим образом.

Если это установлено, то дочерний элемент может отправить такую ​​команду, а родительский элемент выполнит ее. Стоит упомянуть, что вам нужно будет предоставить Javascript для родителя вместе с iframe, чтобы выполнить эту работу.

Теперь вы можете захотеть сделать некоторые пользовательские вещи, например, разрешить прокрутка родителя, когда ребенок не находится в фокусе, и позволяет прокручивать ребенка, когда он находится в фокусе. В этом случае вам может понадобиться обратный, то есть родительский элемент для выдачи команд дочернему элементу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...