|
Отложенная загрузка контента через 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. Заранее, спасибо, откликнувшимся! |
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> |
рони,
Хитро придумано. Проверил, всё отлично работает! Большое спасибо! Написал в личку. |
рони,
Вылезла одна проблема: в вызываемых страницах контента, например в 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. |
Vaska,
так поставьте вместо fetch ваш прежний код, и id вставьте какое вам нужно. |
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> |
рони,
сейчас всё отлично работает. Большое спасибо! |
рони,
можно ли определить область применения вашего скрипта, через назначение по ID. Как здесь $(document).on('DOMNodeInserted', '#haupt', function() { Но ругается, если я добавляю второй аргумент document.addEventListener('DOMContentLoaded', '#haupt', function() { . |
Цитата:
document.querySelectorAll('#haupt .inner-content').forEach |
рони,
Спасибо! |
Часовой пояс GMT +3, время: 13:32. |
|