reverse infinite loading

v1.18.x
Baris Soner Usakli 11 years ago
parent 7918a23835
commit 21367a1847

@ -47,8 +47,6 @@ var ajaxify = {};
// Remove trailing slash // Remove trailing slash
url = url.replace(/\/$/, ""); url = url.replace(/\/$/, "");
var hash = window.location.hash;
if (url.indexOf(RELATIVE_PATH.slice(1)) !== -1) { if (url.indexOf(RELATIVE_PATH.slice(1)) !== -1) {
url = url.slice(RELATIVE_PATH.length); url = url.slice(RELATIVE_PATH.length);
} }
@ -66,13 +64,18 @@ var ajaxify = {};
tpl_url = url; tpl_url = url;
} }
var hash = '';
if(ajaxify.initialLoad && window.location.href.search(/#[0-9]+$/) !== -1) {
hash = window.location.hash ? window.location.hash : '';
}
if (templates.is_available(tpl_url) && !templates.force_refresh(tpl_url)) { if (templates.is_available(tpl_url) && !templates.force_refresh(tpl_url)) {
ajaxify.currentPage = tpl_url; ajaxify.currentPage = tpl_url;
if (window.history && window.history.pushState) { if (window.history && window.history.pushState) {
window.history[!quiet ? 'pushState' : 'replaceState']({ window.history[!quiet ? 'pushState' : 'replaceState']({
url: url url: url + hash
}, url, RELATIVE_PATH + '/' + url); }, url, RELATIVE_PATH + '/' + url + hash);
$.ajax(RELATIVE_PATH + '/plugins/fireHook', { $.ajax(RELATIVE_PATH + '/plugins/fireHook', {
type: 'PUT', type: 'PUT',
@ -110,16 +113,6 @@ var ajaxify = {};
jQuery('#content, #footer').stop(true, true).removeClass('ajaxifying'); jQuery('#content, #footer').stop(true, true).removeClass('ajaxifying');
ajaxify.initialLoad = false; ajaxify.initialLoad = false;
if (window.location.hash) {
hash = window.location.hash;
}
if (hash) {
require(['forum/topic'], function(topic) {
topic.scrollToPost(hash.substr(1));
});
}
app.refreshTitle(url); app.refreshTitle(url);
$(window).trigger('action:ajaxify.end', { url: url }); $(window).trigger('action:ajaxify.end', { url: url });
}, url); }, url);
@ -165,7 +158,6 @@ var ajaxify = {};
var url = this.href.replace(rootUrl + '/', ''); var url = this.href.replace(rootUrl + '/', '');
if (ajaxify.go(url)) { if (ajaxify.go(url)) {
e.preventDefault(); e.preventDefault();
} }
} else if (window.location.pathname !== '/outgoing') { } else if (window.location.pathname !== '/outgoing') {

@ -420,13 +420,20 @@ var socket,
}); });
}; };
var previousScrollTop = 0;
app.enableInfiniteLoading = function(callback) { app.enableInfiniteLoading = function(callback) {
$(window).off('scroll').on('scroll', function() { $(window).off('scroll').on('scroll', function() {
var top = $(window).height() * 0.1;
var bottom = ($(document).height() - $(window).height()) * 0.9; var bottom = ($(document).height() - $(window).height()) * 0.9;
var currentScrollTop = $(window).scrollTop();
if ($(window).scrollTop() > bottom) { if($(window).scrollTop() < top && previousScrollTop > currentScrollTop) {
callback(); callback(-1);
} else if ($(window).scrollTop() > bottom && previousScrollTop < currentScrollTop) {
callback(1);
} }
previousScrollTop = currentScrollTop;
}); });
} }

@ -16,6 +16,7 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
}); });
Topic.init = function() { Topic.init = function() {
var expose_tools = templates.get('expose_tools'), var expose_tools = templates.get('expose_tools'),
tid = templates.get('topic_id'), tid = templates.get('topic_id'),
thread_state = { thread_state = {
@ -49,8 +50,6 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
showBottomPostBar(); showBottomPostBar();
updateHeader();
if (thread_state.locked === '1') set_locked_state(true); if (thread_state.locked === '1') set_locked_state(true);
if (thread_state.deleted === '1') set_delete_state(true); if (thread_state.deleted === '1') set_delete_state(true);
if (thread_state.pinned === '1') set_pinned_state(true); if (thread_state.pinned === '1') set_pinned_state(true);
@ -336,10 +335,15 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
enableInfiniteLoading(); enableInfiniteLoading();
var bookmark = localStorage.getItem('topic:' + tid + ':bookmark'); var bookmark = localStorage.getItem('topic:' + tid + ':bookmark');
if(window.location.hash) {
Topic.scrollToPost(window.location.hash.substr(1));
} else if(bookmark) {
if(bookmark) { if(bookmark) {
Topic.scrollToPost(parseInt(bookmark, 10)); Topic.scrollToPost(parseInt(bookmark, 10));
} }
} else {
updateHeader();
}
$('#post-container').on('mouseenter', '.favourite-tooltip', function(e) { $('#post-container').on('mouseenter', '.favourite-tooltip', function(e) {
if (!$(this).data('users-loaded')) { if (!$(this).data('users-loaded')) {
@ -356,10 +360,31 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
function enableInfiniteLoading() { function enableInfiniteLoading() {
if(!config.usePagination) { if(!config.usePagination) {
$('.pagination-block').removeClass('hide'); $('.pagination-block').removeClass('hide');
app.enableInfiniteLoading(function() {
app.enableInfiniteLoading(function(direction) {
if (!infiniteLoaderActive && $('#post-container').children().length) { if (!infiniteLoaderActive && $('#post-container').children().length) {
loadMorePosts(tid, function(posts) { var after = 0;
var el = null;
if(direction > 0) {
el = $('#post-container .post-row.infiniteloaded').last();
after = parseInt(el.attr('data-index'), 10) + 1;
} else {
el = $('#post-container .post-row.infiniteloaded').first();
after = parseInt(el.attr('data-index'), 10);
after -= config.postsPerPage;
if(after < 0) {
after = 0;
}
}
var offset = el.offset().top - $('#header-menu').offset().top + $('#header-menu').height();
loadMorePosts(tid, after, function() {
fixDeleteStateForPosts(); fixDeleteStateForPosts();
if(direction < 0 && el) {
Topic.scrollToPost(el.attr('data-pid'), 0, offset);
}
}); });
} }
}); });
@ -1080,51 +1105,58 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
$('#header-topic-title').html('').hide(); $('#header-topic-title').html('').hide();
} }
if (scrollTop < jQuery('.posts > .post-row:first-child').height() && Topic.postCount > 1) { $($('.posts > .post-row').get().reverse()).each(function() {
localStorage.removeItem("topic:" + tid + ":bookmark"); var el = $(this);
paginationEl.html('1 out of ' + Topic.postCount);
progressBar.width(0);
return; if (elementInView(el)) {
var index = parseInt(el.attr('data-index'), 10) + 1;
if(index > Topic.postCount) {
index = Topic.postCount;
} }
paginationEl.html(index + ' out of ' + Topic.postCount);
progressBar.width((index / Topic.postCount * 100) + '%');
return false;
}
});
var count = 0, smallestNonNegative = 0; $('.posts > .post-row').each(function() {
var el = $(this);
jQuery('.posts > .post-row:not(".deleted")').each(function() { if (elementInView(el)) {
count++; var index = parseInt(el.attr('data-index'), 10) + 1;
this.postnumber = count; if(index === 0) {
localStorage.removeItem("topic:" + tid + ":bookmark");
} else {
localStorage.setItem("topic:" + tid + ":bookmark", el.attr('data-pid'));
}
return false;
}
});
}
function elementInView(el) {
var scrollTop = $(window).scrollTop();
var scrollBottom = scrollTop + $(window).height();
var el = jQuery(this);
var elTop = el.offset().top; var elTop = el.offset().top;
var height = Math.floor(el.height()); var height = Math.floor(el.height());
var elBottom = elTop + (height < 300 ? height : 300); var elBottom = elTop + height;
var inView = ((elBottom >= scrollTop) && (elTop <= scrollBottom) && (elBottom <= scrollBottom) && (elTop >= scrollTop));
if (inView) { return ((elBottom >= scrollTop) &&
if(elTop - scrollTop > smallestNonNegative) { (elTop <= scrollBottom) &&
localStorage.setItem("topic:" + tid + ":bookmark", el.attr('data-pid')); (elBottom <= scrollBottom) &&
smallestNonNegative = Number.MAX_VALUE; (elTop >= scrollTop));
} }
paginationEl.html((this.postnumber-1) + ' out of ' + Topic.postCount); Topic.scrollToPost = function(pid, duration, offset) {
progressBar.width(((this.postnumber-1) / Topic.postCount * 100) + '%'); if (!pid) {
} return;
});
setTimeout(function() {
if (scrollTop + windowHeight == jQuery(document).height() && !infiniteLoaderActive) {
paginationEl.html(Topic.postCount + ' out of ' + Topic.postCount);
progressBar.width('100%');
} }
}, 100); if(!offset) {
offset = 0;
} }
Topic.scrollToPost = function(pid) { if($('#post_anchor_' + pid).length) {
if (!pid) { return scrollToPid(pid);
return;
} }
if(config.usePagination) { if(config.usePagination) {
@ -1139,38 +1171,37 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
} }
}); });
} else { } else {
socket.emit('posts.getPidIndex', pid, function(err, index) {
if(err) {
return;
}
var tid = $('#post-container').attr('data-tid');
$('#post-container').empty();
var after = index - config.postsPerPage + 1;
if(after < 0) {
after = 0;
}
loadMorePosts(tid, after, function() {
scrollToPid(pid); scrollToPid(pid);
});
});
} }
function scrollToPid(pid) { function scrollToPid(pid) {
var container = $(window), var scrollTo = $('#post_anchor_' + pid),
scrollTo = $('#post_anchor_' + pid),
tid = $('#post-container').attr('data-tid'); tid = $('#post-container').attr('data-tid');
function animateScroll() { function animateScroll() {
$('window,html').animate({ $('window,html').animate({
scrollTop: scrollTo.offset().top + container.scrollTop() - $('#header-menu').height() scrollTop: scrollTo.offset().top - $('#header-menu').height() - offset
}, 400); }, duration !== undefined ? duration : 400, function() {
updateHeader();
});
} }
if (!scrollTo.length && tid) {
var intervalID = setInterval(function () {
loadMorePosts(tid, function (posts) {
scrollTo = $('#post_anchor_' + pid);
if (tid && scrollTo.length) { if (tid && scrollTo.length) {
animateScroll(); animateScroll();
} }
if (!posts.length || scrollTo.length)
clearInterval(intervalID);
});
}, 100);
} else if (tid) {
animateScroll();
}
} }
} }
@ -1188,7 +1219,7 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
}); });
} }
function createNewPosts(data, infiniteLoaded) { function createNewPosts(data, infiniteLoaded, callback) {
if(!data || (data.posts && !data.posts.length)) { if(!data || (data.posts && !data.posts.length)) {
return; return;
} }
@ -1199,12 +1230,14 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
}); });
} }
function findInsertionPoint() {
var after = null, var after = null,
firstPid = data.posts[0].pid; before = null;
function findInsertionPoint() {
var firstPid = parseInt(data.posts[0].pid, 10);
$('#post-container li[data-pid]').each(function() { $('#post-container li[data-pid]').each(function() {
if(parseInt(firstPid, 10) > parseInt($(this).attr('data-pid'), 10)) { if(firstPid > parseInt($(this).attr('data-pid'), 10)) {
after = $(this); after = $(this);
if(after.next().length && after.next().hasClass('post-bar')) { if(after.next().length && after.next().hasClass('post-bar')) {
after = after.next(); after = after.next();
@ -1213,7 +1246,13 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
return false; return false;
} }
}); });
return after;
if(!after) {
var firstPost = $('#post-container .post-row').first();
if(firstPid < parseInt(firstPost.attr('data-pid'), 10)) {
before = firstPost;
}
}
} }
removeAlreadyAddedPosts(); removeAlreadyAddedPosts();
@ -1221,7 +1260,7 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
return; return;
} }
var insertAfter = findInsertionPoint(); findInsertionPoint();
parseAndTranslatePosts(data, function(translatedHTML) { parseAndTranslatePosts(data, function(translatedHTML) {
var translated = $(translatedHTML); var translated = $(translatedHTML);
@ -1230,25 +1269,21 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
translated.removeClass('infiniteloaded'); translated.removeClass('infiniteloaded');
} }
translated.insertAfter(insertAfter) if(after) {
.hide() translated.insertAfter(after)
.fadeIn('slow'); } else if(before) {
translated.insertBefore(before);
// Remove the extra post-bar and "follow" button that gets added } else {
var postsEl = $('.posts'); $('#post-container').append(translated);
postsEl.find('.post-bar').each(function(idx, el) {
if (idx !== 0) {
el.parentNode.removeChild(el);
}
});
postsEl.find('li.post-row[data-index]').each(function(idx, el) {
followEl = el.querySelector('.follow');
if (idx !== 0 && followEl) {
followEl.parentNode.removeChild(followEl);
} }
});
onNewPostsLoaded(data.posts); translated.hide().fadeIn('slow');
onNewPostsLoaded(translated, data.posts);
if(typeof callback === 'function') {
callback();
}
}); });
} }
@ -1258,7 +1293,7 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
} }
function onNewPostsLoaded(posts) { function onNewPostsLoaded(html, posts) {
for (var x = 0, numPosts = posts.length; x < numPosts; x++) { for (var x = 0, numPosts = posts.length; x < numPosts; x++) {
socket.emit('posts.getPrivileges', posts[x].pid, function(err, privileges) { socket.emit('posts.getPrivileges', posts[x].pid, function(err, privileges) {
if(err) { if(err) {
@ -1273,8 +1308,9 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
app.populateOnlineUsers(); app.populateOnlineUsers();
app.createUserTooltips(); app.createUserTooltips();
app.addCommasToNumbers(); app.addCommasToNumbers();
$('span.timeago').timeago(); app.makeNumbersHumanReadable($('.human-readable-number'));
$('.post-content img').addClass('img-responsive'); html.find('span.timeago').timeago();
html.find('.post-content img').addClass('img-responsive');
updatePostCount(); updatePostCount();
showBottomPostBar(); showBottomPostBar();
} }
@ -1304,41 +1340,39 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
}); });
} }
function loadMorePosts(tid, callback) { function loadMorePosts(tid, after, callback) {
var indicatorEl = $('.loading-indicator'); var indicatorEl = $('.loading-indicator');
if (infiniteLoaderActive) { if (infiniteLoaderActive || !$('#post-container').length) {
return;
}
if(after === 0 && $('#post-container li.post-row[data-index="0"]').length) {
return; return;
} }
if (indicatorEl.attr('done') === '0') {
infiniteLoaderActive = true; infiniteLoaderActive = true;
indicatorEl.fadeIn(); indicatorEl.fadeIn();
socket.emit('topics.loadMore', { socket.emit('topics.loadMore', {
tid: tid, tid: tid,
after: parseInt($('#post-container .post-row.infiniteloaded').last().attr('data-index'), 10) + 1 after: after
}, function (err, data) { }, function (err, data) {
infiniteLoaderActive = false;
indicatorEl.fadeOut();
if(err) { if(err) {
return app.alertError(err.message); return app.alertError(err.message);
} }
infiniteLoaderActive = false;
if (data && data.posts && data.posts.length) { if (data && data.posts && data.posts.length) {
indicatorEl.attr('done', '0'); createNewPosts(data, true, callback);
createNewPosts(data, true);
} else { } else {
indicatorEl.attr('done', '1');
updateHeader(); updateHeader();
} if (typeof callback === 'function') {
indicatorEl.fadeOut();
if (callback) {
callback(data.posts); callback(data.posts);
} }
});
} }
});
} }
return Topic; return Topic;

@ -65,9 +65,7 @@
</div> </div>
<div class="btn-group"> <div class="btn-group">
<!-- IF @first -->
<button class="btn btn-sm btn-default follow" type="button" title="[[topic:notify_me]]"><i class="fa fa-eye"></i></button> <button class="btn btn-sm btn-default follow" type="button" title="[[topic:notify_me]]"><i class="fa fa-eye"></i></button>
<!-- ENDIF @first -->
<button class="btn btn-sm btn-default flag" type="button" title="[[topic:flag_title]]"><i class="fa fa-flag-o"></i></button> <button class="btn btn-sm btn-default flag" type="button" title="[[topic:flag_title]]"><i class="fa fa-flag-o"></i></button>
<button data-favourited="{posts.favourited}" class="favourite favourite-tooltip btn btn-sm btn-default <!-- IF posts.favourited --> btn-warning <!-- ENDIF posts.favourited -->" type="button"> <button data-favourited="{posts.favourited}" class="favourite favourite-tooltip btn btn-sm btn-default <!-- IF posts.favourited --> btn-warning <!-- ENDIF posts.favourited -->" type="button">
<span class="favourite-text">[[topic:favourite]]</span> <span class="favourite-text">[[topic:favourite]]</span>
@ -157,7 +155,6 @@
<div style="clear:both;"></div> <div style="clear:both;"></div>
</li> </li>
<!-- IF @first -->
<li class="well post-bar" data-index="{posts.index}"> <li class="well post-bar" data-index="{posts.index}">
<div class="inline-block"> <div class="inline-block">
<small class="topic-stats"> <small class="topic-stats">
@ -189,7 +186,6 @@
</div> </div>
<div style="clear:both;"></div> <div style="clear:both;"></div>
</li> </li>
<!-- ENDIF @first -->
<!-- END posts --> <!-- END posts -->
</ul> </ul>

@ -525,6 +525,16 @@ var db = require('./database'),
}); });
}); });
}); });
};
Posts.getPidIndex = function(pid, callback) {
Posts.getPostField(pid, 'tid', function(err, tid) {
if(err) {
return callback(err);
}
db.sortedSetRank('tid:' + tid + ':posts', pid, callback);
});
} }
}(exports)); }(exports));

@ -205,7 +205,6 @@ var path = require('path'),
}); });
app.get('/topic/:id/:slug?', function (req, res, next) { app.get('/topic/:id/:slug?', function (req, res, next) {
var uid = (req.user) ? req.user.uid : 0; var uid = (req.user) ? req.user.uid : 0;
var page = 1; var page = 1;
if(req.query && req.query.page) { if(req.query && req.query.page) {

@ -235,6 +235,10 @@ SocketPosts.getPidPage = function(socket, pid, callback) {
posts.getPidPage(pid, socket.uid, callback); posts.getPidPage(pid, socket.uid, callback);
} }
SocketPosts.getPidIndex = function(socket, pid, callback) {
posts.getPidIndex(pid, callback);
}
SocketPosts.flag = function(socket, pid, callback) { SocketPosts.flag = function(socket, pid, callback) {
if (!socket.uid) { if (!socket.uid) {
return callback(new Error('not-logged-in')); return callback(new Error('not-logged-in'));

@ -230,7 +230,7 @@ SocketTopics.follow = function(socket, tid, callback) {
}; };
SocketTopics.loadMore = function(socket, data, callback) { SocketTopics.loadMore = function(socket, data, callback) {
if(!data || !data.tid || !data.after) { if(!data || !data.tid || !(parseInt(data.after, 10) >= 0)) {
return callback(new Error('invalid data')); return callback(new Error('invalid data'));
} }

Loading…
Cancel
Save