Permalink
Browse files

Added shoutbox example.

  • Loading branch information...
1 parent d86b08e commit 040c498d1846e03fdc5017c432e1ff730ee59489 @cskr committed Aug 3, 2010
@@ -0,0 +1,29 @@
+var gh = require('../grasshopper'),
+ shoutRepo = require('./shoutRepository'),
+ Shout = require('./model').Shout;
+
+gh.get('/', function() {
+ var self = this;
+ shoutRepo.all(function(err, shouts) {
+ self.model['shout'] = new Shout();
+ self.model['shouts'] = shouts;
+ self.render('index');
+ });
+});
+
+gh.post('/', function() {
+ var self = this;
+ var shout = new Shout().update(this.params['shout']);
+ if(shout.isValid()) {
+ shoutRepo.save(shout, function() {
+ self.flash['success'] = 'Thanks for shouting!';
+ self.redirect('/');
+ });
+ } else {
+ shoutRepo.all(function(err, shouts) {
+ self.model['shouts'] = shouts;
+ self.model['shout'] = shout;
+ self.render('index');
+ });
+ }
+});
@@ -0,0 +1,18 @@
+var gh = require('../grasshopper'),
+ crypto = require('crypto');
+
+function Shout() {
+}
+
+exports.Shout = gh.initModel(Shout, 'name', 'email', 'message');
+
+Shout.prototype.validate = function() {
+ this.validateRequired('name', 'Name is required.', false);
+ this.validateRequired('email', 'Email is required.', false);
+ this.validateRequired('message', 'Message is required.', false);
+};
+
+Shout.prototype.mailHash = function() {
+ return crypto.createHash('md5').update(this.email()).digest('hex');
+};
+
@@ -0,0 +1,31 @@
+var couchdb = require('../../support/node-couchdb/lib/couchdb'),
+ Shout = require('./model').Shout;
+
+exports.all = function(cb) {
+ var db = couchdb.createClient().db('shout');
+ db.view('shout', 'all', {}, function(err, res) {
+ if(!err) {
+ var shouts = []
+ res.rows.forEach(function(row) {
+ var shout = new Shout();
+ shout.name(row.value.name)
+ .email(row.value.email)
+ .message(row.value.message);
+ shouts.push(shout);
+ });
+ }
+ cb(err, shouts);
+ });
+};
+
+exports.save = function(shout, cb) {
+ var doc = {
+ name: shout.name(),
+ email: shout.email(),
+ message: shout.message()
+ };
+ var db = couchdb.createClient().db('shout');
+ db.saveDoc(doc, function(err) {
+ cb(err);
+ });
+};
View
@@ -0,0 +1,10 @@
+var gh = require('./grasshopper');
+
+gh.configure({
+ layout: 'views/layout',
+ viewsDir: 'views'
+});
+
+require('./app/controller');
+
+gh.serve(8080);
@@ -0,0 +1,14 @@
+var couchdb = require('../support/node-couchdb/lib/couchdb'),
+ client = couchdb.createClient();
+
+client.request('put', '/shout');
+
+client.db('shout').saveDesign('shout', {
+ views: {
+ all: {
+ map: function(doc) {
+ emit(null, doc);
+ }
+ }
+ }
+});
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1,160 @@
+* {
+margin: 0;
+padding: 0;
+}
+
+body {
+background: #323f66 top center url("../images/back.png") no-repeat;
+color: #ffffff;
+font-family: Helvetica, Arial, Verdana, sans-serif;
+}
+
+h1 {
+font-size: 3.5em;
+letter-spacing: -1px;
+background: url("../images/shoutbox.png") no-repeat;
+width: 303px;
+height: 66px;
+margin: 0 auto;
+text-indent: -9999em;
+color: #33ccff;
+}
+
+h2 {
+font-size: 2em;
+letter-spacing: -1px;
+background: url("../images/shout.png") no-repeat;
+width: 119px;
+height: 44px;
+text-indent: -9999em;
+color: #33ccff;
+clear: both;
+margin: 15px 0;
+}
+
+h5 a:link, h5 a:visited {
+color: #ffffff;
+text-decoration: none;
+}
+
+h5 a:hover, h5 a:active, h5 a:focus {
+border-bottom: 1px solid #fff;
+}
+
+p {
+font-size: 0.9em;
+line-height: 1.3em;
+font-family: Lucida Sans Unicode, Helvetica, Arial, Verdana, sans-serif;
+}
+
+p.error, .errorExplanation li {
+background-color: #603131;
+border: 1px solid #5c2d2d;
+padding: 10px !important;
+margin-bottom: 15px;
+}
+
+p.success {
+background-color: #313d60;
+border: 1px solid #2d395c;
+padding: 10px;
+margin-bottom: 15px;
+}
+
+#container {
+width: 664px;
+margin: 20px auto;
+text-align: center;
+}
+
+#boxtop {
+margin: 30px auto 0px;
+background: url("../images/top.png") no-repeat;
+width: 663px;
+height: 23px;
+}
+
+#boxbot {
+margin: 0px auto 30px;
+background: url("../images/bot.png") no-repeat;
+width: 664px;
+height: 25px;
+}
+
+#content {
+margin: 0 auto;
+width: 600px;
+text-align: left;
+background: url("../images/bg.png") repeat-y;
+padding: 15px 35px;
+overflow: hidden;
+}
+
+#content ul {
+margin-left: 0;
+margin-bottom: 15px;
+}
+
+#content ul li {
+list-style: none;
+clear: both;
+padding-top: 30px;
+}
+
+#content ul li:first-child {
+padding-top:0;
+}
+
+.meta {
+width: 85px;
+text-align: left;
+float: left;
+min-height: 110px;
+font-weight: bold;
+}
+
+.meta img {
+padding: 5px;
+background-color: #313d60;
+}
+
+.meta p {
+font-size: 0.8em;
+}
+
+.shout {
+width: 500px;
+float: left;
+margin-left: 15px;
+min-height: 110px;
+padding-top: 5px;
+}
+
+form {
+clear: both;
+margin-top: 135px !important;
+}
+
+.fname, .femail {
+width: 222px;
+float: left;
+}
+
+form p {
+font-weight: bold;
+margin-bottom: 3px;
+}
+
+form textarea {
+width: 365px;
+overflow: hidden;
+}
+
+form input, form textarea {
+background-color: #313d60;
+border: 1px solid #2d395c;
+color: #ffffff;
+padding: 5px;
+font-family: Lucida Sans Unicode, Helvetica, Arial, Verdana, sans-serif;
+margin-bottom: 10px;
+}
@@ -0,0 +1,41 @@
+<% if(shout.errors) { %>
+ <p class="error">
+ <%= errors(shout).join('</p><p class="error">') %>
+ </p>
+<% } %>
+<% if(flash['success']) { %>
+ <p class="success"><%= flash['success'] %></p>
+<% } %>
+
+<ul>
+ <% shouts.forEach(function(shout) { %>
+ <li>
+ <div class="meta">
+ <img src="http://www.gravatar.com/avatar/<%= shout.mailHash() %>"
+ alt="Gravatar" />
+ <p><%= h(shout.name()) %></p>
+ </div>
+ <div class="shout">
+ <p><%= h(shout.message()) %></p>
+ </div>
+ </li>
+ <% }); %>
+</ul>
+
+<form action="/" method="post">
+ <h2>Shout!</h2>
+
+ <div class="fname">
+ <label for="name"><p>Name:</p></label>
+ <input type="text" name="shout.name" value="<%= shout.name() %>" size="20" />
+ </div>
+
+ <div class="femail">
+ <label for="email"><p>Email:</p></label>
+ <input type="text" name="shout.email" value="<%= shout.email() %>" size="20" />
+ </div>
+
+ <textarea name="shout.message" rows="5" cols="40"><%= shout.message() %></textarea>
+
+ <p><input type="submit" value="Submit" /></p>
+</form>
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+ <head>
+ <title>Shoutbox in Grasshopper</title>
+ <link href="/stylesheets/style.css" rel="stylesheet" type="text/css"></link>
+ </head>
+ <body>
+ <div id="container">
+ <h1>Shoutbox</h1>
+
+ <div id="boxtop"></div>
+ <div id="content">
+ <%= include(view) %>
+ </div>
+ <div id="boxbot"></div>
+ </div>
+ </body>
+</html>

0 comments on commit 040c498

Please sign in to comment.