Further tweaks to viewport shuffling and dynamic image loading

@BenLubar
v1.18.x
Julian Lam 9 years ago
parent 8ae2afff05
commit 1385d19f64

@ -14,7 +14,7 @@
&[data-state="unloaded"], &[data-state="loading"] { &[data-state="unloaded"], &[data-state="loading"] {
display: inherit; display: inherit;
height: 1rem; height: 0;
opacity: 0; opacity: 0;
} }

@ -10,7 +10,9 @@ define('forum/topic/posts', [
'components' 'components'
], function(pagination, infinitescroll, postTools, navigator, components) { ], function(pagination, infinitescroll, postTools, navigator, components) {
var Posts = {}; var Posts = {
_imageLoaderTimeout: undefined
};
Posts.onNewPost = function(data) { Posts.onNewPost = function(data) {
if (!data || !data.posts || !data.posts.length) { if (!data || !data.posts || !data.posts.length) {
@ -240,70 +242,74 @@ define('forum/topic/posts', [
images.each(function() { images.each(function() {
$(this).attr('data-src', $(this).attr('src')); $(this).attr('data-src', $(this).attr('src'));
$(this).attr('data-state', 'unloaded'); $(this).attr('data-state', 'unloaded');
$(this).attr('src', 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'); $(this).attr('src', 'about:blank');
}); });
$(window).scrollTop(scrollTop + $(document).height() - height);
}; };
Posts.loadImages = function(threshold) { Posts.loadImages = function(threshold) {
/* if (Posts._imageLoaderTimeout) {
If threshold is defined, images loaded above this threshold will modify clearTimeout(Posts._imageLoaderTimeout);
the user's scroll position so they are not scrolled away from content }
they were reading. Images loaded below this threshold will push down content.
If no threshold is defined, loaded images will push down content, as per
default
*/
var images = components.get('post/content').find('img[data-state="unloaded"]'),
visible = images.filter(function() {
return utils.isElementInViewport(this);
}),
scrollTop = $(window).scrollTop(),
adjusting = false,
adjustQueue = [],
adjustPosition = function() {
adjusting = true;
oldHeight = document.body.clientHeight;
// Display the image
$(this).attr('data-state', 'loaded');
newHeight = document.body.clientHeight;
var imageRect = this.getBoundingClientRect();
if (imageRect.top < threshold) {
scrollTop = scrollTop + (newHeight - oldHeight);
$(window).scrollTop(scrollTop);
}
if (adjustQueue.length) { Posts._imageLoaderTimeout = setTimeout(function() {
adjustQueue.pop()(); /*
} else { If threshold is defined, images loaded above this threshold will modify
adjusting = false; the user's scroll position so they are not scrolled away from content
} they were reading. Images loaded below this threshold will push down content.
},
oldHeight, newHeight; If no threshold is defined, loaded images will push down content, as per
default
// For each image, reset the source and adjust scrollTop when loaded */
visible.attr('data-state', 'loading');
visible.each(function(index, image) { var images = components.get('post/content').find('img[data-state="unloaded"]'),
image = $(image); visible = images.filter(function() {
return utils.isElementInViewport(this);
image.on('load', function() { }),
if (!adjusting) { scrollTop = $(window).scrollTop(),
adjustPosition.call(this); adjusting = false,
} else { adjustQueue = [],
adjustQueue.push(adjustPosition.bind(this)); adjustPosition = function() {
adjusting = true;
oldHeight = document.body.clientHeight;
// Display the image
$(this).attr('data-state', 'loaded');
newHeight = document.body.clientHeight;
var imageRect = this.getBoundingClientRect();
if (imageRect.top < threshold) {
scrollTop = scrollTop + (newHeight - oldHeight);
$(window).scrollTop(scrollTop);
}
if (adjustQueue.length) {
adjustQueue.pop()();
} else {
adjusting = false;
}
},
oldHeight, newHeight;
// For each image, reset the source and adjust scrollTop when loaded
visible.attr('data-state', 'loading');
visible.each(function(index, image) {
image = $(image);
image.on('load', function() {
if (!adjusting) {
adjustPosition.call(this);
} else {
adjustQueue.push(adjustPosition.bind(this));
}
});
image.attr('src', image.attr('data-src'));
if (image.parent().attr('href')) {
image.parent().attr('href', image.attr('data-src'));
} }
image.removeAttr('data-src');
}); });
}, 250);
image.attr('src', image.attr('data-src'));
if (image.parent().attr('href')) {
image.parent().attr('href', image.attr('data-src'));
}
image.removeAttr('data-src');
});
}; };
Posts.wrapImagesInLinks = function(posts) { Posts.wrapImagesInLinks = function(posts) {
@ -318,13 +324,10 @@ define('forum/topic/posts', [
Posts.showBottomPostBar = function() { Posts.showBottomPostBar = function() {
var mainPost = components.get('post', 'index', 0); var mainPost = components.get('post', 'index', 0);
var posts = $('[component="post"]'); var posts = $('[component="post"]');
var height = $(document).height();
if (!!mainPost.length && posts.length > 1 && $('.post-bar').length < 2) { if (!!mainPost.length && posts.length > 1 && $('.post-bar').length < 2) {
$('.post-bar').clone().appendTo(mainPost); $('.post-bar').clone().appendTo(mainPost);
$(window).scrollTop($(window).scrollTop() + $(document).height() - height);
} else if (mainPost.length && posts.length < 2) { } else if (mainPost.length && posts.length < 2) {
mainPost.find('.post-bar').remove(); mainPost.find('.post-bar').remove();
$(window).scrollTop($(window).scrollTop() - $(document).height() - height);
} }
}; };

@ -121,20 +121,24 @@ define('navigator', ['forum/pagination', 'components'], function(pagination, com
} }
}); });
var atTop = scrollTop === 0 && parseInt(els.first().attr('data-index'), 10) === 0,
nearBottom = scrollTop + windowHeight > documentHeight - 100 && parseInt(els.last().attr('data-index'), 10) === count - 1;
// check if we are at the top if (atTop) {
if (scrollTop === 0 && parseInt(els.first().attr('data-index'), 10) === 0) {
index = 1; index = 1;
// check if we are near the bottom } else if (nearBottom) {
} else if (scrollTop + windowHeight > documentHeight - 100 && parseInt(els.last().attr('data-index'), 10) === count - 1) {
index = count; index = count;
} }
// If a threshold is undefined, try to determine one based on new index // If a threshold is undefined, try to determine one based on new index
if (threshold === undefined) { if (threshold === undefined) {
var anchorEl = components.get('post/anchor', index - 1); if (atTop) {
var anchorRect = anchorEl.get(0).getBoundingClientRect(); threshold = 0;
threshold = anchorRect.top; } else {
var anchorEl = components.get('post/anchor', index - 1);
var anchorRect = anchorEl.get(0).getBoundingClientRect();
threshold = anchorRect.top;
}
} }
if (typeof navigator.callback === 'function') { if (typeof navigator.callback === 'function') {

Loading…
Cancel
Save