Skip to content
This repository has been archived by the owner on Dec 1, 2017. It is now read-only.

Minimal backbone version #11

Merged
merged 22 commits into from
Mar 27, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ Testing policy

Review policy
-------------
* Pull requests that are pair-programmed with at least one committer do not
require code review, although contributors are encouraged to request it
* Pull requests that are pair-programmed with at least one committer do not
require code review, although contributors are encouraged to request it
if another set of eyes seems important. Pair-programmed merges should
include a sentence like `These commits were paired on by n10k and dmose`.
* Otherwise, pull-requests require code review:
Expand Down
11 changes: 9 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
test: mocha jshint

mocha:
@./node_modules/mocha/bin/mocha --reporter spec
install:
@npm install

jshint:
@jshint *.js static test

mocha:
@./node_modules/mocha/bin/mocha --reporter spec

runserver:
@env PORT=5000 node app.js

.PHONY: test

7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,21 @@ Local Development

2. Make sure you have [node installed](http://nodejs.org/).

3. Install the required node modules:
3. Install the required node dependencies:

$ npm install
# or alternatively:
$ make install

4. Start the server:

$ env PORT=5000 node app.js
# or alternatively:
$ make runserver

5. Point your web browser to [http://localhost:5000](http://localhost:5000).


Unit Tests
----------

Expand Down
28 changes: 16 additions & 12 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,30 @@ function findNewNick(aNick) {
return nickParts[1] + newDigits;
}

server.get('/users', function(req, res) {
res.send(200, JSON.stringify(server.get('users')));
});

server.post('/signin', function(req, res) {
var users = server.get('users');
var nick = req.body.nick;
while (users.indexOf(nick) !== -1)
function exists(nick) {
return users.some(function(user) {
return user.nick === nick;
});
}
while (exists(nick))
nick = findNewNick(nick);
res.send(200, JSON.stringify({nick: nick, users: users}));
users.push(nick);
users.push({nick: nick});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason why this was sending the reply before pushing the new nick to the users array is that this way I didn't have to filter the user's nick out of the received list of contacts on the front-end side (offering a user to call himself doesn't make sense).

I haven't searched very hard, but I didn't see any code in the front-end here that filters out the user's nick.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking of adding no link to the user's own entry adn maybe suffixing it with (me)… a bit like what some irc clients do, but now I'm not so sure :/

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now there is no UI to call someone, so it's not a bug (yet). We can decide what to do when the feature will be implemented.
For me it's not a blocker.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the "As the first user logged in, I see a message that I am the only person logged in, and see an offer to invite friends" story is no longer done, then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed! I implemented it in other prs but not in this one. I'll be fixing that right now. Should I create a new PR for the fix?

server.set('users', users);
res.send(200, JSON.stringify({nick: nick, users: users}));
});

server.post('/signout', function(req, res) {
var users = server.get('users');
var pos = users.indexOf(req.body.nick);
if (pos === -1)
res.send(404, 'User not logged in');

users.pop(pos);
server.set('users', users);

res.send(200);
server.set('users', server.get('users').filter(function(user) {
return user.nick !== req.body.nick;
}));
res.send(200, JSON.stringify(true));
});

var _listen = server.listen;
Expand Down
45 changes: 36 additions & 9 deletions static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,43 @@
<head>
<meta charset="utf-8">
<title>Talkilla</title>
<script type="text/javascript" src="talkilla.js"></script>
<style>
.hide {display:none;}
</style>
<link href="vendor/bootstrap-2.1.1/css/bootstrap.css" rel="stylesheet">
<link href="vendor/bootstrap-2.1.1/css/bootstrap-responsive.css" rel="stylesheet">
</head>

<body>
<h1 id="title">Welcome to Talkilla!</h1>
<form id="login" onsubmit="login(); return false;" action="signin" method="post">
<p>Please enter a nickname to use with Talkilla: <input id="nick" name="nick" type="text">
<input id="submit" type="submit"></p>
</form>
<p id="invite" style="display: none">You are the only person logged in, invite your friends.</p>
<ul id="friends"></ul>
<div class="container-fluid">
<div class="row-fluid">
<h1>Welcome to Talkilla!</h1>
</div>
<div class="row-fluid">
<div class="span9" id="login">
<form action="signin" method="post" id="signin" class="form-inline">
<label for="nick">Please enter a nickname to use with Talkilla:</label><br>
<div class="input-prepend">
<span class="add-on"><i class="icon-user"></i></span>
<input class="input-small" placeholder="nickname" id="nick" name="nick" type="text">
</div>
<input class="btn" id="submit" type="submit" value="Join">
</form>
<form action="/signout" id="signout" method="post" class="hide">
<p>Joined as <strong class="nick"></strong>
| <button class="btn" type="submit">sign out</button></p>
</form>
</div>
<div class="span3" id="users">
<ul class="nav nav-list">
<li class="nav-header">Online users</li>
<li>Empty room</li>
</ul>
</div>
</div>
</div>
<script src="vendor/jquery-1.9.1.js"></script>
<script src="vendor/underscore-1.4.4.js"></script>
<script src="vendor/backbone-1.0.0.js"></script>
<script src="js/talkilla.js"></script>
</body>
</html>
148 changes: 148 additions & 0 deletions static/js/talkilla.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/*global jQuery, Backbone*/
/* jshint unused: false */
var Talkilla = (function($, Backbone) {
"use strict";
var app = {data: {}};

function login(nick, cb) {
$.ajax({
type: "POST",
url: '/signin',
data: {nick: nick},
dataType: 'json'
})
.done(function(auth) {
return cb(null,
new app.User({nick: auth.nick}),
new app.UserSet(auth.users));
})
.fail(function(xhr, textStatus, error) {
return cb(error);
});
}

function logout(cb) {
$.ajax({
type: "POST",
url: '/signout',
data: {nick: app.data.user && app.data.user.get('nick')},
dataType: 'json'
})
.done(function(result) {
return cb(null, result);
})
.fail(function(xhr, textStatus, error) {
return cb(error);
});
}

app.Router = Backbone.Router.extend({
routes: {
'': 'index'
},

index: function() {
// login form
if (this.loginView)
this.loginView.undelegateEvents();
this.loginView = new app.LoginView(app.data);
this.loginView.render();

// users list
if (this.usersView)
this.usersView.undelegateEvents();
this.usersView = new app.UsersView(app.data);
this.usersView.render();
}
});

app.User = Backbone.Model.extend({
defaults: {nick: undefined}
});

app.UserSet = Backbone.Collection.extend({
url: '/users',
model: app.User
});

app.UsersView = Backbone.View.extend({
el: '#users',

initialize: function(options) {
this.collection = options && options.users;
if (this.collection)
return this.render();
this.collection = new app.UserSet();
this.collection.fetch({
error: function() {
alert('Could not load connected users list');
},
success: function(users) {
this.render();
}.bind(this)
});
},

render: function() {
var $list = this.$el.find('ul');
$list.find('li:not([class=nav-header])').remove();
this.collection.each(function(user) {
$list.append($('<li/>').text(user.get('nick')));
});
return this;
}
});

app.LoginView = Backbone.View.extend({
el: '#login',

events: {
'submit form#signin': 'signin',
'submit form#signout': 'signout'
},

initialize: function(options) {
this.user = options && options.user;
},

render: function() {
if (!this.user) {
this.$el.find('#signin').show();
this.$el.find('#signout').hide().find('.nick').text('');
} else {
this.$el.find('#signin').hide();
this.$el.find('#signout').show().find('.nick')
.text(this.user.get('nick'));
}
return this;
},

signin: function(event) {
event.preventDefault();
var nick = $.trim($(event.currentTarget).find('[name="nick"]').val());
if (!nick)
return alert('please enter a nickname');
login(nick, function(err, user, users) {
if (err)
return alert(err);
app.data.user = user;
app.data.users = users;
app.router.index();
});
},

signout: function(event) {
event.preventDefault();
logout(function(err) {
if (err)
return alert(err);
app.data.user = app.data.users = undefined;
app.router.index();
});
}
});

app.router = new app.Router();
Backbone.history.start();
return app;
})(jQuery, Backbone);
28 changes: 0 additions & 28 deletions static/talkilla.js

This file was deleted.

Loading