Javascript-форум (https://javascript.ru/forum/)
-   Работа (https://javascript.ru/forum/job/)
-   -   Отложенная загрузка контента через div Ajax'ом (https://javascript.ru/forum/job/83968-otlozhennaya-zagruzka-kontenta-cherez-div-ajax%27om.html)

Vaska 29.04.2022 21:29

Отложенная загрузка контента через div Ajax'ом
 
Приветствую!
Есть страница .HTML:
<html>
	<head>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
		<style>
			header {
				background: cyan;
				min-height: 100px;
			}

			.content_container {

				background: rgba(255, 0, 0, 0.3);
				padding: 20px;
                display: none;
			}

			.inner-content {
				height: 400px;
				margin: 5px;
				background: red;
			}

			footer {
				background: cyan;
				min-height: 500px;
			}
		</style>
	</head>
	<body>
		<header>
			<div>other content</div>
			<p>text two</p>
		</header>
		
		<div id="haupt">
			<div id="acidhaupt" class="haupt-wrap background-color">
				<div class="content_container">
					<div id="content_a" class="inner-content"></div>
					<div id="content_b" class="inner-content"></div>
					<div id="content_c" class="inner-content"></div>
					<div id="content_d" class="inner-content"></div>     
				</div>
			</div>
		</div>					
		<footer>
			<p>footer content</p>
		</footer>
		<script>
			$(function () {
				$("#content_a").load("/first.html", function(){
					if($(this).html() != '') {
						$(this).show();
					}				
				}); 
				$("#content_b").load("/second.html", function(){
					if($(this).html() != '') {
						$(this).show();
					}				
				}); 
				$("#content_c").load("/third.html", function(){
					if($(this).html() != '') {
						$(this).show();
					}				
				}); 
				$("#content_d").load("/fourth.html", function(){
					if($(this).html() != '') {
						$(this).show();
					}				
				}); 
			}); 				
		</script>
	</body>
</html>

На странице выводится 4 блока, в которые подгружается Ajax'ом разный контент.
После первой загрузки страницы, часть блоков, которые видимы, грузятся Ajax'ом сразу, а остальные блоки, которые находятся за пределами экрана, не должны загружаться.
Невидимые блоки должны подгружаться по мере видимости при прокрутке скролла вниз или вверх, в зависимости на каком уровне просмотра перезагрузили страницу или открыли новую страницу, заранее за 50px..
Почитал про IntersectionObserver, но я могу его сделать только под каждый div индивидуально, это слишком много кода для многих блоков, а мне нужно сделать оптимизированный код:
один общий скрипт, с применением IntersectionObserver, который можно разместить внизу футера, и в div добавлять активный class, для активации функции отложенной загрузки для этого дива, а для вызов Ajax обернуть в функцию этого скрипта. У каждого div свой Ajax, который вызывает свой файл .html с контентом.

За решение этой задачи предлагаю 500 руб., после выполнения задания, на карту банка в РФ, или на yoomoney.ru.

Заранее, спасибо, откликнувшимся!

рони 29.04.2022 23:13

Vaska,
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <style>
        header {
            background: cyan;
            min-height: 100px;
        }

        .content_container {

            background: rgba(255, 0, 0, 0.3);
            padding: 20px;

        }

        .inner-content {
            height: 400px;
            margin: 5px;
            background: red;
            overflow: hidden;
        }

        footer {
            background: cyan;
            min-height: 500px;
        }
  </style>
  <title></title>
</head>
<body>
  <header>
    <div>
      other content
    </div>
    <p>text two</p>
  </header>
  <div id="haupt">
    <div id="acidhaupt" class="haupt-wrap background-color">
      <div class="content_container">
        <div class="inner-content" data-url="/first.html"></div>
        <div class="inner-content" data-url="/second.html"></div>
        <div class="inner-content" data-url="/third.html"></div>
        <div class="inner-content" data-url="/fourth.html"></div>
      </div>
    </div>
  </div>
  <footer>
    <p>footer content</p>
  </footer>
  <script>
        document.addEventListener('DOMContentLoaded', function() {
            const lazyShow = divs => {
                divs.forEach(e => {
                    if (e.intersectionRatio < .3) return;
                    let div = e.target,
                        url = div.dataset.url;
                    (async () => {
                        let response = await fetch(url);
                        let html = await response.text();
                        div.innerHTML = html;
                    })()
                    observer.unobserve(div);
                });
            };
            let observer = new IntersectionObserver(lazyShow, {
                rootMargin: "50px",
                threshold: [.3]
            });
            document.querySelectorAll('.inner-content').forEach(div => observer.observe(div))

        });
  </script>
</body>
</html>

Vaska 29.04.2022 23:39

рони,
Хитро придумано.
Проверил, всё отлично работает!
Большое спасибо!
Написал в личку.

Vaska 30.04.2022 04:22

рони,
Вылезла одна проблема: в вызываемых страницах контента, например в third.html, перестал инициализироваться ID в DIV'е (например id="mc_point_info"), к которому привязан скрипт, размещённый в этой странице third.html.
Теперь, чтобы инициализировать ID, мне пришлось вынести скрипт из файла third.html - на страницу, из которой вызывается third.html и обернуть его в DOMNodeInserted.

Так работает:
$.getScript("{$Think.PLUGINS_SITE_ROOT}/jquery.SuperSlide.2.1.3.js", function() {
		$(document).on('DOMNodeInserted', '#ds-bundling', function() {
			setTimeout( function(){
				jQuery('.mc_point_info').slide({mainCell:"ul",effect:"left",trigger:"click",switchLoad:"_src",delayTime:1000,prevCell:".btn-prev",nextCell:".btn-next",vis:5});
			}, 0);
		});
	});

Раньше было так:
$.getScript("{$Think.PLUGINS_SITE_ROOT}/jquery.SuperSlide.2.1.3.js", function() {
        jQuery('.mc_point_info').slide({mainCell:"ul",effect:"left",trigger:"click",switchLoad:"_src",delayTime:1000,prevCell:".btn-prev",nextCell:".btn-next",vis:5});
	});


По причине того, что из файла third.html приходится переносить вызов скрипта на страницу, откуда я хотел убрать всё лишнее, немного потерялся смысл.
Почему при простом вызове Ajax'ом файла third.html id="mc_point_info" инициализировался скриптом внутри id="mc_point_info", а сейчас нет?
Может возможно учесть это в вашем коде?
С другими файлами, которые вызываются вашим скриптом, где есть скрипты - такая же беда.
Или можно обернуть скрипт внутри файла third.html, чтобы его не выносить из файла, и чтобы он инициализировал id="mc_point_info"?
У меня не получилось. Получилось только когда вынес в файл из которого вызывается файл third.html.

рони 30.04.2022 08:13

Vaska,
так поставьте вместо fetch ваш прежний код, и id вставьте какое вам нужно.

рони 30.04.2022 08:22

Vaska,
как-то так, зачем нужно id не понимаю, jquery учитывает скрипты на странице, парсит и запускает отдельно, и то что вы сделали вручную, там заложено.
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <style>
        header {
            background: cyan;
            min-height: 100px;
        }

        .content_container {

            background: rgba(255, 0, 0, 0.3);
            padding: 20px;

        }

        .inner-content {
            height: 400px;
            margin: 5px;
            background: red;
            overflow:  scroll;
        }

        footer {
            background: cyan;
            min-height: 500px;
        }
  </style>
  <title></title>
</head>
<body>
  <header>
    <div>
      other content
    </div>
    <p>text two</p>
  </header>
  <div id="haupt">
    <div id="acidhaupt" class="haupt-wrap background-color">
      <div class="content_container">
        <div id="content_a" class="inner-content" data-url="/first.html"></div>
        <div id="content_b" class="inner-content" data-url="/second.html"></div>
        <div id="content_c" class="inner-content" data-url="/third.html"></div>
        <div id="content_d" class="inner-content" data-url="/fourth.html"></div>
      </div>
    </div>
  </div>
  <footer>
    <p>footer content</p>
  </footer>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  <script>
        document.addEventListener('DOMContentLoaded', function() {
            const lazyShow = divs => {
                divs.forEach(e => {
                    if (e.intersectionRatio < .3) return;
                    let div = e.target,
                        url = div.dataset.url;
                    $(div).load(url);
                    observer.unobserve(div);
                });
            };
            let observer = new IntersectionObserver(lazyShow, {
                rootMargin: "10px",
                threshold: [.3]
            });
            document.querySelectorAll('.inner-content').forEach(div => observer.observe(div))

        });
  </script>
</body>
</html>

Vaska 30.04.2022 10:02

рони,
сейчас всё отлично работает.
Большое спасибо!

Vaska 30.04.2022 20:53

рони,
можно ли определить область применения вашего скрипта, через назначение по ID.
Как здесь $(document).on('DOMNodeInserted', '#haupt', function() {
Но ругается, если я добавляю второй аргумент document.addEventListener('DOMContentLoaded', '#haupt', function() { .

рони 30.04.2022 21:19

Цитата:

Сообщение от Vaska
можно ли определить область применения вашего скрипта,

???
document.querySelectorAll('#haupt .inner-content').forEach

Vaska 30.04.2022 21:32

рони,
Спасибо!


Часовой пояс GMT +3, время: 21:55.