WebFund 2013F: Tutorial 9: Difference between revisions
(6 intermediate revisions by the same user not shown) | |||
Line 29: | Line 29: | ||
} | } | ||
</source> | </source> | ||
===app.js=== | ===app.js=== | ||
Line 140: | Line 141: | ||
exports.getContents = getContents; | exports.getContents = getContents; | ||
</source> | </source> | ||
===public/javascripts/adventure.js=== | ===public/javascripts/adventure.js=== | ||
<source line lang="javascript"> | <source line lang="javascript"> | ||
// adventure.js | |||
// client-side code for adventure AJAX demo | |||
(function() { // setup local scope | |||
var getRoom = function() { | |||
$.getJSON("/getContents", function(room) { | |||
var exits; | |||
$('#title').replaceWith('<h1 id="title">'+room.title+'</h1>'); | |||
$('#description').replaceWith('<p id="description">' + | |||
room.description + '</p>'); | |||
$('.exits').remove(); | |||
room.roomExits.forEach(function(theExit) { | |||
$('#exitList').append( | |||
'<button type="button" id="' + theExit + | |||
'" class="btn btn-default exits">' | |||
+ theExit + '</button>'); | |||
$('#'+theExit).on('click', function() { | |||
$.post("/doAction", {action: "move", | |||
room: theExit}); | |||
getRoom(); | |||
}); | |||
}); | |||
}); | |||
} | |||
$(window).load(getRoom()); | |||
})(); // finish setting up local scope (call function defined) | |||
</source> | </source> | ||
Line 151: | Line 181: | ||
<source line lang="javascript"> | <source line lang="javascript"> | ||
// rooms.js | |||
var rooms = { | |||
bridge: { | |||
title: "Bridge", | |||
description: "You are on the Bridge. There are big comfy chairs and a big screen here.", | |||
roomExits: ['sickbay'], | |||
}, | |||
engineering: { | |||
title: "Engineering", | |||
description: "You are in Engineering. There are lots of funny instruments, many smaller screens, and kind of uncomfortable chairs.", | |||
roomExits: ['sickbay'], | |||
}, | |||
sickbay: { | |||
title: "Sickbay", | |||
description: "You are in Sickbay. It is in the center of the ship, the safest place there is. There are lots of comfy beds here and blinky lights.", | |||
roomExits: ['engineering','bridge'], | |||
}, | |||
secret: { | |||
title: "Secret Room", | |||
description: "This is a secret room. How did you get here?", | |||
roomExits: ['engineering', 'sickbay', 'bridge'], | |||
}, | |||
TheVoid: { | |||
title: "The Void", | |||
description: "You are in the Void. This is the fate of all cheaters.", | |||
roomExits: ['TheVoid'], | |||
}, | |||
}; | |||
exports.rooms = rooms; | |||
</source> | </source> | ||
Line 158: | Line 222: | ||
<source line lang="javascript"> | <source line lang="javascript"> | ||
extends layout | |||
block content | |||
h1= title | |||
p Welcome to the #{title} | |||
- if(error) | |||
div.alert-error #{error} | |||
p Please choose your player name | |||
div | |||
form(action="/start", method="post") | |||
div.control-group.input-append | |||
input(type="text", name="player") | |||
label.add-on(for="player") Player Name | |||
button(type="submit") Start | |||
</source> | </source> | ||
===views/ | ===views/room.jade=== | ||
<source line lang="javascript"> | <source line lang="javascript"> | ||
extends layout | |||
block content | |||
script(src='/javascripts/adventure.js') | |||
h1(id="title") Room Name | |||
p(id="description") Room Description | |||
p Go to: | |||
div(id="exitList").btn-group | |||
button(type="button").btn.btn-default.exits Exits | |||
p | |||
form(action="/quit", method="post") | |||
button(type="submit") Quit | |||
</source> | </source> | ||
===views/ | ===views/layout.jade=== | ||
<source line lang="javascript"> | <source line lang="javascript"> | ||
doctype 5 | |||
html | |||
head | |||
title= title | |||
script(src='/libs/jquery/jquery.min.js') | |||
link(rel='stylesheet', href='/libs/bootstrap/css/bootstrap.min.css') | |||
link(rel='stylesheet', href='/stylesheets/style.css') | |||
body | |||
block content | |||
</source> | </source> |
Latest revision as of 18:31, 11 November 2013
In this tutorial you will be modifying adventure-ajax-demo, an updated version of Simple Adventure that now uses asynchronous background requests (AJAX) to navigate between rooms and update the page.
First, grab the code, either with modules or without. Then unzip it and get it running as usual. (If you download the version with modules, you shouldn't need to run npm install.)
Do the following:
- Create a room, the Holodeck, which is just connected to sick bay.
- Get to the secret room by editing and re-sending a post request.
- Modify the server code so that attempts to get to non-existent rooms instead send you to the Void.
- Modify the server code so that if the password "openSesame" is included in the post request, it allows users to enter the secret room. If users give the wrong password or no password at all, they should get redirected to the void.
- [BONUS] Modify the server so only allows users to exit using valid exits for the current room.
Code
package.json
{
"name": "application-name",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "3.4.0",
"jade": "*",
"stylus": "*",
"validator": "*"
}
}
app.js
/**
* Module dependencies.
*/
var express = require('express');
var routes = require('./routes');
var http = require('http');
var path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('COMP2406 rules!'));
app.use(express.session());
app.use(app.router);
app.use(require('stylus').middleware(__dirname + '/public'));
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
app.get('/game', routes.game);
app.get('/getContents', routes.getContents);
app.post('/start', routes.start);
app.post('/quit', routes.quit);
app.post('/doAction', routes.doAction);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
routes/index.js
var sanitize = require('validator').sanitize;
var rooms = require('../rooms.js').rooms;
function index(req, res) {
if (req.session.player) {
res.redirect("/game");
} else {
res.render('index', { title: 'COMP 2406 Adventure Demo',
error: req.query.error });
}
}
function start(req, res) {
var player = req.body.player;
// Sanitize the player name as it may be displayed
req.session.player = sanitize(player).escape();
req.session.currentRoom = "bridge"; // We start on the bridge
res.redirect("/game")
}
function quit(req, res) {
req.session.destroy(function(err){
if(err){
console.log("Error: %s", err);
}
});
res.redirect("/");
}
function game(req, res) {
if (req.session.player) {
res.render("room.jade", {title: "Adventure Demo"});
} else {
res.redirect("/");
}
}
function doAction(req, res) {
var action = req.body.action;
var room = req.body.room;
if (action === "move") {
req.session.currentRoom = room;
res.send("Success");
} else {
res.send("Error: InvalidAction");
}
}
function getContents(req, res) {
res.send(rooms[req.session.currentRoom]);
}
exports.index = index;
exports.start = start;
exports.quit = quit;
exports.game = game;
exports.doAction = doAction;
exports.getContents = getContents;
public/javascripts/adventure.js
// adventure.js
// client-side code for adventure AJAX demo
(function() { // setup local scope
var getRoom = function() {
$.getJSON("/getContents", function(room) {
var exits;
$('#title').replaceWith('<h1 id="title">'+room.title+'</h1>');
$('#description').replaceWith('<p id="description">' +
room.description + '</p>');
$('.exits').remove();
room.roomExits.forEach(function(theExit) {
$('#exitList').append(
'<button type="button" id="' + theExit +
'" class="btn btn-default exits">'
+ theExit + '</button>');
$('#'+theExit).on('click', function() {
$.post("/doAction", {action: "move",
room: theExit});
getRoom();
});
});
});
}
$(window).load(getRoom());
})(); // finish setting up local scope (call function defined)
rooms.js
// rooms.js
var rooms = {
bridge: {
title: "Bridge",
description: "You are on the Bridge. There are big comfy chairs and a big screen here.",
roomExits: ['sickbay'],
},
engineering: {
title: "Engineering",
description: "You are in Engineering. There are lots of funny instruments, many smaller screens, and kind of uncomfortable chairs.",
roomExits: ['sickbay'],
},
sickbay: {
title: "Sickbay",
description: "You are in Sickbay. It is in the center of the ship, the safest place there is. There are lots of comfy beds here and blinky lights.",
roomExits: ['engineering','bridge'],
},
secret: {
title: "Secret Room",
description: "This is a secret room. How did you get here?",
roomExits: ['engineering', 'sickbay', 'bridge'],
},
TheVoid: {
title: "The Void",
description: "You are in the Void. This is the fate of all cheaters.",
roomExits: ['TheVoid'],
},
};
exports.rooms = rooms;
views/index.jade
extends layout
block content
h1= title
p Welcome to the #{title}
- if(error)
div.alert-error #{error}
p Please choose your player name
div
form(action="/start", method="post")
div.control-group.input-append
input(type="text", name="player")
label.add-on(for="player") Player Name
button(type="submit") Start
views/room.jade
extends layout
block content
script(src='/javascripts/adventure.js')
h1(id="title") Room Name
p(id="description") Room Description
p Go to:
div(id="exitList").btn-group
button(type="button").btn.btn-default.exits Exits
p
form(action="/quit", method="post")
button(type="submit") Quit
views/layout.jade
doctype 5
html
head
title= title
script(src='/libs/jquery/jquery.min.js')
link(rel='stylesheet', href='/libs/bootstrap/css/bootstrap.min.css')
link(rel='stylesheet', href='/stylesheets/style.css')
body
block content