Skip to content

Commit a8398e2

Browse files
author
Karl Seguin
committed
top scores api
1 parent 35dd703 commit a8398e2

File tree

4 files changed

+323
-10
lines changed

4 files changed

+323
-10
lines changed

jquery.leaderboard.js

+205
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
(function($)
2+
{
3+
var defaults = {lids: null, scope: 0, records: 10, page: 1, baseUrl: 'http://api.mogade.com/api/gamma/scores', nextText: 'next', previousText: 'prev', data: null}
4+
var monthnames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
5+
$.fn.leaderboard = function(opts)
6+
{
7+
var options = $.extend({}, defaults, opts);
8+
return this.each(function()
9+
{
10+
if (this.leaderboard) { return false; }
11+
var $container = $(this);
12+
var $table, $tbody, $error, $tabContainer, $pager, $lid = null;
13+
var data = {lid: options.lids[0][0], scope: options.scope, page: options.page};
14+
var previousPage = 0;
15+
var self =
16+
{
17+
initialize: function()
18+
{
19+
self.buildLeaderboardChoice($container);
20+
$tabContainer = self.buildScopeTabs($container);
21+
$table = self.buildTable($container);
22+
$pager = self.buildPager($container);
23+
24+
$table = $container.children('table');
25+
$error = $('<div>').appendTo($container);
26+
$tbody = $table.find('tbody');
27+
$tabContainer.children().eq(options.scope).click();
28+
$container.show();
29+
},
30+
buildLeaderboardChoice: function($container)
31+
{
32+
if (options.lids.length == 1)
33+
{
34+
return $('<div class="leaderboard_name">').text(options.lids[0][1]).appendTo($container);
35+
}
36+
var $select = $('<select class="leaderboard_name">').appendTo($container)
37+
for(var i = 0; i < options.lids.length; ++i)
38+
{
39+
var lid = options.lids[i];
40+
$select.append($('<option>').text(lid[1]).val(lid[0]))
41+
}
42+
if ($select.purdySelect) { $select.purdySelect(); }
43+
return $select.change(self.leaderboardChanged);
44+
},
45+
buildScopeTabs: function($container)
46+
{
47+
var $tabs = $('<div class="tabs">');
48+
$tabs.append($('<div>').data('scope', 1).text('today'));
49+
$tabs.append($('<div>').data('scope', 2).text('this week'));
50+
$tabs.append($('<div>').data('scope', 3).text('overall'));
51+
$tabs.append($('<div>').data('scope', 4).text('yesterday'));
52+
$tabs.delegate('div', 'click', self.scopeChanged);
53+
return $tabs.appendTo($container);
54+
},
55+
buildTable: function($container)
56+
{
57+
var $table = $('<table>');
58+
var $thead = $('<thead>').appendTo($table);
59+
var $tr = $('<tr>').appendTo($thead)
60+
.append($('<th class="rank">').text('rank'))
61+
.append($('<th class="name">').text('name'))
62+
.append($('<th class="score">').text('score'))
63+
.append($('<th class="date">').text('date'));
64+
65+
if (options.data)
66+
{
67+
$tr.append($('<th class="data">').text(options.data.name))
68+
}
69+
return $table.append($('<tbody>')).appendTo($container);
70+
},
71+
buildPager: function($container)
72+
{
73+
var $pager = $('<div class="pager">').css('display', 'none');
74+
$('<div class="prev">').text(options.previousText).appendTo($pager);
75+
$('<div class="next">').text(options.nextText).appendTo($pager);
76+
return $pager.delegate('div', 'click', self.pageChanged).appendTo($container);
77+
},
78+
scopeChanged: function()
79+
{
80+
var $tab = $(this);
81+
previousPage = 0;
82+
data['scope'] = $tab.data('scope');
83+
data['page'] = 1;
84+
self.getLeaderboard();
85+
return false;
86+
},
87+
pageChanged: function()
88+
{
89+
var page = data['page'];
90+
var previousPage = page;
91+
if ($(this).is('.next')) { ++page; }
92+
else { --page; }
93+
94+
data['page'] = page;
95+
self.getLeaderboard();
96+
return false;
97+
},
98+
leaderboardChanged: function()
99+
{
100+
data['page'] = 1
101+
data['lid'] = $(this).val();
102+
self.getLeaderboard();
103+
return false;
104+
},
105+
getLeaderboard: function()
106+
{
107+
$.ajax({
108+
url: options.baseUrl,
109+
data: data,
110+
type: 'GET',
111+
dataType: 'jsonp',
112+
success: self.gotLeaderboard,
113+
});
114+
},
115+
gotLeaderboard: function(d)
116+
{
117+
var $tabs = $tabContainer.children();
118+
$tabs.removeClass('active');
119+
$tabs.eq(data['scope']-1).addClass('active');
120+
121+
if (d.scores.length == 0) { return self.noData(); }
122+
self.setPagerVisibility(d.page > 1, d.scores.length == options.records);
123+
124+
var dateTimeName = self.isDailyScope() ? 'time' : 'date';
125+
$table.find('th.date').text(dateTimeName);
126+
$table.show();
127+
$error.hide();
128+
var page = d.page;
129+
var rows = [];
130+
for(var i = 0; i < d.scores.length; ++i)
131+
{
132+
var score = d.scores[i];
133+
var $row = $('<tr>');
134+
if (i % 2 == 1) { $row.addClass('odd'); }
135+
$row.append(self.createCell((page - 1) * options.records + i + 1));
136+
$row.append(self.createCell(score.username));
137+
$row.append(self.createCell(score.points));
138+
$row.append(self.createCell(self.formatDate(new Date(score.dated))));
139+
if (options.data)
140+
{
141+
$row.append(self.createCell(options.data.handler(score.data)));
142+
}
143+
rows.push($row);
144+
}
145+
if (previousPage == 0) {$tbody.empty(); for(var i = 0; i < rows.length; ++i) { $tbody.append(rows[i]);} }
146+
else if (previousPage < page){ self.loadNextRows(rows, 0, $tbody.children().length); }
147+
else{ self.loadPrevRows(rows, rows.length, $tbody.children().length); }
148+
previousPage = page;
149+
},
150+
loadNextRows: function(rows, index, previous)
151+
{
152+
if (index == rows.length) { return; }
153+
setTimeout(function()
154+
{
155+
if (index < previous) { $tbody.children().first().remove(); }
156+
$tbody.append(rows[index]);
157+
self.loadNextRows(rows, ++index, previous)
158+
}, 10)
159+
},
160+
loadPrevRows: function(rows, index, previous)
161+
{
162+
if (index == -1) { return; }
163+
setTimeout(function()
164+
{
165+
if (index < previous) { $tbody.children().last().remove(); }
166+
$tbody.prepend(rows[index]);
167+
self.loadPrevRows(rows, --index, previous)
168+
}, 10)
169+
},
170+
formatDate: function(date)
171+
{
172+
var time = date.getHours() + ':' + (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes());
173+
if (self.isDailyScope())
174+
{
175+
return time;
176+
}
177+
return monthnames[date.getMonth()] + ' ' + date.getDate() + ', ' + time;
178+
},
179+
isDailyScope: function()
180+
{
181+
return data.scope == 1 || data.scope == 4;
182+
},
183+
createCell: function(text)
184+
{
185+
return '<td>' + text + '</td>';
186+
},
187+
noData: function()
188+
{
189+
$table.hide();
190+
$tbody.empty();
191+
self.setPagerVisibility(data['page'] > 1, false);
192+
$error.text('no scores are available right now').show();
193+
},
194+
setPagerVisibility: function(prev, next)
195+
{
196+
prev ? $pager.children('div.prev').show() : $pager.children('div.prev').hide();
197+
next ? $pager.children('div.next').show() : $pager.children('div.next').hide();
198+
$pager.show();
199+
}
200+
};
201+
this.leaderboard = self;
202+
self.initialize();
203+
});
204+
};
205+
})(jQuery);

jquery.topScores.js

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
(function($)
2+
{
3+
var defaults = {lids: null, baseUrl: 'http://mogade.com/api/gamma/scores/'}
4+
$.fn.topScores = function(opts)
5+
{
6+
var options = $.extend({}, defaults, opts);
7+
return this.each(function()
8+
{
9+
if (this.topScores) { return false; }
10+
var $container = $(this);
11+
var data = {lid: options.lids[0][0]};
12+
var self =
13+
{
14+
initialize: function()
15+
{
16+
self.buildLeaderboardChoice($container);
17+
$container.show();
18+
self.getTopScores();
19+
},
20+
buildLeaderboardChoice: function($container)
21+
{
22+
if (options.lids.length == 1)
23+
{
24+
return $('<div class="leaderboard_name">').text(options.lids[0][1]).appendTo($container);
25+
}
26+
var $select = $('<select class="leaderboard_name">').appendTo($container)
27+
for(var i = 0; i < options.lids.length; ++i)
28+
{
29+
var lid = options.lids[i];
30+
$select.append($('<option>').text(lid[1]).val(lid[0]))
31+
}
32+
if ($select.purdySelect) { $select.purdySelect(); }
33+
return $select.change(self.leaderboardChanged);
34+
},
35+
leaderboardChanged: function()
36+
{
37+
data['lid'] = $(this).val();
38+
self.getTopScores();
39+
return false;
40+
},
41+
getTopScores: function()
42+
{
43+
$.ajax({
44+
url: options.baseUrl,
45+
data: data,
46+
type: 'GET',
47+
dataType: 'jsonp',
48+
success: self.gotTopScores,
49+
});
50+
},
51+
gotTopScores: function(d)
52+
{
53+
$container.children().remove('div.scope');
54+
$container.append(self.buildFor(d[4], 'yesterday'));
55+
$container.append(self.buildFor(d[1], 'today'));
56+
$container.append(self.buildFor(d[2], 'this week'));
57+
$container.append(self.buildFor(d[3], 'overall'));
58+
$container.children('div.scope:odd').css('margin-right', 0);
59+
},
60+
buildFor: function(data, name)
61+
{
62+
if (data.length == 0) {return;}
63+
var $div = $('<div class="scope">');
64+
$div.append('<h3>' + name + '</h3>');
65+
var $ul = $('<ul>');
66+
for(var i = 0; i < data.length; ++i)
67+
{
68+
var points = '<span>' + data[i]['points'] + '</span>';
69+
var name = '<li>' + data[i]['username'] + points + '</li>';
70+
$ul.append(name);
71+
}
72+
$ul.children(':last').css('border-bottom', 'none');
73+
return $div.append($ul);
74+
}
75+
};
76+
this.topScores = self;
77+
self.initialize();
78+
});
79+
};
80+
})(jQuery);

readme.markdown

+28-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# About #
22
The Mogade Javascript API allows anyone to load leaderboards on webpages using JSONP.
33

4-
Since mogade.com uses this libraries itself, and to avoid unnecessarily duplicating the code, you should grab these files from the core mogade-server project at: <https://github.com/mogade/mogade-server/tree/master/public/js/v1>
4+
The `jquery.leaderboard.js` shows leaderboard scopes.
55

6-
The `jquery.leaderboard.js` file is a jquery plugin aimed at helping developers easily do this.
6+
The `jquery.topScores.js` shows the top 3 scores for each scope for a given leaderboard.
77

8-
## Using It ##
8+
## Using Leaderboards ##
99
`sample.html` is a good place to start. `styles.css` is the style used by mogade.com for the facebook leaderboards.
1010

1111
Include `jquery`, then `jquery.leaderboard.js` on your page:
@@ -21,12 +21,11 @@ On document ready, load the leaderboard:
2121
<script type="text/javascript">
2222
$(document).ready(function()
2323
{
24-
$('#leaderboard').mogade({lids: [['4d58982c1d9517207b000006', 'Top Scores']]})
24+
$('#leaderboard').leaderboard({lids: [['4d58982c1d9517207b000006', 'Top Scores']]})
2525
});
2626
</script>
2727

28-
29-
## Options ##
28+
## Leaderboard Options ##
3029

3130
`lids` An array of leaderboard ids + name, [['Id1', 'Name1'], ['Optional Id2', 'Optional Name 2'] ... ]
3231

@@ -43,8 +42,30 @@ On document ready, load the leaderboard:
4342
### Using data ###
4443
Here's an example of how you might use data:
4544

46-
$('#leaderboard').mogade({lids: [['4d58982c1d9517207b000006', 'LB1], ['4d58982c1d9517207b000007', 'LB2']], data: {name: 'time', callback: function(data)
45+
$('#leaderboard').leaderboard({lids: [['4d58982c1d9517207b000006', 'LB1], ['4d58982c1d9517207b000007', 'LB2']], data: {name: 'time', callback: function(data)
4746
{
4847
return data + 'ms';
4948
}}})
5049

50+
## Using Top Scores ##
51+
The top ccores works almost identically to leaderboards. This time though you include the `jquery.topScores.js` file:
52+
53+
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
54+
<script type="text/javascript" src="jquery.leaderboard.js"></script>
55+
56+
create some type of container, like a `div`:
57+
58+
<div id="topscores"></div>
59+
60+
On document ready, load the top scores:
61+
62+
<script type="text/javascript">
63+
$(document).ready(function()
64+
{
65+
$('#topscores').topScores({lids: [['4d58982c1d9517207b000006', 'Top Scores']]})
66+
});
67+
</script>
68+
69+
## Top Scores Options ##
70+
71+
`lids` An array of leaderboard ids + name, [['Id1', 'Name1'], ['Optional Id2', 'Optional Name 2'] ... ]

styles.css

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
1+
#topscores{display:none;}
2+
#topscores div.scope {float:left;margin-right:25px;width:240px;}
3+
#topscores div.scope:nth-child(even) {margin-right:0;}
4+
#topscores h3{margin-bottom:5px;}
5+
#topscores ul{margin-bottom:10px;}
6+
#topscores li{padding:5px;border-bottom:1px solid #e0e0e0;}
7+
#topscores span{float:right;}
8+
#topscores .leaderboard_name{margin:20px 0;text-align:center;font-weight:bold;}
9+
10+
111
#leaderboard {display:none;width:550px;}
212
#leaderboard .leaderboard_name{margin:20px 0;text-align:center;font-weight:bold;}
3-
413
#leaderboard div.tabs{border-bottom:1px solid #ccc;overflow:auto;margin-bottom:5px;}
514
#leaderboard div.tabs > div {float:left;padding:5px 20px;margin-right:5px;background:#fff;cursor:pointer;-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;border-top-right-radius:4px;border-top-left-radius:4px;}
615
#leaderboard div.tabs > div.active{background:#eee;border:1px solid #ccc;border-bottom:none;}
7-
816
#leaderboard table{width:100%;display:none;border-collapse:collapse;}
917
#leaderboard th{font-weight:bold;text-align:left;border-bottom:2px solid #666;}
1018
#leaderboard th.rank{width:50px;}
@@ -13,7 +21,6 @@
1321
#leaderboard td, #leaderboard th{padding:5px;}
1422
#leaderboard tbody tr{border-bottom:1px dashed #eee;}
1523
#leaderboard tbody tr:nth-last-child(-n+1){border-bottom:none}
16-
1724
#leaderboard div.pager{margin-top:10px;}
1825
#leaderboard div.pager > div{cursor:pointer;color:#3B5998;padding:6px;border:1px solid #eee;-moz-border-radius: 4px;-webkit-border-radius: 4px;border-radius:4px;}
1926
#leaderboard div.pager div.prev{float:left;}

0 commit comments

Comments
 (0)