Skip to content

Instantly share code, notes, and snippets.

@g-k
Created October 23, 2012 01:23
Show Gist options
  • Save g-k/3936113 to your computer and use it in GitHub Desktop.
Save g-k/3936113 to your computer and use it in GitHub Desktop.
meteor.js leaderboard example exercises
body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 200;
margin: 50px 0;
padding: 0;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
#outer {
width: 600px;
margin: 0 auto;
}
.player {
cursor: pointer;
padding: 5px;
}
.player .name {
display: inline-block;
width: 300px;
font-size: 1.75em;
}
.player .score {
display: inline-block;
width: 100px;
text-align: right;
font-size: 2em;
font-weight: bold;
color: #777;
}
.player.selected {
background-color: yellow;
}
.player.selected .score {
color: black;
}
.details, .none {
font-weight: bold;
font-size: 2em;
border-style: dashed none none none;
border-color: #ccc;
border-width: 4px;
margin: 50px 10px;
padding: 10px 0px;
}
.none {
color: #777;
}
.inc {
cursor: pointer;
}
<head>
<title>Leaderboard</title>
</head>
<body>
<div id="outer">
{{> leaderboard}}
</div>
</body>
<template name="leaderboard">
<div>
Sorting by {{currentSortBy}}. Sort By:
{{#each sortBy}}
<input type="button" class="sortBy {{selectedSortBy}}" value="{{value}}" />
{{/each}}
</div>
<div class="leaderboard">
{{#each players}}
{{> player}}
{{/each}}
</div>
{{#if selected_name}}
<div class="details">
<div class="name">{{selected_name}}</div>
<input type="button" class="inc" value="Give 5 points" />
</div>
{{/if}}
{{#unless selected_name}}
<div class="none">Click a player to select</div>
{{/unless}}
<input type="button" class="reset" value="Reset Scores" />
<input type="button" class="add" value="Add Player" />
<input type="text" id="add-player-name" />
</template>
<template name="player">
<div class="player {{selected}}">
<span class="name">{{name}}</span>
<span class="score">{{score}}</span>
<input type="button" class="remove" value="X" />
</div>
</template>
// Set up a collection to contain player information. On the server,
// it is backed by a MongoDB collection named "players".
Players = new Meteor.Collection("players");
Players.reset = function (names) {
if (!names) {
names = _.pluck(Players.find().fetch(), 'name');
}
for (var i = 0; i < names.length; i++)
Players.update({'name': names[i] }, { $set: { score: Math.floor(Math.random()*10)*5}});
};
// Shouldn't be visible on the client
Players.validName = function (name) {
// Must have name and name must be alpha or space chars
if (name && /^[A-Za-z ]+$/.test(name)) {
return true;
}
return false;
};
Players.addPlayer = function (name) {
if (Players.validName(name)) {
return Players.insert({name: name, score: Math.floor(Math.random()*10)*5 });
} else {
throw new Error("Invalid Name");
}
};
if (Meteor.isClient) {
Template.leaderboard.players = function () {
var sortBy = Session.get('sortBy');
var sort = {};
// Hack to set entire object
if (sortBy === 'name') {
sort = { name: 1, score: -1 };
} else if (sortBy === 'score') {
sort = { score: -1, name: 1 };
}
return Players.find({}, {sort: sort});
};
Template.leaderboard.sortBy = [
{ value: "name" },
{ value: "score" }
];
Template.leaderboard.currentSortBy = function () {
return Session.get("sortBy");
};
Template.leaderboard.selectedSortBy = function () {
return Session.equals("sortBy", this.value) ? "selected" : '';
};
Template.leaderboard.selected_name = function () {
var player = Players.findOne(Session.get("selected_player"));
return player && player.name;
};
Template.player.selected = function () {
return Session.equals("selected_player", this._id) ? "selected" : '';
};
Template.leaderboard.events({
'click input.inc': function () {
Players.update(Session.get("selected_player"), {$inc: {score: 5}});
},
'click input.reset': function () {
Players.reset();
},
'click input.add': function () {
var name = document.getElementById('add-player-name').value;
Players.addPlayer(name);
// Reset input
document.getElementById('add-player-name').value = '';
},
'click .sortBy': function () {
Session.set('sortBy', this.value);
}
});
Template.player.events({
'click': function () {
Session.set("selected_player", this._id);
},
'click .remove': function () {
Players.remove({ _id: this._id });
}
});
Session.get("sortBy") || Session.set('sortBy', 'score');
}
// On server startup, create some players if the database is empty.
if (Meteor.isServer) {
Meteor.startup(function () {
if (Players.find().count() === 0) {
var names = ["Ada Lovelace",
"Grace Hopper",
"Marie Curie",
"Carl Friedrich Gauss",
"Nikola Tesla",
"Claude Shannon"];
for (var i = 0; i < names.length; i++) {
Players.insert({name: names[i]});
}
Players.reset(names);
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment