diff --git a/public/src/forum/category.js b/public/src/forum/category.js index aa6b25dd79..b0dff6f486 100644 --- a/public/src/forum/category.js +++ b/public/src/forum/category.js @@ -52,24 +52,10 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { } }); } else { - pagination.init(templates.get('currentPage'), templates.get('pageCount'), loadPage); + pagination.init(templates.get('currentPage'), templates.get('pageCount')); } } - function loadPage(page, callback) { - socket.emit('categories.loadPage', {cid: templates.get('category_id'), page: page}, function(err, data) { - if(err) { - return callback(err); - } - - if (data && data.topics && data.topics.length) { - Category.onTopicsLoaded(data.topics); - } - - callback(null); - }); - } - Category.onNewTopic = function(data) { var html = templates.prepare(templates['category'].blocks['topics']).parse({ topics: [data] diff --git a/public/src/forum/pagination.js b/public/src/forum/pagination.js index d7e9abc965..7c21a3090d 100644 --- a/public/src/forum/pagination.js +++ b/public/src/forum/pagination.js @@ -5,12 +5,10 @@ define(function() { pagination.currentPage = 0; pagination.pageCount = 0; - pagination.loadFunction = null; - pagination.init = function(currentPage, pageCount, loadFunction) { + pagination.init = function(currentPage, pageCount) { pagination.currentPage = parseInt(currentPage, 10); pagination.pageCount = parseInt(pageCount, 10); - pagination.loadFunction = loadFunction; updatePageLinks(); @@ -48,17 +46,9 @@ define(function() { return; } - pagination.loadFunction(page, function(err) { - if(err) { - return app.alertError(err.message); - } - - pagination.currentPage = parseInt(page, 10); - updatePageLinks(); - }); + ajaxify.go(window.location.pathname.slice(1) + '?page=' + page); } - function updatePageLinks() { if(pagination.pageCount === 0) { $('.pagination').addClass('hide'); @@ -79,6 +69,11 @@ define(function() { $('.pagination .page').removeClass('active'); $('.pagination .page[data-page="' + pagination.currentPage + '"]').addClass('active'); + $('.pagination .page').each(function(index, element) { + var li = $(this); + var page = li.attr('data-page'); + li.find('a').attr('href', window.location.pathname + '?page=' + page); + }); } return pagination; diff --git a/public/src/forum/topic.js b/public/src/forum/topic.js index 60ab01ce92..3976687684 100644 --- a/public/src/forum/topic.js +++ b/public/src/forum/topic.js @@ -4,8 +4,8 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { pagination; function showBottomPostBar() { - if($('#post-container .post-row').length > 1) { - $('.topic-main-buttons').removeClass('hide').parent().removeClass('hide'); + if($('#post-container .post-row').length > 1 || !$('#post-container li[data-index="0"]').length) { + $('.bottom-post-bar').removeClass('hide'); } } @@ -328,7 +328,7 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { var bookmark = localStorage.getItem('topic:' + tid + ':bookmark'); - if(bookmark && !config.usePagination) { + if(bookmark) { Topic.scrollToPost(parseInt(bookmark, 10)); } @@ -358,65 +358,10 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { } else { $('.pagination-block').addClass('hide'); - pagination.init(currentPage, pageCount, loadPage); + pagination.init(currentPage, pageCount); } } - function loadPage(page, callback) { - if(page === 1) { - ajaxify.go('topic/' + tid ); - return; - } - - socket.emit('topics.loadPage', {tid: tid, page: page}, function(err, data) { - if(err) { - return callback(err); - } - - if (data && data.posts && data.posts.length) { - createPagePosts(data, function() { - fixDeleteStateForPosts(); - }); - } - - callback(null); - }); - } - - function onNewPostPagination(data) { - var posts = data.posts; - socket.emit('topics.getPageCount', tid, function(err, newPageCount) { - - pagination.recreatePaginationLinks('topic', newPageCount); - - if(pagination.currentPage === pagination.newPageCount) { - createNewPosts(data); - } else if(data.posts && data.posts.length && parseInt(data.posts[0].uid, 10) === parseInt(app.uid, 10)) { - pagination.loadPage(pagination.pageCount); - } - }); - } - - function createPagePosts(data, callback) { - if(!data || (data.posts && !data.posts.length)) { - return; - } - - parseAndTranslatePosts(data.posts, function(translatedHTML) { - var translated = $(translatedHTML); - - $('#post-container').fadeOut(200, function() { - - $('#post-container').empty().append(translated).fadeIn('slow'); - - onNewPostsLoaded(data.posts); - - callback(); - }); - }); - } - - $('.topic').on('click', '.post_reply', function() { var selectionText = '', selection = window.getSelection() || document.getSelection(); @@ -1071,36 +1016,64 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { return; } - var container = $(window), + if(config.usePagination) { + socket.emit('posts.getPidPage', pid, function(err, page) { + if(parseInt(page, 10) !== pagination.currentPage) { + pagination.loadPage(page); + } else { + scrollToPid(pid); + } + }); + } else { + scrollToPid(pid); + } + + function scrollToPid(pid) { + var container = $(window), scrollTo = $('#post_anchor_' + pid), tid = $('#post-container').attr('data-tid'); - function animateScroll() { - $('window,html').animate({ - scrollTop: scrollTo.offset().top + container.scrollTop() - $('#header-menu').height() - }, 400); - } + function animateScroll() { + $('window,html').animate({ + scrollTop: scrollTo.offset().top + container.scrollTop() - $('#header-menu').height() + }, 400); + } - if (!scrollTo.length && tid) { + if (!scrollTo.length && tid) { - var intervalID = setInterval(function () { - loadMorePosts(tid, function (posts) { - scrollTo = $('#post_anchor_' + pid); + var intervalID = setInterval(function () { + loadMorePosts(tid, function (posts) { + scrollTo = $('#post_anchor_' + pid); - if (tid && scrollTo.length) { - animateScroll(); - } + if (tid && scrollTo.length) { + animateScroll(); + } - if (!posts.length || scrollTo.length) - clearInterval(intervalID); - }); - }, 100); + if (!posts.length || scrollTo.length) + clearInterval(intervalID); + }); + }, 100); - } else if (tid) { - animateScroll(); + } else if (tid) { + animateScroll(); + } } } + function onNewPostPagination(data) { + var posts = data.posts; + socket.emit('topics.getPageCount', tid, function(err, newPageCount) { + + pagination.recreatePaginationLinks('topic', newPageCount); + + if(pagination.currentPage === pagination.pageCount) { + createNewPosts(data); + } else if(data.posts && data.posts.length && parseInt(data.posts[0].uid, 10) === parseInt(app.uid, 10)) { + pagination.loadPage(pagination.pageCount); + } + }); + } + function createNewPosts(data, infiniteLoaded) { if(!data || (data.posts && !data.posts.length)) { return; diff --git a/public/templates/topic.tpl b/public/templates/topic.tpl index 36b3a63076..bd5b7e82b7 100644 --- a/public/templates/topic.tpl +++ b/public/templates/topic.tpl @@ -143,7 +143,7 @@ </li> <!-- IF @first --> - <li class="well post-bar"> + <li class="well post-bar" data-index="{posts.index}"> <div class="inline-block"> <small class="topic-stats"> <span>[[category:posts]]</span> @@ -178,8 +178,8 @@ <!-- END posts --> </ul> - <div class="well col-md-11 col-xs-12 pull-right hide"> - <div class="topic-main-buttons pull-right inline-block hide"> + <div class="well col-md-11 col-xs-12 pull-right post-bar bottom-post-bar hide"> + <div class="topic-main-buttons pull-right inline-block"> <div class="loading-indicator" done="0" style="display:none;"> <span class="hidden-xs-inline">[[topic:loading_more_posts]]</span> <i class="fa fa-refresh fa-spin"></i> </div> diff --git a/src/categories.js b/src/categories.js index d3d6f04c95..5131f8e57a 100644 --- a/src/categories.js +++ b/src/categories.js @@ -46,15 +46,14 @@ var db = require('./database.js'), }); }; - Categories.getCategoryById = function(category_id, current_user, callback) { + Categories.getCategoryById = function(category_id, start, end, current_user, callback) { Categories.getCategoryData(category_id, function(err, categoryData) { if (err) { return callback(err); } function getTopicIds(next) { - var topicsPerPage = meta.config.topicsPerPage || 20; - Categories.getTopicIds(category_id, 0, topicsPerPage - 1, next); + Categories.getTopicIds(category_id, start, end, next); } function getActiveUsers(next) { diff --git a/src/feed.js b/src/feed.js index ac55c64460..89828328e1 100644 --- a/src/feed.js +++ b/src/feed.js @@ -84,7 +84,7 @@ }; Feed.updateCategory = function (cid, callback) { - categories.getCategoryById(cid, 0, function (err, categoryData) { + categories.getCategoryById(cid, 0, -1, 0, function (err, categoryData) { if (err) return callback(new Error('category-invalid')); var feed = new rss({ diff --git a/src/posts.js b/src/posts.js index b4aa4c1882..b7048dc09c 100644 --- a/src/posts.js +++ b/src/posts.js @@ -468,4 +468,28 @@ var db = require('./database'), }); } + Posts.getPidPage = function(pid, callback) { + Posts.getPostField(pid, 'tid', function(err, tid) { + if(err) { + return callback(err); + } + + topics.getPids(tid, function(err, pids) { + if(err) { + return callback(err); + } + + var index = pids.indexOf(pid); + if(index === -1) { + return callback(new Error('pid not found')); + } + var postsPerPage = parseInt(meta.config.postsPerPage, 10); + postsPerPage = postsPerPage ? postsPerPage : 20; + + var page = Math.ceil((index + 1) / postsPerPage); + callback(null, page); + }); + }); + } + }(exports)); diff --git a/src/routes/api.js b/src/routes/api.js index 171dc5147d..f700334764 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -164,17 +164,33 @@ var path = require('path'), }); app.get('/topic/:id/:slug?', function (req, res, next) { - console.log(req.query); + var uid = (req.user) ? req.user.uid : 0; + var page = 1; + if(req.query && req.query.page) { + page = req.query.page; + } + + if(parseInt(page, 10) < 1) { + return res.send(404); + } + + var postsPerPage = parseInt(meta.config.postsPerPage ? meta.config.postsPerPage : 20, 10); + var start = (page - 1) * postsPerPage; + var end = start + postsPerPage - 1; ThreadTools.privileges(req.params.id, uid, function(err, privileges) { if (privileges.read) { - var postsPerPage = parseInt(meta.config.postsPerPage ? meta.config.postsPerPage : 20, 10); - topics.getTopicWithPosts(req.params.id, uid, 0, postsPerPage - 1, false, function (err, data) { + topics.getTopicWithPosts(req.params.id, uid, start, end, false, function (err, data) { if(err) { return next(err); } - data.currentPage = 1; + + if(page > data.pageCount) { + return res.send(404); + } + + data.currentPage = page; data.privileges = privileges; if (parseInt(data.deleted, 10) === 1 && parseInt(data.expose_tools, 10) === 0) { @@ -191,16 +207,32 @@ var path = require('path'), app.get('/category/:id/:slug?', function (req, res, next) { var uid = (req.user) ? req.user.uid : 0; + var page = 1; + if(req.query && req.query.page) { + page = req.query.page; + } + + if(parseInt(page, 10) < 1) { + return res.send(404); + } + + var topicsPerPage = parseInt(meta.config.topicsPerPage ? meta.config.topicsPerPage : 20, 10); + var start = (page - 1) * topicsPerPage; + var end = start + topicsPerPage - 1; // Category Whitelisting categoryTools.privileges(req.params.id, uid, function(err, privileges) { if (!err && privileges.read) { - categories.getCategoryById(req.params.id, uid, function (err, data) { + categories.getCategoryById(req.params.id, start, end, uid, function (err, data) { if(err) { return next(err); } - data.currentPage = 1; + if(page > data.pageCount) { + return res.send(404); + } + + data.currentPage = page; data.privileges = privileges; if (data && parseInt(data.disabled, 10) === 0) { diff --git a/src/socket.io/categories.js b/src/socket.io/categories.js index ec663ee8e6..eaac85b4ac 100644 --- a/src/socket.io/categories.js +++ b/src/socket.io/categories.js @@ -28,23 +28,6 @@ SocketCategories.loadMore = function(socket, data, callback) { }); }; -SocketCategories.loadPage = function(socket, data, callback) { - if(!data) { - return callback(new Error('invalid data')); - } - - var topicsPerPage = parseInt(meta.config.topicsPerPage, 10) || 20; - - var start = (data.page - 1) * topicsPerPage, - end = start + topicsPerPage - 1; - - categories.getCategoryTopics(data.cid, start, end, socket.uid, function(err, topics) { - callback(err, { - topics: topics - }); - }); -} - SocketCategories.getPageCount = function(socket, cid, callback) { categories.getPageCount(cid, callback); } diff --git a/src/socket.io/posts.js b/src/socket.io/posts.js index 652f09cada..14726ab0cb 100644 --- a/src/socket.io/posts.js +++ b/src/socket.io/posts.js @@ -194,4 +194,8 @@ SocketPosts.getFavouritedUsers = function(socket, pid, callback) { }); }; +SocketPosts.getPidPage = function(socket, pid, callback) { + posts.getPidPage(pid, callback); +} + module.exports = SocketPosts; \ No newline at end of file diff --git a/src/socket.io/topics.js b/src/socket.io/topics.js index 3a45f1293e..6ea39afbc9 100644 --- a/src/socket.io/topics.js +++ b/src/socket.io/topics.js @@ -245,31 +245,6 @@ SocketTopics.loadMore = function(socket, data, callback) { }); }; -SocketTopics.loadPage = function(socket, data, callback) { - if(!data || !data.tid || !data.page || parseInt(data.page < 0)) { - return callback(new Error('invalid data')); - } - - var postsPerPage = parseInt((meta.config.postsPerPage ? meta.config.postsPerPage : 20), 10); - - topics.getPageCount(data.tid, function(err, pageCount) { - if(err) { - return callback(err); - } - - if(data.page > pageCount) { - return callback(new Error('page doesn\'t exist')); - } - - var start = (data.page-1) * postsPerPage, - end = start + postsPerPage - 1; - - topics.getTopicPosts(data.tid, start, end, socket.uid, function(err, posts) { - callback(err, {posts: posts}); - }); - }); -} - SocketTopics.loadMoreRecentTopics = function(socket, data, callback) { if(!data || !data.term) { return callback(new Error('invalid data')); diff --git a/src/webserver.js b/src/webserver.js index ee5b1a0dc6..323a977522 100644 --- a/src/webserver.js +++ b/src/webserver.js @@ -9,6 +9,7 @@ var path = require('path'), validator = require('validator'), async = require('async'), S = require('string'), + qs = require('querystring'), pkg = require('../package.json'), @@ -644,6 +645,10 @@ module.exports.server = server; } var topic_url = tid + (req.params.slug ? '/' + req.params.slug : ''); + var queryString = qs.stringify(req.query); + if(queryString.length) { + topic_url += '?' + queryString; + } res.send( data.header + @@ -701,7 +706,7 @@ module.exports.server = server; }); }, function (next) { - categories.getCategoryById(cid, 0, function (err, categoryData) { + categories.getCategoryById(cid, 0, -1, 0, function (err, categoryData) { if (categoryData) { if (parseInt(categoryData.disabled, 10) === 1) { @@ -758,6 +763,10 @@ module.exports.server = server; } var category_url = cid + (req.params.slug ? '/' + req.params.slug : ''); + var queryString = qs.stringify(req.query); + if(queryString.length) { + category_url += '?' + queryString; + } res.send( data.header + diff --git a/tests/categories.js b/tests/categories.js index 6f83d774f8..ba9cf3b702 100644 --- a/tests/categories.js +++ b/tests/categories.js @@ -31,7 +31,7 @@ describe('Categories', function() { describe('.getCategoryById', function() { it('should retrieve a newly created category by its ID', function(done) { - Categories.getCategoryById(categoryObj.cid, 0, function(err, categoryData) { + Categories.getCategoryById(categoryObj.cid, 0, -1, 0, function(err, categoryData) { assert(categoryData); assert.equal(categoryObj.name, categoryData.category_name); assert.equal(categoryObj.description, categoryData.category_description);