29.04.2022, 21:29
|
Профессор
|
|
Регистрация: 08.05.2017
Сообщений: 178
|
|
Отложенная загрузка контента через 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, 29.04.2022 в 21:52.
|
|
29.04.2022, 23:13
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,126
|
|
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>
|
|
29.04.2022, 23:39
|
Профессор
|
|
Регистрация: 08.05.2017
Сообщений: 178
|
|
рони,
Хитро придумано.
Проверил, всё отлично работает!
Большое спасибо!
Написал в личку.
Последний раз редактировалось Vaska, 29.04.2022 в 23:49.
|
|
30.04.2022, 04:22
|
Профессор
|
|
Регистрация: 08.05.2017
Сообщений: 178
|
|
рони,
Вылезла одна проблема: в вызываемых страницах контента, например в 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, 30.04.2022 в 04:30.
|
|
30.04.2022, 08:13
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,126
|
|
Vaska,
так поставьте вместо fetch ваш прежний код, и id вставьте какое вам нужно.
|
|
30.04.2022, 08:22
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,126
|
|
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>
|
|
30.04.2022, 10:02
|
Профессор
|
|
Регистрация: 08.05.2017
Сообщений: 178
|
|
рони,
сейчас всё отлично работает.
Большое спасибо!
|
|
30.04.2022, 20:53
|
Профессор
|
|
Регистрация: 08.05.2017
Сообщений: 178
|
|
рони,
можно ли определить область применения вашего скрипта, через назначение по ID.
Как здесь $(document).on('DOMNodeInserted', '#haupt', function() {
Но ругается, если я добавляю второй аргумент document.addEventListener('DOMContentLoaded', '#haupt', function() { .
Последний раз редактировалось Vaska, 30.04.2022 в 20:57.
|
|
30.04.2022, 21:19
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,126
|
|
Сообщение от Vaska
|
можно ли определить область применения вашего скрипта,
|
???
document.querySelectorAll(' #haupt .inner-content').forEach
|
|
30.04.2022, 21:32
|
Профессор
|
|
Регистрация: 08.05.2017
Сообщений: 178
|
|
рони,
Спасибо!
|
|
|
|