mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 11:05:54 +01:00 
			
		
		
		
	closes #1101
This commit is contained in:
		| @@ -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); | ||||
| 			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(); | ||||
| 				} | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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; | ||||
| 		} | ||||
|  | ||||
| 	Category.onTopicsLoaded = function(topics) { | ||||
| 		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(); | ||||
|  | ||||
| 		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 { | ||||
| 				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, after, callback) { | ||||
| 		if (loadingMoreTopics || !$('#topics-container').length) { | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 	Category.loadMoreTopics = function(cid) { | ||||
| 		if (loadingMoreTopics || !$('#topics-container').length) { | ||||
| 		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; | ||||
| }); | ||||
| @@ -39,7 +39,7 @@ | ||||
| 		<ul id="topics-container" itemscope itemtype="http://www.schema.org/ItemList" data-nextstart="{nextStart}"> | ||||
| 			<meta itemprop="itemListOrder" content="descending"> | ||||
| 			<!-- BEGIN topics --> | ||||
| 			<li class="category-item <!-- IF topics.deleted -->deleted<!-- ENDIF topics.deleted --><!-- IF topics.unread -->unread<!-- ENDIF topics.unread -->" itemprop="itemListElement"> | ||||
| 			<li class="category-item <!-- IF topics.deleted -->deleted<!-- ENDIF topics.deleted --><!-- IF topics.unread -->unread<!-- ENDIF topics.unread -->" itemprop="itemListElement" data-tid="{topics.tid}" data-index="{topics.index}"> | ||||
|  | ||||
| 				<div class="col-md-12 col-xs-12 panel panel-default topic-row"> | ||||
|  | ||||
|   | ||||
| @@ -85,11 +85,13 @@ var db = require('./database'), | ||||
| 	}; | ||||
|  | ||||
| 	Categories.getCategoryTopics = function(cid, start, stop, uid, callback) { | ||||
| 		var tids; | ||||
| 		async.waterfall([ | ||||
| 			function(next) { | ||||
| 				Categories.getTopicIds(cid, start, stop, next); | ||||
| 			}, | ||||
| 			function(tids, next) { | ||||
| 			function(topicIds, next) { | ||||
| 				tids = topicIds; | ||||
| 				topics.getTopicsByTids(tids, uid, next); | ||||
| 			}, | ||||
| 			function(topics, next) { | ||||
| @@ -100,6 +102,15 @@ var db = require('./database'), | ||||
| 					}); | ||||
| 				} | ||||
|  | ||||
| 				var indices = {}; | ||||
| 				for(var i=0; i<tids.length; ++i) { | ||||
| 					indices[tids[i]] = start + i; | ||||
| 				} | ||||
|  | ||||
| 				for(var i=0; i<topics.length; ++i) { | ||||
| 					topics[i].index = indices[topics[i].tid]; | ||||
| 				} | ||||
|  | ||||
| 				db.sortedSetRevRank('categories:' + cid + ':tid', topics[topics.length - 1].tid, function(err, rank) { | ||||
| 					if(err) { | ||||
| 						return next(err); | ||||
| @@ -118,6 +129,16 @@ var db = require('./database'), | ||||
| 		db.getSortedSetRevRange('categories:' + cid + ':tid', start, stop, callback); | ||||
| 	}; | ||||
|  | ||||
| 	Categories.getTopicIndex = function(tid, callback) { | ||||
| 		topics.getTopicField(tid, 'cid', function(err, cid) { | ||||
| 			if(err) { | ||||
| 				return callback(err); | ||||
| 			} | ||||
|  | ||||
| 			db.sortedSetRevRank('categories:' + cid + ':tid', tid, callback); | ||||
| 		}); | ||||
| 	}; | ||||
|  | ||||
| 	Categories.getPageCount = function(cid, uid, callback) { | ||||
| 		db.sortedSetCard('categories:' + cid + ':tid', function(err, topicCount) { | ||||
| 			if(err) { | ||||
|   | ||||
| @@ -243,11 +243,11 @@ SocketPosts.getFavouritedUsers = function(socket, pid, callback) { | ||||
|  | ||||
| SocketPosts.getPidPage = function(socket, pid, callback) { | ||||
| 	posts.getPidPage(pid, socket.uid, callback); | ||||
| } | ||||
| }; | ||||
|  | ||||
| SocketPosts.getPidIndex = function(socket, pid, callback) { | ||||
| 	posts.getPidIndex(pid, callback); | ||||
| } | ||||
| }; | ||||
|  | ||||
| SocketPosts.flag = function(socket, pid, callback) { | ||||
| 	if (!socket.uid) { | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| var topics = require('../topics'), | ||||
| 	categories = require('../categories'), | ||||
| 	threadTools = require('../threadTools'), | ||||
| 	index = require('./index'), | ||||
| 	user = require('../user'), | ||||
| @@ -291,9 +292,16 @@ SocketTopics.loadMoreFromSet = function(socket, data, callback) { | ||||
| 	topics.getTopicsFromSet(socket.uid, data.set, start, end, callback); | ||||
| }; | ||||
|  | ||||
|  | ||||
| SocketTopics.getPageCount = function(socket, tid, callback) { | ||||
| 	topics.getPageCount(tid, socket.uid, callback); | ||||
| }; | ||||
|  | ||||
| SocketTopics.getTidPage = function(socket, tid, callback) { | ||||
| 	topics.getTidPage(tid, socket.uid, callback); | ||||
| }; | ||||
|  | ||||
| SocketTopics.getTidIndex = function(socket, tid, callback) { | ||||
| 	categories.getTopicIndex(tid, callback); | ||||
| }; | ||||
|  | ||||
| module.exports = SocketTopics; | ||||
| @@ -426,6 +426,26 @@ var async = require('async'), | ||||
| 		}); | ||||
| 	}; | ||||
|  | ||||
| 	Topics.getTidPage = function(tid, uid, callback) { | ||||
| 		if(!tid) { | ||||
| 			return callback(new Error('invalid-tid')); | ||||
| 		} | ||||
|  | ||||
| 		async.parallel({ | ||||
| 			index: function(next) { | ||||
| 				categories.getTopicIndex(tid, next); | ||||
| 			}, | ||||
| 			settings: function(next) { | ||||
| 				user.getSettings(uid, next); | ||||
| 			} | ||||
| 		}, function(err, results) { | ||||
| 			if(err) { | ||||
| 				return callback(err); | ||||
| 			} | ||||
| 			callback(null, Math.ceil((results.index + 1) / results.settings.topicsPerPage)); | ||||
| 		}); | ||||
| 	}; | ||||
|  | ||||
| 	Topics.getCategoryData = function(tid, callback) { | ||||
| 		Topics.getTopicField(tid, 'cid', function(err, cid) { | ||||
| 			if(err) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user