Multiple form entries
Experimental UX for entering multiple entries of the same object. Uses Backbone and localStorage to persist data. Won't work in IE9-
by davidhong
HTML
<link rel="stylesheet" href="http://twitter.github.com/bootstrap/1.4.0/bootstrap.min.css">
<script src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
<script src="http://documentcloud.github.com/backbone/backbone-min.js"></script>
<script src="https://raw.github.com/janl/mustache.js/master/mustache.js"></script>
<script src="https://github.com/hongymagic/jQuery.serializeObject/raw/master/jQuery.serializeObject.js"></script>
<script src="http://documentcloud.github.com/backbone/examples/backbone-localstorage.js"></script>
<div id="pets" class="well">
<header>
<h1>Register your pets</h1>
<caption>All form entries are automatically saved</caption>
</header>
<form type="post" class="form-stacked clearfix">
</form>
<div class="well">
<button id="create" class="btn success">I have another pet</button>
<button id="save" class="btn primary">I have entered all my pets, continue</button>
</div>
</div>
<!--
Mustache template representing each Pet
-->
<script type="html/template" id="pet">
<fieldset id="pet-{{cid}}" class="alert-message block-message success">
<div class="close">×</div>
<h2>Pet #{{cid}}<h2>
<div class="field clearfix">
<input name="name[{{cid}}]" type="text" placeholder="Name of your pet" value="{{name}}" />
</div>
<div class="field clearfix">
<input name="breed[{{cid}}]" type="text" placeholder="Breed of your pet" value="{{breed}}" />
</div>
<ul class="field input-lists">
<li>
<label for="type-cat[{{cid}}]"><input name="type[{{cid}}]" type="radio" id="type-cat[{{cid}}]" value="cat"><span>Cat</span></label>
</li>
<li>
<label for="type-dog[{{cid}}]"><input name="type[{{cid}}]" type="radio" id="type-dog[{{cid}}]" value="dog"><span>Dog</span></label>
</li>
</ul>
</fieldset>
</script>
CSS
img, article, aside, figure, footer, header, hgroup, menu, nav, section { display: block; }
#pets { margin: 1em auto; max-width: 640px; }
form { display: block; }
form .close { color: red; cursor: pointer; }
form ul { list-style-type: none; }
JavaScript
$(function() {
// Pet model
var Pet = Backbone.Model.extend({
name: '',
breed: '',
type: ''
});
// Pets collection
// This collection is persisted via localStorage
var PetsList = Backbone.Collection.extend({
model: Pet,
localStorage: new Store("pets")
});
// Pet entry view
PetEntryView = Backbone.View.extend({
template: $('#pet').html(),
initialize: function() {
this.render();
},
render: function() {
var model = this.model.toJSON();
model.cid = this.model.cid;
$(this.el).html(Mustache.to_html(this.template, model));
return this;
},
events: {
'click .close': 'close',
'keyup input': 'save',
'click input': 'save'
},
close: function() {
if (confirm('Are you sure you wish to remove this pet?')) {
this.model.destroy();
$(this.el).remove();
}
},
save: function() {
var $el = $(this.el);
this.model.save({
name: $el.find('[name="name\[' + this.model.cid + '\]"]').val(),
type: $el.find('[name="type\[' + this.model.cid + '\]"]:selected').val(),
breed: $el.find('[name="breed\[' + this.model.cid + '\]"]').val()
});
}
});
// Pets entry list view
PetsEntryView = Backbone.View.extend({
el: $('#pets'),
initialize: function() {
Pets.bind('add', this.add, this);
Pets.bind('reset', this.addAll, this);
Pets.bind('all', this.render, this);
// Fetch data from localStorage
Pets.fetch();
// If there are no pets, add a new one by default
if (Pets.length === 0) {
Pets.add(new Pet);
}
},
events: {
'click #create': 'create',
...