From 7ac458ac3396532fe3850910f27b6487d71d2f85 Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Sun, 25 Nov 2012 14:51:38 +0100 Subject: [PATCH] added ability to view up to 210 results on the leaderboards --- app.js | 7 +-- lib/utils.js | 66 ++++++++++++++++++---------- package.json | 2 +- public/css/style.css | 91 +++++++++++++++++++++++++++++++++++++++ public/js/leaderboards.js | 33 ++++++++++++++ routes/user.js | 36 ++++++++++------ views/layout.jade | 2 +- views/leaderboards.jade | 50 ++++++++++++--------- 8 files changed, 226 insertions(+), 61 deletions(-) create mode 100644 public/js/leaderboards.js diff --git a/app.js b/app.js index 6ca2d83..9b32aa6 100644 --- a/app.js +++ b/app.js @@ -27,7 +27,7 @@ app.use('/static', express.static(pub, {maxAge: 2419200000})); // 4 weeks = 2419 app.use(express.favicon(pub + '/img/favicon.ico', {maxAge: 2419200000})); app.use(express.bodyParser()); app.use(express.cookieParser(process.env.SITE_SECRET)); -app.use(express.session({store: sessionstore})); +app.use(express.session({store: sessionstore, cookie: {maxAge: 14400000}})); // 4 h = 14400000 ms // Routes app.get('/', site.home); @@ -38,12 +38,13 @@ app.get('/leaderboards', user.leaderboards); app.get('/login', site.validationErrors, site.login); app.post('/login', user.validateLogin, user.checkUser, user.authenticate); app.get('/logout', user.logout); -app.get('/signup', site.validationErrors, site.signup); -app.post('/signup', user.validateSignUp, user.userExists, user.emailExists, user.createAccount); app.get('/recoverpasswd', site.validationErrors, site.recoverPasswd); app.post('/recoverpasswd', user.validateRecoverPasswd, user.sendEmail); app.get('/resetpasswd', site.validationErrors, site.resetPasswd); app.post('/resetpasswd', user.resetPasswd); +app.get('/sliceleaderboard', user.sliceLeaderboard); +app.get('/signup', site.validationErrors, site.signup); +app.post('/signup', user.validateSignUp, user.userExists, user.emailExists, user.createAccount); app.get('/:room', site.room); app.get('/user/*', user.profile); diff --git a/lib/utils.js b/lib/utils.js index 84b1127..b5118ec 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,26 +1,3 @@ -/** - * Get a random slogan. - */ - -exports.randomSlogan = function() { - var slogans = [ - 'guess the song.' - , 'name that tune.' - , 'i know this track.' - ]; - return slogans[Math.floor(Math.random() * slogans.length)]; -}; - -/** - * Check if the provided string is a valid email address. - */ - -exports.isEmail = function(str) { - // Simple filter, but it covers most of the use cases. - var filter = /^[+a-zA-Z0-9_.\-]+@([a-zA-Z0-9\-]+\.)+[a-zA-Z0-9]{2,6}$/; - return filter.test(str); -}; - /** * Helper function used to build leaderboards. * Rearrange database results in an object. @@ -43,3 +20,46 @@ exports.buildLeaderboards = function(pointsresults, timesresults) { } return obj; }; + +/** + * Check if the provided string is a valid email address. + */ + +exports.isEmail = function(str) { + // Simple filter, but it covers most of the use cases. + var filter = /^[+a-zA-Z0-9_.\-]+@([a-zA-Z0-9\-]+\.)+[a-zA-Z0-9]{2,6}$/; + return filter.test(str); +}; + +/** + * Get a random slogan. + */ + +exports.randomSlogan = function() { + var slogans = [ + 'guess the song.' + , 'name that tune.' + , 'i know this track.' + ]; + return slogans[Math.floor(Math.random() * slogans.length)]; +}; + +/** + * Return the sorting parameters used to get users ordered by best guess time. + */ + +exports.sortParams = function(offset) { + var params = [ + 'users' + , 'by' + , 'user:*->bestguesstime' + , 'get' + , '#' + , 'get' + , 'user:*->bestguesstime' + , 'limit' + , offset + , '30' + ]; + return params; +}; diff --git a/package.json b/package.json index dfe55b1..6e829e1 100644 --- a/package.json +++ b/package.json @@ -21,5 +21,5 @@ "start": "app.js" }, "subdomain": "binb", - "version": "0.3.4-10" + "version": "0.3.5" } \ No newline at end of file diff --git a/public/css/style.css b/public/css/style.css index c009672..2b622d1 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -218,6 +218,97 @@ form .clearfix { .leaderboard tbody tr:hover td, .stats tbody tr:hover td { background-color: #dadada; } +.loading { + width: 18px; + position: absolute; + top: 360px; + left: 191px; + display: none; +} +.loading-block { + background-color: #6184B7; + border: 1px solid #466085; + float: left; + height: 12px; + margin-left: 1px; + width: 3px; + opacity: 0.1; + -o-animation-name: bounce; + -o-animation-duration: 1s; + -o-animation-iteration-count: infinite; + -o-transform: scale(0.7); + -moz-animation-name: bounce; + -moz-animation-duration: 1s; + -moz-animation-iteration-count: infinite; + -moz-transform: scale(0.7); + -ms-transform: scale(0.7); + -webkit-animation-name: bounce; + -webkit-animation-duration: 1s; + -webkit-animation-iteration-count: infinite; + -webkit-transform: scale(0.7); + animation-name: bounce; + animation-duration: 1s; + animation-iteration-count: infinite; + transform: scale(0.7); +} +.loading-block:first-child { + -o-animation-delay: 0.4s; + -moz-animation-delay: 0.4s; + -webkit-animation-delay: 0.4s; + animation-delay: 0.4s; +} +.loading-block:nth-child(2) { + -o-animation-delay: 0.5s; + -moz-animation-delay: 0.5s; + -webkit-animation-delay: 0.5s; + animation-delay: 0.5s; +} +.loading-block:last-child { + -o-animation-delay: 0.6s; + -moz-animation-delay: 0.6s; + -webkit-animation-delay: 0.6s; + animation-delay: 0.6s; +} +@-o-keyframes bounce { + 0% { + -o-transform: scale(1); + opacity: 1; + } + 100% { + -o-transform: scale(0.7); + opacity: 0.1; + } +} +@-moz-keyframes bounce { + 0% { + -moz-transform: scale(1); + opacity: 1; + } + 100% { + -moz-transform: scale(0.7); + opacity: 0.1; + } +} +@-webkit-keyframes bounce { + 0% { + -webkit-transform: scale(1); + opacity: 1; + } + 100% { + -webkit-transform: scale(0.7); + opacity: 0.1; + } +} +@keyframes bounce { + 0% { + transform: scale(1); + opacity: 1; + } + 100% { + transform:s cale(0.7); + opacity: 0.1; + } +} .room { height: 25px; line-height: 25px; diff --git a/public/js/leaderboards.js b/public/js/leaderboards.js new file mode 100644 index 0000000..d009716 --- /dev/null +++ b/public/js/leaderboards.js @@ -0,0 +1,33 @@ +(function() { + var appendResults = function(data, leaderboard, offset, type) { + for (var i=0; i').text(data[i]) + , col1 = ''+(++offset)+'' + , col2 = $('').append(link) + , col3 = (type === 'points') + ? ''+data[i+1]+'' + : ' '+(data[i+1] / 1000).toFixed(2)+' sec'; + var row = $('').append(col1, col2, col3); + leaderboard.append(row); + } + }; + + $('.leaderboard-wrapper').each(function(index) { + var leaderboard = $(this).find('tbody') + , loading = $(this).find('.loading') + , offset = 0 + , type = (index === 0) ? 'points' : 'times'; + + $(this).scroll(function() { + var diff = $(this).prop('scrollHeight') - $(this).scrollTop(); + if (diff === $(this).height() && offset < 180) { + offset += 30; + loading.show(); + $.get('/sliceleaderboard', {begin: offset, by: type}, function(data) { + loading.hide(); + appendResults(data, leaderboard, offset, type); + }); + } + }); + }); +})(); diff --git a/routes/user.js b/routes/user.js index 03472ca..43b6629 100644 --- a/routes/user.js +++ b/routes/user.js @@ -24,19 +24,7 @@ for (var i=0; ibestguesstime' - , 'get' - , '#' - , 'get' - , 'user:*->bestguesstime' - , 'limit' - , '0' - , '30' - ]; - db.sort(sortparams, function (e, timesresults) { + db.sort(utils.sortParams(0), function(e, timesresults) { var leaderboards = utils.buildLeaderboards(pointsresults, timesresults); res.locals.slogan = utils.randomSlogan(); res.render('leaderboards', leaderboards); @@ -44,6 +32,28 @@ exports.leaderboards = function(req, res) { }); }; +/** + * Get 30 users from the ranking, starting at index `begin`. + */ + +exports.sliceLeaderboard = function(req, res) { + var begin = parseInt(req.query.begin, 10) + , by = req.query.by; + if (isNaN(begin) || begin > 180 || (by !== 'points' && by !== 'times')) { + return res.send(412); + } + var end = begin + 29; + if (by === 'points') { + db.zrevrange('users', begin, end, 'withscores', function(err, results) { + res.json(results); + }); + return; + } + db.sort(utils.sortParams(begin), function(err, results) { + res.json(results); + }); +}; + /** * Change password middlewares. */ diff --git a/views/layout.jade b/views/layout.jade index 07126dd..dcf7731 100644 --- a/views/layout.jade +++ b/views/layout.jade @@ -43,7 +43,7 @@ html span.footer-info Powered by block media block scripts - script(src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js") + script(src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js") script(src="/static/js/bootstrap.min.js") script var uvOptions = {}; diff --git a/views/leaderboards.jade b/views/leaderboards.jade index 800a64c..2dfef06 100644 --- a/views/leaderboards.jade +++ b/views/leaderboards.jade @@ -15,31 +15,41 @@ block sections .icons.img section .row - .span7.offset1 + .span7.offset1.relative h4 Points - div.leaderboard-wrapper + .leaderboard-wrapper table.table.table-striped.table-bordered.leaderboard tbody - - each user, i in pointsleaderboard - tr - td #{i+1} - td - a(href="/user/#{encodeURIComponent(user.username)}") - | #{user.username.replace(/&/g, '&')} - td #{user.totpoints} - .span7 + - each user, i in pointsleaderboard + tr + td #{i+1} + td + a(href="/user/#{encodeURIComponent(user.username)}") + | #{user.username.replace(/&/g, '&')} + td #{user.totpoints} + .loading + .loading-block + .loading-block + .loading-block + .span7.relative h4 Times - div.leaderboard-wrapper + .leaderboard-wrapper table.table.table-striped.table-bordered.leaderboard tbody - - each user, i in timesleaderboard - tr - td #{i+1} - td - a(href="/user/#{encodeURIComponent(user.username)}") - | #{user.username.replace(/&/g, '&')} - td - i.icon-time - | #{user.bestguesstime} sec + - each user, i in timesleaderboard + tr + td #{i+1} + td + a(href="/user/#{encodeURIComponent(user.username)}") + | #{user.username.replace(/&/g, '&')} + td + i.icon-time + | #{user.bestguesstime} sec + .loading + .loading-block + .loading-block + .loading-block block scripts + script(src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js") + script(src="/static/js/leaderboards.js") -- 2.54.0