From 94c765fa250a2ffdc23698edf0be8dc8979d1ea7 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 27 Aug 2014 18:03:53 -0400 Subject: [PATCH] closes #1996 --- public/src/forum/admin/tags.js | 25 +++++++++++++---- public/src/forum/tags.js | 51 ++++++++++++++++++++++++++++++---- src/controllers/admin.js | 2 +- src/controllers/tags.js | 5 ++-- src/socket.io/topics.js | 49 ++++++++++++++++++++++++++++++++ src/topics/tags.js | 13 +++++---- 6 files changed, 123 insertions(+), 22 deletions(-) diff --git a/public/src/forum/admin/tags.js b/public/src/forum/admin/tags.js index e6468c7f21..965ae0db13 100644 --- a/public/src/forum/admin/tags.js +++ b/public/src/forum/admin/tags.js @@ -1,8 +1,9 @@ "use strict"; -/*global define, socket, app, admin*/ +/*global define, socket, app, admin, utils*/ -define('forum/admin/tags', [], function() { +define('forum/admin/tags', ['forum/infinitescroll'], function(infinitescroll) { var Tags = {}; + var timeoutId = 0; Tags.init = function() { handleColorPickers(); @@ -12,10 +13,22 @@ define('forum/admin/tags', [], function() { }); $('#tag-search').on('input propertychange', function() { - $('.tag-list').children().each(function() { - var $this = $(this); - $this.toggleClass('hide', $this.attr('data-tag').indexOf($('#tag-search').val()) === -1); - }); + if (timeoutId) { + clearTimeout(timeoutId); + timeoutId = 0; + } + timeoutId = setTimeout(function() { + socket.emit('topics.searchAndLoadTags', {query: $('#tag-search').val()}, function(err, tags) { + if (err) { + return app.alertError(err.message); + } + infinitescroll.parseAndTranslate('admin/tags', 'tags', {tags: tags}, function(html) { + $('.tag-list').html(html); + utils.makeNumbersHumanReadable(html.find('.human-readable-number')); + timeoutId = 0; + }); + }); + }, 100); }); }; diff --git a/public/src/forum/tags.js b/public/src/forum/tags.js index c96a921472..bf4395f497 100644 --- a/public/src/forum/tags.js +++ b/public/src/forum/tags.js @@ -1,20 +1,59 @@ 'use strict'; -/* globals define, app */ +/* globals define, app, utils, socket */ -define('forum/tags', function() { +define('forum/tags', ['forum/infinitescroll'], function(infinitescroll) { var Tags = {}; + var timeoutId = 0; Tags.init = function() { app.enterRoom('tags'); $('#tag-search').on('input propertychange', function() { - $('.tag-list').children().each(function() { - var $this = $(this); - $this.toggleClass('hide', $this.find('a').attr('data-value').indexOf($('#tag-search').val()) === -1); - }) + if (timeoutId) { + clearTimeout(timeoutId); + timeoutId = 0; + } + timeoutId = setTimeout(function() { + socket.emit('topics.searchAndLoadTags', {query: $('#tag-search').val()}, function(err, results) { + if (err) { + return app.alertError(err.message); + } + onTagsLoaded(results, true, function() { + timeoutId = 0; + }); + }); + }, 100); }); + + infinitescroll.init(Tags.loadMoreTags); }; + Tags.loadMoreTags = function(direction) { + if(direction < 0 || !$('.tag-list').length) { + return; + } + + infinitescroll.loadMore('topics.loadMoreTags', { + after: $('.tag-list').attr('data-nextstart') + }, function(data, done) { + if (data && data.tags && data.tags.length) { + onTagsLoaded(data.tags, false, done); + $('.tag-list').attr('data-nextstart', data.nextStart); + } else { + done(); + } + }); + }; + + function onTagsLoaded(tags, replace, callback) { + callback = callback || function() {}; + infinitescroll.parseAndTranslate('tags', 'tags', {tags: tags}, function(html) { + $('.tag-list')[replace ? 'html' : 'append'](html); + utils.makeNumbersHumanReadable(html.find('.human-readable-number')); + callback(); + }); + } + return Tags; }); diff --git a/src/controllers/admin.js b/src/controllers/admin.js index f853f16cf7..13b0bfde7b 100644 --- a/src/controllers/admin.js +++ b/src/controllers/admin.js @@ -132,7 +132,7 @@ function filterAndRenderCategories(req, res, next, active) { } adminController.tags.get = function(req, res, next) { - topics.getTags(0, -1, function(err, tags) { + topics.getTags(0, 99, function(err, tags) { if (err) { return next(err); } diff --git a/src/controllers/tags.js b/src/controllers/tags.js index 258a28b6c9..6d3d18c1f0 100644 --- a/src/controllers/tags.js +++ b/src/controllers/tags.js @@ -47,14 +47,13 @@ tagsController.getTag = function(req, res, next) { }; tagsController.getTags = function(req, res, next) { - topics.getTags(0, -1, function(err, tags) { + topics.getTags(0, 99, function(err, tags) { if (err) { return next(err); } - res.render('tags', {tags: tags}); + res.render('tags', {tags: tags, nextStart: 100}); }); - }; module.exports = tagsController; diff --git a/src/socket.io/topics.js b/src/socket.io/topics.js index 576c368f34..30d64b7b96 100644 --- a/src/socket.io/topics.js +++ b/src/socket.io/topics.js @@ -518,4 +518,53 @@ SocketTopics.searchTags = function(socket, data, callback) { topics.searchTags(data, callback); }; +SocketTopics.searchAndLoadTags = function(socket, data, callback) { + topics.searchTags(data, function(err, tags) { + if (err) { + return callback(err); + } + async.parallel({ + counts: function(next) { + db.sortedSetScores('tags:topic:count', tags, next); + }, + tagData: function(next) { + tags = tags.map(function(tag) { + return {value: tag}; + }); + + topics.getTagData(tags, next); + } + }, function(err, results) { + if (err) { + return callback(err); + } + results.tagData.forEach(function(tag, index) { + tag.score = results.counts[index]; + }); + results.tagData.sort(function(a, b) { + return parseInt(b.score, 10) - parseInt(a.score, 10); + }); + + callback(null, results.tagData); + }); + }); +}; + +SocketTopics.loadMoreTags = function(socket, data, callback) { + if(!data || !data.after) { + return callback(new Error('[[error:invalid-data]]')); + } + + var start = parseInt(data.after, 10), + end = start + 99; + + topics.getTags(start, end, function(err, tags) { + if (err) { + return callback(err); + } + + callback(null, {tags: tags, nextStart: end + 1}); + }); +}; + module.exports = SocketTopics; diff --git a/src/topics/tags.js b/src/topics/tags.js index ecca55eb2f..681d137fc9 100644 --- a/src/topics/tags.js +++ b/src/topics/tags.js @@ -89,11 +89,11 @@ module.exports = function(Topics) { return callback(err); } - addTagData(tags, callback); + Topics.getTagData(tags, callback); }); }; - function addTagData(tags, callback) { + Topics.getTagData = function(tags, callback) { var keys = tags.map(function(tag) { return 'tag:' + tag.value; }); @@ -109,7 +109,7 @@ module.exports = function(Topics) { }); callback(null, tags); }); - } + }; Topics.getTopicTags = function(tid, callback) { db.getSetMembers('topic:' + tid + ':tags', callback); @@ -139,7 +139,7 @@ module.exports = function(Topics) { async.parallel({ tagData: function(next) { - addTagData(tags, next); + Topics.getTagData(tags, next); }, counts: function(next) { db.sortedSetScores('tags:topic:count', uniqueTopicTags, next); @@ -214,12 +214,13 @@ module.exports = function(Topics) { return callback(null, []); } - db.getSortedSetRevRange('tags:topic:count', 0, -1, function(err, tags) { if (err) { return callback(null, []); } - + if (data.query === '') { + return callback(null, tags); + } data.query = data.query.toLowerCase(); var matches = []; for(var i=0; i