为什么通过 AJAX infinity scroll 加载的内容加载后高度测量不正确?
Why is the height of content loaded through AJAX infinity scroll not measured correctly after loading?
我正在使用 infinity scroll 将由图片或视频组成的 post 加载到我网站的主要 div(通过 AJAX).该系统的工作原理与任何流行的模因网站非常相似。
问题:每个post左侧都有一个正文部分,右侧有一个社交按钮容器。我希望社交按钮容器在用户滚动时沿着 post 的主体移动,并停在 parent div 的底部,以便他们在到达时可以点赞post 的底部。问题是通过我的 AJAX 滚动函数加载的 post 中的 some 似乎没有正确计算 parents 的高度,它们当浏览器的顶部 window 到达它们时,永远不要移动或直接跳到 parent div 的底部。 Here is a visual illustration 的所需行为。
实现: 我无法编译一个可以模拟 AJAX 请求加载图像和视频的行为的工作 jsFiddle 以及 "scroll" 来电。这是我的实现和调试尝试:
每篇文章结构如下:
<div class="article-container">
<div class="article-body-left"><img src="..."></div>
<div class="social-buttons-right">
<div class="facebook-button">...</div>
</div>
</div>
在每个 AJAX 请求完成后,我尝试使用 on 'scroll' 来确定每个社交按钮容器的位置,并在用户使用 ajaxComplete() 滚动时修改它们:
$(document).ajaxComplete(function() {
bind_sticky_boxes();
});
function bind_sticky_boxes() {
$(window).on('scroll', function() {
$('.social-buttons-right').not('.following').each( function() {
var element = $(this).addClass('following'),
originalY = element.offset().top,
parent_offset = element.parent().offset().top,
parent_height = element.parent().height(),
element_height = element.height(),
destination = originalY+parent_height-element.height() -10;
$(window).on('scroll', function(event) {
var scrollTop = $(window).scrollTop();
if (scrollTop > originalY - 10){
element.css('position','absolute');
element.css('top',(scrollTop - parent_offset + 10) + 'px');
element.css('right', '0px');
if (scrollTop > (destination -10 ) ) {
element.css('top',parent_height-element_height);
element.css('right', '0px');
element.css('bottom', '0px');
}
} else {
element.css('position','relative');
element.css('top','initial');
element.css('left', 'initial');
element.css('right','initial');
element.css('bottom', 'initial');
}
});
});
});
}
调试和注释: 滚动功能在第一个 AJAX 请求后工作正常,但在某些 .social-buttons-right 在站点滚动过程中,不要跟随文章正文或直接跳到 parent div 的底部。
当我检查我发现的行为不当的元素时,它们都有“.following”,这意味着滚动功能已经找到它们,但它们也得到了 css 属性的错误组合bind_sticky_boxes 给了他们。
这让我相信它与图像加载过程中的高度计算有关,所以我使用 requestanimationframe() 稍等一下,然后 setTimeout(function(){..},2000) 触发滚动绑定甚至更晚。 None 其中确实解决了问题(后一个无论如何都不是解决方案。)我也尝试过早一点触发 AJAX 请求,但这似乎对一些原因。
更新: 我现在确信问题与 parent 高度计算有关。我将 css 属性替换为具有相同属性的唯一 classes,并注意到行为不当元素的 class 更改几乎总是发生在 parent div,我认为这是一个强烈的迹象,表明在将它附加到主要 div.
之后,它的高度没有被正确计算。
关于我的无限卷轴。我不包括整个 AJAX,因为我认为它与该问题没有严格关系。但是我通过这种方式将内容附加到主 div 中:
success: function(response){
if ( max_page >= paged){
$('#page').append(response.content);
} else{
has_content = false;
}
loading = false;
}
页面加载完成后,我启动无限滚动。 AJAX 当用户到达 id 为 load-more-posts 的元素时请求触发,该元素位于主包装器下方。
$(window).on('load',function(){
$(window).on('scroll', function() {
var element_position = $('#load-more-posts').offset().top + $('#load-more-posts').outerHeight() - window.innerHeight;
var y_scroll_pos = $(window).scrollTop();
if( ( y_scroll_pos >= element_position ) && !loading) {
paged++;
load_more_posts();
}
});
});
问题是目前各种 height/position 属性的计算绑定到滚动事件,该事件可能会在通过 AJAX 附加的图像加载之前触发,因此计算不正确。为了解决这个问题,我必须将它绑定到加载事件,以确保图像可以使用。
$('.article-body-left img').one('load', function() {
var element = $(this).parent().parent().find('.social-buttons-right'),
originalY = element.offset().top,
parent_offset = element.parent().offset().top,
parent_height = element.parent().height(),
element_height = element.height(),
destination = parent_offset+parent_height-element.height() -10;
//alert("Element offset: "+originalY+"\nParent offset: "+parent_offset+"\nParent height: "+parent_height+"\nElement height: "+element_height+"\nDestination: "+destination);
$(window).on('scroll', function(event) {
var scrollTop = $(window).scrollTop();
if (scrollTop > originalY - 10){
element.removeClass('above').removeClass('below').addClass('along');
element.css('top',(parseInt(scrollTop - parent_offset + 10)) + 'px');
if (scrollTop > (destination -10 ) ) {
element.removeClass('above').removeClass('along').addClass('below');
element.css('top','');
}
} else {
element.removeClass('below').removeClass('along').addClass('above');
element.css('top','');
}
});
}).each(function() {
if(this.complete) $(this).load();
});
CSS:
.along{
position: absolute;
right : 0px;
}
.below{
position: absolute;
right: 0px;
bottom: 0px;
}
.above{
position: relative;
}
我正在使用 infinity scroll 将由图片或视频组成的 post 加载到我网站的主要 div(通过 AJAX).该系统的工作原理与任何流行的模因网站非常相似。
问题:每个post左侧都有一个正文部分,右侧有一个社交按钮容器。我希望社交按钮容器在用户滚动时沿着 post 的主体移动,并停在 parent div 的底部,以便他们在到达时可以点赞post 的底部。问题是通过我的 AJAX 滚动函数加载的 post 中的 some 似乎没有正确计算 parents 的高度,它们当浏览器的顶部 window 到达它们时,永远不要移动或直接跳到 parent div 的底部。 Here is a visual illustration 的所需行为。
实现: 我无法编译一个可以模拟 AJAX 请求加载图像和视频的行为的工作 jsFiddle 以及 "scroll" 来电。这是我的实现和调试尝试:
每篇文章结构如下:
<div class="article-container">
<div class="article-body-left"><img src="..."></div>
<div class="social-buttons-right">
<div class="facebook-button">...</div>
</div>
</div>
在每个 AJAX 请求完成后,我尝试使用 on 'scroll' 来确定每个社交按钮容器的位置,并在用户使用 ajaxComplete() 滚动时修改它们:
$(document).ajaxComplete(function() {
bind_sticky_boxes();
});
function bind_sticky_boxes() {
$(window).on('scroll', function() {
$('.social-buttons-right').not('.following').each( function() {
var element = $(this).addClass('following'),
originalY = element.offset().top,
parent_offset = element.parent().offset().top,
parent_height = element.parent().height(),
element_height = element.height(),
destination = originalY+parent_height-element.height() -10;
$(window).on('scroll', function(event) {
var scrollTop = $(window).scrollTop();
if (scrollTop > originalY - 10){
element.css('position','absolute');
element.css('top',(scrollTop - parent_offset + 10) + 'px');
element.css('right', '0px');
if (scrollTop > (destination -10 ) ) {
element.css('top',parent_height-element_height);
element.css('right', '0px');
element.css('bottom', '0px');
}
} else {
element.css('position','relative');
element.css('top','initial');
element.css('left', 'initial');
element.css('right','initial');
element.css('bottom', 'initial');
}
});
});
});
}
调试和注释: 滚动功能在第一个 AJAX 请求后工作正常,但在某些 .social-buttons-right 在站点滚动过程中,不要跟随文章正文或直接跳到 parent div 的底部。
当我检查我发现的行为不当的元素时,它们都有“.following”,这意味着滚动功能已经找到它们,但它们也得到了 css 属性的错误组合bind_sticky_boxes 给了他们。
这让我相信它与图像加载过程中的高度计算有关,所以我使用 requestanimationframe() 稍等一下,然后 setTimeout(function(){..},2000) 触发滚动绑定甚至更晚。 None 其中确实解决了问题(后一个无论如何都不是解决方案。)我也尝试过早一点触发 AJAX 请求,但这似乎对一些原因。
更新: 我现在确信问题与 parent 高度计算有关。我将 css 属性替换为具有相同属性的唯一 classes,并注意到行为不当元素的 class 更改几乎总是发生在 parent div,我认为这是一个强烈的迹象,表明在将它附加到主要 div.
之后,它的高度没有被正确计算。关于我的无限卷轴。我不包括整个 AJAX,因为我认为它与该问题没有严格关系。但是我通过这种方式将内容附加到主 div 中:
success: function(response){
if ( max_page >= paged){
$('#page').append(response.content);
} else{
has_content = false;
}
loading = false;
}
页面加载完成后,我启动无限滚动。 AJAX 当用户到达 id 为 load-more-posts 的元素时请求触发,该元素位于主包装器下方。
$(window).on('load',function(){
$(window).on('scroll', function() {
var element_position = $('#load-more-posts').offset().top + $('#load-more-posts').outerHeight() - window.innerHeight;
var y_scroll_pos = $(window).scrollTop();
if( ( y_scroll_pos >= element_position ) && !loading) {
paged++;
load_more_posts();
}
});
});
问题是目前各种 height/position 属性的计算绑定到滚动事件,该事件可能会在通过 AJAX 附加的图像加载之前触发,因此计算不正确。为了解决这个问题,我必须将它绑定到加载事件,以确保图像可以使用。
$('.article-body-left img').one('load', function() {
var element = $(this).parent().parent().find('.social-buttons-right'),
originalY = element.offset().top,
parent_offset = element.parent().offset().top,
parent_height = element.parent().height(),
element_height = element.height(),
destination = parent_offset+parent_height-element.height() -10;
//alert("Element offset: "+originalY+"\nParent offset: "+parent_offset+"\nParent height: "+parent_height+"\nElement height: "+element_height+"\nDestination: "+destination);
$(window).on('scroll', function(event) {
var scrollTop = $(window).scrollTop();
if (scrollTop > originalY - 10){
element.removeClass('above').removeClass('below').addClass('along');
element.css('top',(parseInt(scrollTop - parent_offset + 10)) + 'px');
if (scrollTop > (destination -10 ) ) {
element.removeClass('above').removeClass('along').addClass('below');
element.css('top','');
}
} else {
element.removeClass('below').removeClass('along').addClass('above');
element.css('top','');
}
});
}).each(function() {
if(this.complete) $(this).load();
});
CSS:
.along{
position: absolute;
right : 0px;
}
.below{
position: absolute;
right: 0px;
bottom: 0px;
}
.above{
position: relative;
}