Monday, February 22, 2010

CouchApp success() and beforeSave()

‹prev | My Chain | next›

I have my basic recipe edit couchapp work pretty well at this point. There are still a few things that I am not quite sure about:
  • jQuery effects after save (this ought to be easy)
  • defaulting new document IDs to be human readable
  • image upload (I'm not sure this is even possible right now)
  • mapping deep data structures into form variables
  • listing pages to edit
As I say, I doubt that image upload is doable without modifying couchapp—I will leave that to another day (or hope someone else will enlighten me). The others I will work through in order.

First up: jQuery effects upon successful save. This seems fairly trivial. Up until now I have been using tracer bullets to ensure that I am hitting the callbacks I expect in docForm() (a couchapp function that maps form fields to JSON attributes for POST/PUT to the CouchDB database):
// in my edit.html template:
$.CouchApp(function(app) {

app.docForm("form#update-recipe", {
id : <%= docid %>,
fields: ['title', 'summary', 'instructions'],
template: {type: "Recipe"},
beforeSave: function(doc) {
alert("Here!");
},
success: function(res, doc) {
alert("Success!");
}
});
});
Rather than alerting success, I will fade the message in, wait for 3 seconds, then fade out:
$.CouchApp(function(app) {

app.docForm("form#update-recipe", {
id : <%= docid %>,
fields: ['title', 'summary', 'instructions'],
template: {type: "Recipe"},
beforeSave: function(doc) {
// alert("Here!");
},
success: function(res, doc) {
$('#saved').fadeIn().animate({ opacity: 1.0 },3000).fadeOut();
}
});
});
(the #saved id element is a <span> containing the text "Saved")

Now when I click "Save", I see a little "Saved" animation show:



Easy enough (save for the animate() hack that is needed pre-jQuery 1.4)

Onto human-readable IDs...

Right now, I am ending up with document IDs like "09dd3376209faf7aecb08bcbb460d545", which gives me ugly URLs like: http://localhost:5984/eee/_design/relax/_show/edit/09dd3376209faf7aecb08bcbb460d545. Ever since this cooking site was Perl/XML, we had IDs like "2010-02-22-test". I can use another couchapp callback, beforeSave, to get this right.

The beforeSave() callback receives a single argument: the JSON representation of the HTML form. Currently, for a new recipe, this would contain a title, a recipe summary, and instructions. Missing are the date and a pretty ID.

This beforeSave() should add a date (in ISO 8601 format) if one is not present. If the date is not already present, it will set a pretty ID by concatenating the date and a "slugified" title:
$.CouchApp(function(app) {

app.docForm("form#update-recipe", {
id : <%= docid %>,
fields: ['title', 'summary', 'instructions'],
template: {type: "Recipe"},
beforeSave: function(doc) {
var date = new Date();
function zero_pad(num) {
return ((num.toString()).length == 1) ? "0" + num : num.toString();
}
if (!doc.date) {
doc.date = date.getFullYear() + '-' +
zero_pad(date.getMonth() + 1) + '-' +
zero_pad(date.getDate());
doc._id = doc.date + '-' + app.slugifyString(doc.title);
}
}
,
success: function(res, doc) {
$('#saved').fadeIn().animate({ opacity: 1.0 },3000).fadeOut();
}
});
});
(happily, slugifyString is provided by couchapp)

Now, when I save a new document, I see that couchapp has, indeed, used my pretty ID:
[Tue, 23 Feb 2010 03:26:49 GMT] [info] [<0.30439.3>] 127.0.0.1 - - 'PUT' /eee/2010-02-22-test 201
That's a good stopping point. After getting some easy stuff out of the way, I have the feeling that things will get progressively more difficult in the days to come.

Day #22

No comments:

Post a Comment