Как определить, находится ли дочерний элемент iframe в видимой области прокрутки div? - PullRequest
0 голосов
/ 10 декабря 2018

У меня есть элемент прокрутки, который может содержать или не содержать один или несколько элементов iframe, содержимое которых следует загружать, только если элемент iframe частично или полностью виден между верхней и нижней областью прокрутки родительского элемента div.Однако, когда в div есть iframe и когда я проверяю свою веб-страницу в Chrome, я вижу, что значения offsetTop iframe не меняются, поскольку полоса прокрутки родительского div прокручивается вверх или вниз.Кроме того, я вижу, что offsetParent элементов iframes ссылается на элемент body, а не на элемент прокрутки, который фактически содержит элементы iframes.

Вот простая веб-страница, которая показывает базовую структуру div и вложенную структуру iframe, о которой я говорю:

<!DOCTYPE html>
<html>
  <body>
    <!-- Scrolling div -->
    <div id="scroller" style="height:316px; width: 322px; overflow-y:scroll;">
      <!-- 5 iframes that each contain an img tag that is ignored -->
      <iframe><img id="img" src="1.png"></iframe><br />
      <iframe><img id="img" src="2.png"></iframe><br />
      <iframe><img id="img" src="3.png"></iframe><br />
      <iframe><img id="img" src="4.png"></iframe><br />
      <iframe><img id="img" src="5.png"></iframe><br />
    </div>
    <script>
      //
      // Assign an onScroll function to the scroller div that monitors the div's
      // scrolling ...
      //

      function scrollerDivScrolling() {
        var div = scrollerDivScrolling.div;

        //
        // The following code only changes the div's background color when the
        // div's scroll-bar is scrolled: white when less-than or 50px or
        // yellow when more 50px.
        //

        if( div.scrollTop > 50 ) {
          div.style.backgroundColor = "yellow";
        }
        else {
          div.style.backgroundColor = "white";
        }

        //
        // This is code needs to check each of the iframe's position to
        // see if the iframe is displayed partially/fully between the
        // parent div's scroll area's top and bottom, and if so then the
        // iframe's content is set to the html statement(s) that are
        // between to iframe's opening and closing tags.  If the iframe's
        // position is either completely above top of the parent div's
        // scroll area or completely below the parent div's scroll area,
        // then remove the contents.
        //

      }
      scrollerDivScrolling.div          = document.getElementById( 'scroller' );
      scrollerDivScrolling.iframes      = scrollerDivScrolling.div.getElementsByTagName( 'iframe' );
      scrollerDivScrolling.div.onscroll = scrollerDivScrolling;

      // Initialize the iframes with in the scroller div to 'show' their contents ...

      for( var i = 0, iframes = scrollerDivScrolling.iframes, l = iframes.length, iframeDoc = null; i < l; ++i ) {

        iframeDoc = iframes[ i ].contentWindow.document;
        iframeDoc.open();
        iframeDoc.write('Test' + ( i + 1 ) );
        iframeDoc.close();

      }
    </script>
  </body>
</html>

Как показано в приведенном выше коде, iframe фактически загруженыс «Test», за которым следует число, а не оператор тега image, который находится внутри отдельных тегов iframe, но это не проблема, поскольку я уже знаю, как это сделать.Что еще более важно, функция scrollerDivScrolling (), которая обрабатывает прокрутку div, на самом деле не меняет содержимое каждого iframe в зависимости от его положения относительно верхней и нижней области прокрутки родительского div, потому что я не выяснил, какие свойства каждого элементаiframe мне нужно использовать.

1 Ответ

0 голосов
/ 10 декабря 2018

Я расширил свой поиск и обнаружил: Обнаружение, когда элементы в прокручиваемом элементе div не отображаются , которые я интегрировал с моей функцией scrollerDivScrolling () следующим образом:

<script>
  const UNDEFINED = undefined;

  // Assign an onScroll function to the scroller div that monitors the div's scrolling ...

  function checkInView( elem, partial ) {
    var container  = $( '.scrollable' );
    var contHeight = container.height();
    var contTop    = container.scrollTop();
    var contBottom = contTop + contHeight - 1;
    var $elem      = $( elem );

    var elemTop    = $elem.offset().top - container.offset().top;
    var elemBottom = elemTop + $elem.height();

    var isTotal    = ( ( elemTop >= 0 ) && ( elemBottom <= contHeight ) );
    var isPart     = false;

    if( partial ) {
      isPart  = ( ( ( elemTop < 0 ) && ( elemBottom > 0 ) ) || ( ( elemTop > 0 ) && ( elemTop <= container.height() ) ) );
    }

    return ( isTotal || isPart );
  }

  function scrollerDivScrolling() {
    var div = scrollerDivScrolling.div;

    for( var i = 0, iframes = scrollerDivScrolling.iframes, l = iframes.length, iframeDoc = null; i < l; ++i ) {

      // If the element is in the scrollable div's visible area ...

      if( checkInView( scrollerDivScrolling.iframes[ i ], true ) ) {

        // If the element had not already been loaded ...

        if( ( iframes[ i ].loaded === UNDEFINED ) || !iframes[ i ].loaded ) {

          // Mark the element as loaded and load the element ...

          iframes[ i ].loaded = true;
          iframeDoc           = iframes[ i ].contentWindow.document;
          iframeDoc.open();
          iframeDoc.write( 'Test' + ( i + 1 ) + '&nbsp' + iframes[ i ].innerHTML );
          iframeDoc.close();

        }

      }
      else {

        // Mark the element as NOT loaded and unload the element ...

        iframes[ i ].loaded = false;
        iframeDoc           = iframes[ i ].contentWindow.document;
        iframeDoc.open();
        iframeDoc.write( '' );
        iframeDoc.close();

      }

    }

  }
  scrollerDivScrolling.div          = document.getElementById( 'scroller' );
  scrollerDivScrolling.div.onscroll = scrollerDivScrolling;
  scrollerDivScrolling.iframes      = scrollerDivScrolling.div.getElementsByTagName( 'iframe' );

  // Initialize the iframes with in the scroller div to 'show' their contents ...

  for( var i = 0, iframes = scrollerDivScrolling.iframes, l = iframes.length, iframeDoc = null; i < l; ++i ) {

    iframes[ i ].loaded = UNDEFINED;

  }

  scrollerDivScrolling();
</script>

Длямне, функция checkInView (...) показывает, что первые три элемента iframe находятся «в поле зрения», когда скроллер находится полностью сверху, что означает, что функция возвращает true для первых трех элементов в div, даже еслиВысота прокручиваемого div достаточно высока, чтобы показать первые два элемента iframe, но для меня это не проблема.

Используя эту технику, я могу «предварительно загрузить» iframe с помощью HTML, который онибудет отображаться, когда прокручиваемый div прокручивает каждый iframe в поле зрения, а теги img, содержащиеся в каждом iframe, обычно загружают свои изображения по мере их появления.

Для меня это помогает двумя способами: начальная загрузка страницы нене нужно загружать все фреймы, прежде чем страницу можно будет просматривать, и пользователь может начать прокручивать «строки» фреймов »подстраницы, и общий объем памяти, необходимый для хранения всех данных, несколько «сплющен», поскольку загружаются только данные страницы, необходимые для отображаемых элементов, и удаляются скрытые строки в прокручиваемом элементе div.когда их содержимое заменяется на ''.

Вот демонстрационная версия Pen, показывающая рабочий пример того, как это работает: Прокрутка Div из фреймов с задержкой загрузки

...