Further tweaks to viewport shuffling and dynamic image loading

@BenLubar
v1.18.x
Julian Lam 10 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 Posts._imageLoaderTimeout = setTimeout(function() {
default /*
*/ If threshold is defined, images loaded above this threshold will modify
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.
var images = components.get('post/content').find('img[data-state="unloaded"]'), If no threshold is defined, loaded images will push down content, as per
visible = images.filter(function() { default
return utils.isElementInViewport(this); */
}),
scrollTop = $(window).scrollTop(),
adjusting = false,
adjustQueue = [],
adjustPosition = function() {
adjusting = true;
oldHeight = document.body.clientHeight;
// Display the image var images = components.get('post/content').find('img[data-state="unloaded"]'),
$(this).attr('data-state', 'loaded'); visible = images.filter(function() {
newHeight = document.body.clientHeight; return utils.isElementInViewport(this);
}),
scrollTop = $(window).scrollTop(),
adjusting = false,
adjustQueue = [],
adjustPosition = function() {
adjusting = true;
oldHeight = document.body.clientHeight;
var imageRect = this.getBoundingClientRect(); // Display the image
if (imageRect.top < threshold) { $(this).attr('data-state', 'loaded');
scrollTop = scrollTop + (newHeight - oldHeight); newHeight = document.body.clientHeight;
$(window).scrollTop(scrollTop);
} var imageRect = this.getBoundingClientRect();
if (imageRect.top < threshold) {
if (adjustQueue.length) { scrollTop = scrollTop + (newHeight - oldHeight);
adjustQueue.pop()(); $(window).scrollTop(scrollTop);
} else { }
adjusting = false;
} if (adjustQueue.length) {
}, adjustQueue.pop()();
oldHeight, newHeight; } else {
adjusting = false;
// For each image, reset the source and adjust scrollTop when loaded }
visible.attr('data-state', 'loading'); },
visible.each(function(index, image) { oldHeight, newHeight;
image = $(image);
// For each image, reset the source and adjust scrollTop when loaded
image.on('load', function() { visible.attr('data-state', 'loading');
if (!adjusting) { visible.each(function(index, image) {
adjustPosition.call(this); image = $(image);
} else {
adjustQueue.push(adjustPosition.bind(this)); 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