Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple CRUD function for couchapps
{
activate: function(e, id) {
// activate the form, enabling edits
if (id == "new"){
$(this).trigger('newitem');
} else {
$(this).trigger('loaditem', id);
}
},
loaditem: function(e, id) {
// load data from couchdb and display it in the form
this.reset();
var that = this;
$$(this).app.db.openDoc(id, {
error: function() {
$$(that).ldoc = {_id:id}
that.reset();
},
success: function(doc){
$$(that).ldoc = doc;
var fdoc = $.flatten(doc);
for (var name in fdoc){
$(':input[name='+name+']', that).val(fdoc[name]);
$(':checkbox[name='+name+']', that).attr('checked',fdoc[name]);
}
$(that).trigger('postconstruct');
}
})
},
newitem: function(e) {
// activate form for new items
this.reset();
$$(this).ldoc = {};
$(this).trigger('postconstruct');
},
removeitem: function(e){
// Self-explanatory, delete doc from couchdb
if (confirm("Are you sure?")){
$$(this).app.db.removeDoc($$(this).ldoc);
$(this).trigger('predestroy');
}
},
submit: function(e){
// encode the data in form and save it to couchdb
var reg = $.extend({},$$(this).ldoc, $(this).toDeepJson());
var that = this;
$$(this).app.db.saveDoc(reg,{
success: function(res){
reg._id = res.id;
reg._rev = res.rev;
$$(that).ldoc = reg;
$(that).trigger('postconstruct');
}
});
return false;
}
}
(function( $ ){
$.fn.toDeepJson = function() {
function parse(val){
if (val == ""){ return null; }
if (val == "true"){ return true; }
if (val == "false"){ return false; }
if (val == String(parseInt(val))){ return parseInt(val); }
if (val == String(parseFloat(val))){ return parseFloat(val); }
return val;
}
function toNestedObject(obj, arr){
var key = arr.shift();
if (arr.length > 0) {
obj[key] = toNestedObject(obj[key] || {}, arr);
return obj;
}
return key;
}
if (this.length == 1){
return $.makeArray(this[0].elements)
.filter(function(e){
return e.name && e.name != "" && (e.type == 'radio' ? e.checked : true);
})
.map(function(e){
var names = e.name.split('.');
if (e.type == 'checkbox') {
e.value = e.checked;
}
names.push(parse(e.value));
return names;
})
.reduce(toNestedObject, {});
} else {
throw({error:"Can work on a single form only"})
}
};
$.flatten = function (obj){
var ret = {}
for (var key in obj){
if (typeof obj[key] == 'object'){
var fobj = $.flatten(obj[key]);
for (var extkey in fobj){
ret[key+"."+extkey] = fobj[extkey];
}
} else {
ret[key] = String(obj[key]);
}
}
return ret;
}
})( jQuery );

CRUD requires jquery.deepjson.js to work so it should be included

<script type="text/javascript" src="js/jquery.deepjson.js"></script>

Then you can assign whatever's in crud.json to a variable or you can put crud.json into your evently directory and let couchapp push it to your application.

Simplest way to use it is

$.couch.app(function(app) {
  $('#form').evently(app.ddoc.evently.crud, app);
}

If you want to put some lifecycle methods around (you usually need)

$.couch.app(function(app) {
  $('#form').evently($.extend({}, app.ddoc.evently.crud, {
    postconstruct: function(e){
      // after form readies itself for editing
      // may show form or delete buttons here
    },
    predestroy: function(e) {
      // triggers on object deletion only
      // useful to hide form
    }
  }), app);
}

Then you can add function to your controls like

$('.items a').click(function(e){
    // edit item, doc id presumed set to id attr of a
    $('#form').trigger('activate',$(this).attr('id'));
});
$('button.new').click(function(e){
    // ready form for a new item
    $('#form').trigger('activate', 'new');
});
$('button.save').click(function(e){
    // save the form
    $('#form').submit();
});
$('button.delete').click(function(e){
    // delete the item set in form
    $('#form').trigger('removeitem');
});

It is possible to use $$('#form').ldoc to access the doc itself.

@stephenbez
Copy link

stephenbez commented Jul 18, 2012

toDeepJson will fail if any element inside the form doesn't have the name attribute defined (jquery.deepjson.js:25 trying to split undefined).

For example if you form includes a label, then toDeepJson will fail.

@agaoglu
Copy link
Author

agaoglu commented Jul 19, 2012

According to w3c spec, HTMLFormElement.elements should not return non-control types such as label. It will fail if someone decides to use a control w/o a name though. Should be fixed now. Thanks for the heads up.

@robinvk6
Copy link

robinvk6 commented Mar 1, 2013

I see an issue the deepJson.js file in IE. Can you please check why this doesnt work in IE.

Webpage error details

User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; InfoPath.2; .NET4.0C; .NET4.0E; MS-RTC LM 8)
Timestamp: Fri, 1 Mar 2013 15:24:01 UTC

Message: Object doesn't support this property or method
Line: 20
Char: 7
Code: 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment