From 091723a8c56e51a63390c08bd15240e6ae13ddb8 Mon Sep 17 00:00:00 2001 From: Baris Soner Usakli Date: Thu, 27 Feb 2014 23:45:12 -0500 Subject: [PATCH] closes #1101 --- public/src/ajaxify.js | 8 +- public/src/app.js | 7 +- public/src/forum/category.js | 205 ++++++++++++++++++++++++++++++---- public/templates/category.tpl | 2 +- src/categories.js | 23 +++- src/socket.io/posts.js | 4 +- src/socket.io/topics.js | 10 +- src/topics.js | 20 ++++ 8 files changed, 250 insertions(+), 29 deletions(-) diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index 6b88546cba..47a6a0b2a0 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -21,8 +21,9 @@ var ajaxify = {}; window.onpopstate = function (event) { if (event !== null && event.state && event.state.url !== undefined && !ajaxify.initialLoad) { - ajaxify.go(event.state.url, null, true); - $(window).trigger('action:popstate', {url: event.state.url}); + ajaxify.go(event.state.url, function() { + $(window).trigger('action:popstate', {url: event.state.url}); + }, true); } }; @@ -30,6 +31,7 @@ var ajaxify = {}; ajaxify.initialLoad = false; ajaxify.go = function (url, callback, quiet) { + // "quiet": If set to true, will not call pushState app.enterRoom('global'); @@ -102,7 +104,7 @@ var ajaxify = {}; } }); - if (callback) { + if (typeof callback === 'function') { callback(); } diff --git a/public/src/app.js b/public/src/app.js index 17415d392d..3201e2b563 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -446,15 +446,18 @@ var socket, var previousScrollTop = 0; + + app.enableInfiniteLoading = function(callback) { $(window).off('scroll').on('scroll', function() { + var top = $(window).height() * 0.1; var bottom = ($(document).height() - $(window).height()) * 0.9; var currentScrollTop = $(window).scrollTop(); - if($(window).scrollTop() < top && previousScrollTop > currentScrollTop) { + if(currentScrollTop < top && currentScrollTop < previousScrollTop) { callback(-1); - } else if ($(window).scrollTop() > bottom && previousScrollTop < currentScrollTop) { + } else if (currentScrollTop > bottom && currentScrollTop > previousScrollTop) { callback(1); } previousScrollTop = currentScrollTop; diff --git a/public/src/forum/category.js b/public/src/forum/category.js index da62a01226..9e778148e6 100644 --- a/public/src/forum/category.js +++ b/public/src/forum/category.js @@ -2,10 +2,6 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { var Category = {}, loadingMoreTopics = false; - $(window).on('action:popstate', function(ev, data) { - - }); - Category.init = function() { var cid = templates.get('category_id'), categoryName = templates.get('category_name'), @@ -42,13 +38,128 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { socket.on('event:new_topic', Category.onNewTopic); enableInfiniteLoading(); + + $('#topics-container').on('click', '.topic-title', function() { + var clickedTid = $(this).parents('li.category-item[data-tid]').attr('data-tid'); + $('#topics-container li.category-item').each(function(index, el) { + if($(el).offset().top - $(window).scrollTop() > 0) { + tid = $(el).attr('data-tid'); + + localStorage.setItem('category:bookmark', tid); + localStorage.setItem('category:bookmark:clicked', clickedTid); + return false; + } + }); + }); + }; + + $(window).on('action:popstate', function(ev, data) { + if(data.url.indexOf('category/') === 0) { + var bookmark = localStorage.getItem('category:bookmark'); + var clicked = localStorage.getItem('category:bookmark:clicked'); + + if (bookmark) { + + if(config.usePagination) { + socket.emit('topics.getTidPage', bookmark, function(err, page) { + if(err) { + return; + } + if(parseInt(page, 10) !== pagination.currentPage) { + pagination.loadPage(page); + } else { + Category.scrollToTopic(bookmark, clicked, 400); + } + }); + } else { + + socket.emit('topics.getTidIndex', bookmark, function(err, index) { + if(err) { + return; + } + + if(index === 0) { + Category.highlightTopic(clicked); + return; + } + + if (index < 0) { + index = 0; + } + + $('#topics-container').empty(); + loadingMoreTopics = false; + + Category.loadMoreTopics(templates.get('category_id'), after, function() { + Category.scrollToTopic(bookmark, clicked, 0); + }); + }); + } + } + } + }); + + Category.highlightTopic = function(tid) { + var highlight = $('#topics-container li.category-item[data-tid="' + tid + '"]'); + if(highlight.length && !highlight.hasClass('highlight')) { + highlight.addClass('highlight'); + setTimeout(function() { + highlight.removeClass('highlight'); + }, 5000); + } + }; + + Category.scrollToTopic = function(tid, clickedTid, duration, offset) { + if(!tid) { + return; + } + + if(!offset) { + offset = 0; + } + + if($('#topics-container li.category-item[data-tid="' + tid + '"]').length) { + var cid = templates.get('category_id'); + var scrollTo = $('#topics-container li.category-item[data-tid="' + tid + '"]'); + + if (cid && scrollTo.length) { + $('html, body').animate({ + scrollTop: (scrollTo.offset().top - $('#header-menu').height() - offset) + 'px' + }, duration !== undefined ? duration : 400, function() { + Category.highlightTopic(clickedTid); + }); + } + } }; function enableInfiniteLoading() { if(!config.usePagination) { - app.enableInfiniteLoading(function() { - if(!loadingMoreTopics) { - Category.loadMoreTopics(templates.get('category_id')); + app.enableInfiniteLoading(function(direction) { + + if(!loadingMoreTopics && $('#topics-container').children().length) { + + var after = 0; + var el = null; + + if(direction > 0) { + el = $('#topics-container .category-item[data-tid]').last(); + after = parseInt(el.attr('data-index'), 10) + 1; + } else { + el = $('#topics-container .category-item[data-tid]').first(); + after = parseInt(el.attr('data-index'), 10); + after -= config.topicsPerPage; + if(after < 0) { + after = 0; + } + } + + var offset = el.offset().top - $('#header-menu').offset().top + $('#header-menu').height(); + + Category.loadMoreTopics(templates.get('category_id'), after, function() { + if(direction < 0 && el) { + Category.scrollToTopic(el.attr('data-tid'), null, 0, offset); + } + }); } }); } else { @@ -98,56 +209,112 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { $(window).trigger('action:categories.new_topic.loaded'); }); - } + }; + + Category.onTopicsLoaded = function(topics, callback) { + if(!topics || !topics.length) { + return; + } + + function removeAlreadyAddedTopics() { + topics = topics.filter(function(topic) { + return $('#topics-container li[data-tid="' + topic.tid +'"]').length === 0; + }); + } + + var after = null, + before = null; + + function findInsertionPoint() { + if (!$('#topics-container .category-item[data-tid]').length) { + return; + } + var last = $('#topics-container .category-item[data-tid]').last(); + var lastIndex = last.attr('data-index'); + var firstIndex = topics[topics.length - 1].index; + if (firstIndex > lastIndex) { + after = last; + } else { + before = $('#topics-container .category-item[data-tid]').first(); + } + } + + removeAlreadyAddedTopics(); + if(!topics.length) { + return; + } + + findInsertionPoint(); - Category.onTopicsLoaded = function(topics) { var html = templates.prepare(templates['category'].blocks['topics']).parse({ topics: topics }); translator.translate(html, function(translatedHTML) { - var container = $('#topics-container'); + var container = $('#topics-container'), + html = $(translatedHTML); $('#topics-container, .category-sidebar').removeClass('hidden'); $('#category-no-topics').remove(); - html = $(translatedHTML); - if(config.usePagination) { container.empty().append(html); } else { - container.append(html); + if(after) { + html.insertAfter(after); + } else if(before) { + html.insertBefore(before); + } else { + container.append(html); + } } $('#topics-container span.timeago').timeago(); app.createUserTooltips(); app.makeNumbersHumanReadable(html.find('.human-readable-number')); + + if (typeof callback === 'function') { + callback(topics); + } }); - } + }; - Category.loadMoreTopics = function(cid) { + Category.loadMoreTopics = function(cid, after, callback) { if (loadingMoreTopics || !$('#topics-container').length) { return; } + if(after === 0 && $('#topics-container li.category-item[data-index="0"]').length) { + return; + } + $(window).trigger('action:categories.loading'); loadingMoreTopics = true; + socket.emit('categories.loadMore', { cid: cid, - after: $('#topics-container').attr('data-nextstart') + after: after }, function (err, data) { + loadingMoreTopics = false; + if(err) { return app.alertError(err.message); } if (data && data.topics.length) { - Category.onTopicsLoaded(data.topics); + Category.onTopicsLoaded(data.topics, callback); $('#topics-container').attr('data-nextstart', data.nextStart); + } else { + + if (typeof callback === 'function') { + callback(data.topics); + } } - loadingMoreTopics = false; + + $(window).trigger('action:categories.loaded'); }); - } + }; return Category; }); \ No newline at end of file diff --git a/public/templates/category.tpl b/public/templates/category.tpl index 25bc8c0a31..f1b6a9c365 100644 --- a/public/templates/category.tpl +++ b/public/templates/category.tpl @@ -39,7 +39,7 @@