rails-backbone-forms 0.11.1 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,7 @@
1
- ;(function() {
2
-
3
- var Form = Backbone.Form,
4
- editors = Form.editors;
1
+ ;(function(Form) {
5
2
 
6
3
  /**
7
- * LIST
4
+ * List editor
8
5
  *
9
6
  * An array editor. Creates a list of other editor items.
10
7
  *
@@ -12,8 +9,8 @@
12
9
  * @param {String} [options.schema.itemType] The editor type for each item in the list. Default: 'Text'
13
10
  * @param {String} [options.schema.confirmDelete] Text to display in a delete confirmation dialog. If falsey, will not ask for confirmation.
14
11
  */
15
- editors.List = editors.Base.extend({
16
-
12
+ Form.editors.List = Form.editors.Base.extend({
13
+
17
14
  events: {
18
15
  'click [data-action="add"]': function(event) {
19
16
  event.preventDefault();
@@ -22,16 +19,16 @@
22
19
  },
23
20
 
24
21
  initialize: function(options) {
22
+ options = options || {};
23
+
24
+ var editors = Form.editors;
25
+
25
26
  editors.Base.prototype.initialize.call(this, options);
26
27
 
27
28
  var schema = this.schema;
28
29
  if (!schema) throw "Missing required option 'schema'";
29
30
 
30
- //List schema defaults
31
- this.schema = _.extend({
32
- listTemplate: 'list',
33
- listItemTemplate: 'listItem'
34
- }, schema);
31
+ this.template = options.template || this.constructor.template;
35
32
 
36
33
  //Determine the editor to use
37
34
  this.Editor = (function() {
@@ -55,12 +52,10 @@
55
52
  value = this.value || [];
56
53
 
57
54
  //Create main element
58
- var $el = Form.helpers.parseHTML(Form.templates[this.schema.listTemplate]({
59
- items: '<b class="bbf-tmp"></b>'
60
- }));
55
+ var $el = $($.trim(this.template()));
61
56
 
62
57
  //Store a reference to the list (item container)
63
- this.$list = $el.find('.bbf-tmp').parent().empty();
58
+ this.$list = $el.is('[data-items]') ? $el : $el.find('[data-items]');
64
59
 
65
60
  //Add existing items
66
61
  if (value.length) {
@@ -89,11 +84,13 @@
89
84
  * @param {Boolean} [userInitiated] If the item was added by the user clicking 'add'
90
85
  */
91
86
  addItem: function(value, userInitiated) {
92
- var self = this;
87
+ var self = this,
88
+ editors = Form.editors;
93
89
 
94
90
  //Create the item
95
91
  var item = new editors.List.Item({
96
92
  list: this,
93
+ form: this.form,
97
94
  schema: this.schema,
98
95
  value: value,
99
96
  Editor: this.Editor,
@@ -218,7 +215,7 @@
218
215
  remove: function() {
219
216
  _.invoke(this.items, 'remove');
220
217
 
221
- editors.Base.prototype.remove.call(this);
218
+ Form.editors.Base.prototype.remove.call(this);
222
219
  },
223
220
 
224
221
  /**
@@ -247,6 +244,16 @@
247
244
 
248
245
  return fieldError;
249
246
  }
247
+ }, {
248
+
249
+ //STATICS
250
+ template: _.template('\
251
+ <div>\
252
+ <div data-items></div>\
253
+ <button type="button" data-action="add">Add</button>\
254
+ </div>\
255
+ ', null, Form.templateSettings)
256
+
250
257
  });
251
258
 
252
259
 
@@ -259,7 +266,8 @@
259
266
  * @param {Mixed} options.value Value
260
267
  * @param {Object} options.schema Field schema
261
268
  */
262
- editors.List.Item = Backbone.View.extend({
269
+ Form.editors.List.Item = Form.editors.Base.extend({
270
+
263
271
  events: {
264
272
  'click [data-action="remove"]': function(event) {
265
273
  event.preventDefault();
@@ -277,8 +285,11 @@
277
285
  this.list = options.list;
278
286
  this.schema = options.schema || this.list.schema;
279
287
  this.value = options.value;
280
- this.Editor = options.Editor || editors.Text;
288
+ this.Editor = options.Editor || Form.editors.Text;
281
289
  this.key = options.key;
290
+ this.template = options.template || this.schema.itemTemplate || this.constructor.template;
291
+ this.errorClassName = options.errorClassName || this.constructor.errorClassName;
292
+ this.form = options.form;
282
293
  },
283
294
 
284
295
  render: function() {
@@ -288,15 +299,14 @@
288
299
  schema: this.schema,
289
300
  value: this.value,
290
301
  list: this.list,
291
- item: this
302
+ item: this,
303
+ form: this.form
292
304
  }).render();
293
305
 
294
306
  //Create main element
295
- var $el = Form.helpers.parseHTML(Form.templates[this.schema.listItemTemplate]({
296
- editor: '<b class="bbf-tmp"></b>'
297
- }));
307
+ var $el = $($.trim(this.template()));
298
308
 
299
- $el.find('.bbf-tmp').replaceWith(this.editor.el);
309
+ $el.find('[data-editor]').append(this.editor.el);
300
310
 
301
311
  //Replace the entire element so there isn't a wrapper tag
302
312
  this.setElement($el);
@@ -330,7 +340,7 @@
330
340
  var value = this.getValue(),
331
341
  formValues = this.list.form ? this.list.form.getValue() : {},
332
342
  validators = this.schema.validators,
333
- getValidator = Form.helpers.getValidator;
343
+ getValidator = this.getValidator;
334
344
 
335
345
  if (!validators) return null;
336
346
 
@@ -357,7 +367,7 @@
357
367
  * Show a validation error
358
368
  */
359
369
  setError: function(err) {
360
- this.$el.addClass(Form.classNames.error);
370
+ this.$el.addClass(this.errorClassName);
361
371
  this.$el.attr('title', err.message);
362
372
  },
363
373
 
@@ -365,9 +375,21 @@
365
375
  * Hide validation errors
366
376
  */
367
377
  clearError: function() {
368
- this.$el.removeClass(Form.classNames.error);
378
+ this.$el.removeClass(this.errorClassName);
369
379
  this.$el.attr('title', null);
370
380
  }
381
+ }, {
382
+
383
+ //STATICS
384
+ template: _.template('\
385
+ <div>\
386
+ <span data-editor></span>\
387
+ <button type="button" data-action="remove">&times;</button>\
388
+ </div>\
389
+ ', null, Form.templateSettings),
390
+
391
+ errorClassName: 'error'
392
+
371
393
  });
372
394
 
373
395
 
@@ -375,23 +397,33 @@
375
397
  * Base modal object editor for use with the List editor; used by Object
376
398
  * and NestedModal list types
377
399
  */
378
- editors.List.Modal = editors.Base.extend({
400
+ Form.editors.List.Modal = Form.editors.Base.extend({
401
+
379
402
  events: {
380
403
  'click': 'openEditor'
381
404
  },
382
405
 
383
406
  /**
384
407
  * @param {Object} options
408
+ * @param {Form} options.form The main form
385
409
  * @param {Function} [options.schema.itemToString] Function to transform the value for display in the list.
386
410
  * @param {String} [options.schema.itemType] Editor type e.g. 'Text', 'Object'.
387
411
  * @param {Object} [options.schema.subSchema] Schema for nested form,. Required when itemType is 'Object'
388
412
  * @param {Function} [options.schema.model] Model constructor function. Required when itemType is 'NestedModel'
389
413
  */
390
414
  initialize: function(options) {
391
- editors.Base.prototype.initialize.call(this, options);
415
+ options = options || {};
416
+
417
+ Form.editors.Base.prototype.initialize.call(this, options);
392
418
 
393
419
  //Dependencies
394
- if (!editors.List.Modal.ModalAdapter) throw 'A ModalAdapter is required';
420
+ if (!Form.editors.List.Modal.ModalAdapter) throw 'A ModalAdapter is required';
421
+
422
+ this.form = options.form;
423
+ if (!options.form) throw 'Missing required option: "form"';
424
+
425
+ //Template
426
+ this.template = options.template || this.constructor.template;
395
427
  },
396
428
 
397
429
  /**
@@ -423,11 +455,9 @@
423
455
  * Renders the list item representation
424
456
  */
425
457
  renderSummary: function() {
426
- var template = Form.templates['list.Modal'];
427
-
428
- this.$el.html(template({
458
+ this.$el.html($.trim(this.template({
429
459
  summary: this.getStringValue()
430
- }));
460
+ })));
431
461
  },
432
462
 
433
463
  /**
@@ -438,12 +468,18 @@
438
468
  * @return {String}
439
469
  */
440
470
  itemToString: function(value) {
471
+ var createTitle = function(key) {
472
+ var context = { key: key };
473
+
474
+ return Form.Field.prototype.createTitle.call(context);
475
+ };
476
+
441
477
  value = value || {};
442
478
 
443
479
  //Pretty print the object keys and values
444
480
  var parts = [];
445
481
  _.each(this.nestedSchema, function(schema, key) {
446
- var desc = schema.title ? schema.title : Form.helpers.keyToTitle(key),
482
+ var desc = schema.title ? schema.title : createTitle(key),
447
483
  val = value[key];
448
484
 
449
485
  if (_.isUndefined(val) || _.isNull(val)) val = '';
@@ -471,14 +507,15 @@
471
507
  },
472
508
 
473
509
  openEditor: function() {
474
- var self = this;
510
+ var self = this,
511
+ ModalForm = this.form.constructor;
475
512
 
476
- var form = this.modalForm = new Form({
513
+ var form = this.modalForm = new ModalForm({
477
514
  schema: this.nestedSchema,
478
515
  data: this.value
479
516
  });
480
517
 
481
- var modal = this.modal = new editors.List.Modal.ModalAdapter({
518
+ var modal = this.modal = new Form.editors.List.Modal.ModalAdapter({
482
519
  content: form,
483
520
  animate: true
484
521
  });
@@ -553,6 +590,9 @@
553
590
  }
554
591
  }, {
555
592
  //STATICS
593
+ template: _.template('\
594
+ <div><%= summary %></div>\
595
+ ', null, Form.templateSettings),
556
596
 
557
597
  //The modal adapter that creates and manages the modal dialog.
558
598
  //Defaults to BootstrapModal (http://github.com/powmedia/backbone.bootstrap-modal)
@@ -563,10 +603,10 @@
563
603
  isAsync: true
564
604
  });
565
605
 
566
-
567
- editors.List.Object = editors.List.Modal.extend({
606
+
607
+ Form.editors.List.Object = Form.editors.List.Modal.extend({
568
608
  initialize: function () {
569
- editors.List.Modal.prototype.initialize.apply(this, arguments);
609
+ Form.editors.List.Modal.prototype.initialize.apply(this, arguments);
570
610
 
571
611
  var schema = this.schema;
572
612
 
@@ -577,9 +617,9 @@
577
617
  });
578
618
 
579
619
 
580
- editors.List.NestedModel = editors.List.Modal.extend({
620
+ Form.editors.List.NestedModel = Form.editors.List.Modal.extend({
581
621
  initialize: function() {
582
- editors.List.Modal.prototype.initialize.apply(this, arguments);
622
+ Form.editors.List.Modal.prototype.initialize.apply(this, arguments);
583
623
 
584
624
  var schema = this.schema;
585
625
 
@@ -604,7 +644,7 @@
604
644
 
605
645
  //Otherwise use the model
606
646
  return new (schema.model)(value).toString();
607
- },
647
+ }
608
648
  });
609
649
 
610
- })();
650
+ })(Backbone.Form);
@@ -1 +1 @@
1
- (function(){var e=Backbone.Form,t=e.editors;t.List=t.Base.extend({events:{'click [data-action="add"]':function(e){e.preventDefault(),this.addItem(null,!0)}},initialize:function(e){t.Base.prototype.initialize.call(this,e);var n=this.schema;if(!n)throw"Missing required option 'schema'";this.schema=_.extend({listTemplate:"list",listItemTemplate:"listItem"},n),this.Editor=function(){var e=n.itemType;return e?t.List[e]?t.List[e]:t[e]:t.Text}(),this.items=[]},render:function(){var t=this,n=this.value||[],r=e.helpers.parseHTML(e.templates[this.schema.listTemplate]({items:'<b class="bbf-tmp"></b>'}));return this.$list=r.find(".bbf-tmp").parent().empty(),n.length?_.each(n,function(e){t.addItem(e)}):this.Editor.isAsync||this.addItem(),this.setElement(r),this.$el.attr("id",this.id),this.$el.attr("name",this.key),this.hasFocus&&this.trigger("blur",this),this},addItem:function(e,n){var r=this,i=(new t.List.Item({list:this,schema:this.schema,value:e,Editor:this.Editor,key:this.key})).render(),s=function(){r.items.push(i),r.$list.append(i.el),i.editor.on("all",function(e){if(e==="change")return;var n=_.toArray(arguments);n[0]="item:"+e,n.splice(1,0,r),t.List.prototype.trigger.apply(this,n)},r),i.editor.on("change",function(){i.addEventTriggered||(i.addEventTriggered=!0,this.trigger("add",this,i.editor)),this.trigger("item:change",this,i.editor),this.trigger("change",this)},r),i.editor.on("focus",function(){if(this.hasFocus)return;this.trigger("focus",this)},r),i.editor.on("blur",function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(_.find(e.items,function(e){return e.editor.hasFocus}))return;e.trigger("blur",e)},0)},r);if(n||e)i.addEventTriggered=!0;n&&(r.trigger("add",r,i.editor),r.trigger("change",r))};return this.Editor.isAsync?i.editor.on("readyToAdd",s,this):(s(),i.editor.focus()),i},removeItem:function(e){var t=this.schema.confirmDelete;if(t&&!confirm(t))return;var n=_.indexOf(this.items,e);this.items[n].remove(),this.items.splice(n,1),e.addEventTriggered&&(this.trigger("remove",this,e.editor),this.trigger("change",this)),!this.items.length&&!this.Editor.isAsync&&this.addItem()},getValue:function(){var e=_.map(this.items,function(e){return e.getValue()});return _.without(e,undefined,"")},setValue:function(e){this.value=e,this.render()},focus:function(){if(this.hasFocus)return;this.items[0]&&this.items[0].editor.focus()},blur:function(){if(!this.hasFocus)return;var e=_.find(this.items,function(e){return e.editor.hasFocus});e&&e.editor.blur()},remove:function(){_.invoke(this.items,"remove"),t.Base.prototype.remove.call(this)},validate:function(){if(!this.validators)return null;var e=_.map(this.items,function(e){return e.validate()}),t=_.compact(e).length?!0:!1;if(!t)return null;var n={type:"list",message:"Some of the items in the list failed validation",errors:e};return n}}),t.List.Item=Backbone.View.extend({events:{'click [data-action="remove"]':function(e){e.preventDefault(),this.list.removeItem(this)},"keydown input[type=text]":function(e){if(e.keyCode!==13)return;e.preventDefault(),this.list.addItem(),this.list.$list.find("> li:last input").focus()}},initialize:function(e){this.list=e.list,this.schema=e.schema||this.list.schema,this.value=e.value,this.Editor=e.Editor||t.Text,this.key=e.key},render:function(){this.editor=(new this.Editor({key:this.key,schema:this.schema,value:this.value,list:this.list,item:this})).render();var t=e.helpers.parseHTML(e.templates[this.schema.listItemTemplate]({editor:'<b class="bbf-tmp"></b>'}));return t.find(".bbf-tmp").replaceWith(this.editor.el),this.setElement(t),this},getValue:function(){return this.editor.getValue()},setValue:function(e){this.editor.setValue(e)},focus:function(){this.editor.focus()},blur:function(){this.editor.blur()},remove:function(){this.editor.remove(),Backbone.View.prototype.remove.call(this)},validate:function(){var t=this.getValue(),n=this.list.form?this.list.form.getValue():{},r=this.schema.validators,i=e.helpers.getValidator;if(!r)return null;var s=null;return _.every(r,function(e){return s=i(e)(t,n),s?!1:!0}),s?this.setError(s):this.clearError(),s?s:null},setError:function(t){this.$el.addClass(e.classNames.error),this.$el.attr("title",t.message)},clearError:function(){this.$el.removeClass(e.classNames.error),this.$el.attr("title",null)}}),t.List.Modal=t.Base.extend({events:{click:"openEditor"},initialize:function(e){t.Base.prototype.initialize.call(this,e);if(!t.List.Modal.ModalAdapter)throw"A ModalAdapter is required"},render:function(){var e=this;return _.isEmpty(this.value)?this.openEditor():(this.renderSummary(),setTimeout(function(){e.trigger("readyToAdd")},0)),this.hasFocus&&this.trigger("blur",this),this},renderSummary:function(){var t=e.templates["list.Modal"];this.$el.html(t({summary:this.getStringValue()}))},itemToString:function(t){t=t||{};var n=[];return _.each(this.nestedSchema,function(r,i){var s=r.title?r.title:e.helpers.keyToTitle(i),o=t[i];if(_.isUndefined(o)||_.isNull(o))o="";n.push(s+": "+o)}),n.join("<br />")},getStringValue:function(){var e=this.schema,t=this.getValue();return _.isEmpty(t)?"[Empty]":e.itemToString?e.itemToString(t):this.itemToString(t)},openEditor:function(){var n=this,r=this.modalForm=new e({schema:this.nestedSchema,data:this.value}),i=this.modal=new t.List.Modal.ModalAdapter({content:r,animate:!0});i.open(),this.trigger("open",this),this.trigger("focus",this),i.on("cancel",this.onModalClosed,this),i.on("ok",_.bind(this.onModalSubmitted,this))},onModalSubmitted:function(){var e=this.modal,t=this.modalForm,n=!this.value,r=t.validate();if(r)return e.preventClose();this.value=t.getValue(),this.renderSummary(),n&&this.trigger("readyToAdd"),this.trigger("change",this),this.onModalClosed()},onModalClosed:function(){this.modal=null,this.modalForm=null,this.trigger("close",this),this.trigger("blur",this)},getValue:function(){return this.value},setValue:function(e){this.value=e},focus:function(){if(this.hasFocus)return;this.openEditor()},blur:function(){if(!this.hasFocus)return;this.modal&&this.modal.trigger("cancel")}},{ModalAdapter:Backbone.BootstrapModal,isAsync:!0}),t.List.Object=t.List.Modal.extend({initialize:function(){t.List.Modal.prototype.initialize.apply(this,arguments);var e=this.schema;if(!e.subSchema)throw'Missing required option "schema.subSchema"';this.nestedSchema=e.subSchema}}),t.List.NestedModel=t.List.Modal.extend({initialize:function(){t.List.Modal.prototype.initialize.apply(this,arguments);var e=this.schema;if(!e.model)throw'Missing required option "schema.model"';var n=e.model.prototype.schema;this.nestedSchema=_.isFunction(n)?n():n},getStringValue:function(){var e=this.schema,t=this.getValue();return _.isEmpty(t)?null:e.itemToString?e.itemToString(t):(new e.model(t)).toString()}})})()
1
+ (function(e){e.editors.List=e.editors.Base.extend({events:{'click [data-action="add"]':function(e){e.preventDefault(),this.addItem(null,!0)}},initialize:function(t){t=t||{};var n=e.editors;n.Base.prototype.initialize.call(this,t);var r=this.schema;if(!r)throw"Missing required option 'schema'";this.template=t.template||this.constructor.template,this.Editor=function(){var e=r.itemType;return e?n.List[e]?n.List[e]:n[e]:n.Text}(),this.items=[]},render:function(){var e=this,t=this.value||[],n=$($.trim(this.template()));return this.$list=n.is("[data-items]")?n:n.find("[data-items]"),t.length?_.each(t,function(t){e.addItem(t)}):this.Editor.isAsync||this.addItem(),this.setElement(n),this.$el.attr("id",this.id),this.$el.attr("name",this.key),this.hasFocus&&this.trigger("blur",this),this},addItem:function(t,n){var r=this,i=e.editors,s=(new i.List.Item({list:this,form:this.form,schema:this.schema,value:t,Editor:this.Editor,key:this.key})).render(),o=function(){r.items.push(s),r.$list.append(s.el),s.editor.on("all",function(e){if(e==="change")return;var t=_.toArray(arguments);t[0]="item:"+e,t.splice(1,0,r),i.List.prototype.trigger.apply(this,t)},r),s.editor.on("change",function(){s.addEventTriggered||(s.addEventTriggered=!0,this.trigger("add",this,s.editor)),this.trigger("item:change",this,s.editor),this.trigger("change",this)},r),s.editor.on("focus",function(){if(this.hasFocus)return;this.trigger("focus",this)},r),s.editor.on("blur",function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(_.find(e.items,function(e){return e.editor.hasFocus}))return;e.trigger("blur",e)},0)},r);if(n||t)s.addEventTriggered=!0;n&&(r.trigger("add",r,s.editor),r.trigger("change",r))};return this.Editor.isAsync?s.editor.on("readyToAdd",o,this):(o(),s.editor.focus()),s},removeItem:function(e){var t=this.schema.confirmDelete;if(t&&!confirm(t))return;var n=_.indexOf(this.items,e);this.items[n].remove(),this.items.splice(n,1),e.addEventTriggered&&(this.trigger("remove",this,e.editor),this.trigger("change",this)),!this.items.length&&!this.Editor.isAsync&&this.addItem()},getValue:function(){var e=_.map(this.items,function(e){return e.getValue()});return _.without(e,undefined,"")},setValue:function(e){this.value=e,this.render()},focus:function(){if(this.hasFocus)return;this.items[0]&&this.items[0].editor.focus()},blur:function(){if(!this.hasFocus)return;var e=_.find(this.items,function(e){return e.editor.hasFocus});e&&e.editor.blur()},remove:function(){_.invoke(this.items,"remove"),e.editors.Base.prototype.remove.call(this)},validate:function(){if(!this.validators)return null;var e=_.map(this.items,function(e){return e.validate()}),t=_.compact(e).length?!0:!1;if(!t)return null;var n={type:"list",message:"Some of the items in the list failed validation",errors:e};return n}},{template:_.template(' <div> <div data-items></div> <button type="button" data-action="add">Add</button> </div> ',null,e.templateSettings)}),e.editors.List.Item=e.editors.Base.extend({events:{'click [data-action="remove"]':function(e){e.preventDefault(),this.list.removeItem(this)},"keydown input[type=text]":function(e){if(e.keyCode!==13)return;e.preventDefault(),this.list.addItem(),this.list.$list.find("> li:last input").focus()}},initialize:function(t){this.list=t.list,this.schema=t.schema||this.list.schema,this.value=t.value,this.Editor=t.Editor||e.editors.Text,this.key=t.key,this.template=t.template||this.schema.itemTemplate||this.constructor.template,this.errorClassName=t.errorClassName||this.constructor.errorClassName,this.form=t.form},render:function(){this.editor=(new this.Editor({key:this.key,schema:this.schema,value:this.value,list:this.list,item:this,form:this.form})).render();var e=$($.trim(this.template()));return e.find("[data-editor]").append(this.editor.el),this.setElement(e),this},getValue:function(){return this.editor.getValue()},setValue:function(e){this.editor.setValue(e)},focus:function(){this.editor.focus()},blur:function(){this.editor.blur()},remove:function(){this.editor.remove(),Backbone.View.prototype.remove.call(this)},validate:function(){var e=this.getValue(),t=this.list.form?this.list.form.getValue():{},n=this.schema.validators,r=this.getValidator;if(!n)return null;var i=null;return _.every(n,function(n){return i=r(n)(e,t),i?!1:!0}),i?this.setError(i):this.clearError(),i?i:null},setError:function(e){this.$el.addClass(this.errorClassName),this.$el.attr("title",e.message)},clearError:function(){this.$el.removeClass(this.errorClassName),this.$el.attr("title",null)}},{template:_.template(' <div> <span data-editor></span> <button type="button" data-action="remove">&times;</button> </div> ',null,e.templateSettings),errorClassName:"error"}),e.editors.List.Modal=e.editors.Base.extend({events:{click:"openEditor"},initialize:function(t){t=t||{},e.editors.Base.prototype.initialize.call(this,t);if(!e.editors.List.Modal.ModalAdapter)throw"A ModalAdapter is required";this.form=t.form;if(!t.form)throw'Missing required option: "form"';this.template=t.template||this.constructor.template},render:function(){var e=this;return _.isEmpty(this.value)?this.openEditor():(this.renderSummary(),setTimeout(function(){e.trigger("readyToAdd")},0)),this.hasFocus&&this.trigger("blur",this),this},renderSummary:function(){this.$el.html($.trim(this.template({summary:this.getStringValue()})))},itemToString:function(t){var n=function(t){var n={key:t};return e.Field.prototype.createTitle.call(n)};t=t||{};var r=[];return _.each(this.nestedSchema,function(e,i){var s=e.title?e.title:n(i),o=t[i];if(_.isUndefined(o)||_.isNull(o))o="";r.push(s+": "+o)}),r.join("<br />")},getStringValue:function(){var e=this.schema,t=this.getValue();return _.isEmpty(t)?"[Empty]":e.itemToString?e.itemToString(t):this.itemToString(t)},openEditor:function(){var t=this,n=this.form.constructor,r=this.modalForm=new n({schema:this.nestedSchema,data:this.value}),i=this.modal=new e.editors.List.Modal.ModalAdapter({content:r,animate:!0});i.open(),this.trigger("open",this),this.trigger("focus",this),i.on("cancel",this.onModalClosed,this),i.on("ok",_.bind(this.onModalSubmitted,this))},onModalSubmitted:function(){var e=this.modal,t=this.modalForm,n=!this.value,r=t.validate();if(r)return e.preventClose();this.value=t.getValue(),this.renderSummary(),n&&this.trigger("readyToAdd"),this.trigger("change",this),this.onModalClosed()},onModalClosed:function(){this.modal=null,this.modalForm=null,this.trigger("close",this),this.trigger("blur",this)},getValue:function(){return this.value},setValue:function(e){this.value=e},focus:function(){if(this.hasFocus)return;this.openEditor()},blur:function(){if(!this.hasFocus)return;this.modal&&this.modal.trigger("cancel")}},{template:_.template(" <div><%= summary %></div> ",null,e.templateSettings),ModalAdapter:Backbone.BootstrapModal,isAsync:!0}),e.editors.List.Object=e.editors.List.Modal.extend({initialize:function(){e.editors.List.Modal.prototype.initialize.apply(this,arguments);var t=this.schema;if(!t.subSchema)throw'Missing required option "schema.subSchema"';this.nestedSchema=t.subSchema}}),e.editors.List.NestedModel=e.editors.List.Modal.extend({initialize:function(){e.editors.List.Modal.prototype.initialize.apply(this,arguments);var t=this.schema;if(!t.model)throw'Missing required option "schema.model"';var n=t.model.prototype.schema;this.nestedSchema=_.isFunction(n)?n():n},getStringValue:function(){var e=this.schema,t=this.getValue();return _.isEmpty(t)?null:e.itemToString?e.itemToString(t):(new e.model(t)).toString()}})})(Backbone.Form)
@@ -1,95 +1,70 @@
1
- /**
2
- * Include this file _after_ the main backbone-forms file to override the default templates.
3
- * You only need to include templates you want to override.
1
+ /**
2
+ * Include this template file after backbone-forms.amd.js to override the default templates
4
3
  *
5
- * Requirements when customising templates:
6
- * - Each template must have one 'parent' element tag.
7
- * - "data-type" attributes are required.
8
- * - The main placeholder tags such as the following are required: fieldsets, fields
4
+ * 'data-*' attributes control where elements are placed
9
5
  */
10
- ;(function() {
11
- var Form = Backbone.Form;
6
+ ;(function(Form) {
12
7
 
13
-
14
- //TWITTER BOOTSTRAP TEMPLATES
15
- //Requires Bootstrap 2.x
16
- Form.setTemplates({
8
+
9
+ /**
10
+ * Bootstrap templates for Backbone Forms
11
+ */
12
+ Form.template = _.template('\
13
+ <form class="form-horizontal" data-fieldsets></form>\
14
+ ');
17
15
 
18
- //HTML
19
- form: '\
20
- <form class="form-horizontal">{{fieldsets}}</form>\
21
- ',
22
16
 
23
- fieldset: '\
24
- <fieldset>\
25
- <legend>{{legend}}</legend>\
26
- {{fields}}\
27
- </fieldset>\
28
- ',
17
+ Form.Fieldset.template = _.template('\
18
+ <fieldset data-fields>\
19
+ <% if (legend) { %>\
20
+ <legend><%= legend %></legend>\
21
+ <% } %>\
22
+ </fieldset>\
23
+ ');
29
24
 
30
- field: '\
31
- <div class="control-group field-{{key}}">\
32
- <label class="control-label" for="{{id}}">{{title}}</label>\
33
- <div class="controls">\
34
- {{editor}}\
35
- <div class="help-inline">{{error}}</div>\
36
- <div class="help-block">{{help}}</div>\
37
- </div>\
38
- </div>\
39
- ',
40
25
 
41
- nestedField: '\
42
- <div class="field-{{key}}">\
43
- <div title="{{title}}" class="input-xlarge">{{editor}}\
44
- <div class="help-inline">{{error}}</div>\
45
- </div>\
46
- <div class="help-block">{{help}}</div>\
26
+ Form.Field.template = _.template('\
27
+ <div class="control-group field-<%= key %>">\
28
+ <label class="control-label" for="<%= editorId %>"><%= title %></label>\
29
+ <div class="controls">\
30
+ <span data-editor></span>\
31
+ <div class="help-inline" data-error></div>\
32
+ <div class="help-block"><%= help %></div>\
47
33
  </div>\
48
- ',
34
+ </div>\
35
+ ');
49
36
 
50
- list: '\
51
- <div class="bbf-list">\
52
- <ul class="unstyled clearfix">{{items}}</ul>\
53
- <button class="btn bbf-add" data-action="add">Add</button>\
37
+
38
+ Form.NestedField.template = _.template('\
39
+ <div class="field-<%= key %>">\
40
+ <div title="<%= title %>" class="input-xlarge">\
41
+ <span data-editor></span>\
42
+ <div class="help-inline" data-error></div>\
54
43
  </div>\
55
- ',
44
+ <div class="help-block"><%= help %></div>\
45
+ </div>\
46
+ ');
56
47
 
57
- listItem: '\
58
- <li class="clearfix">\
59
- <div class="pull-left">{{editor}}</div>\
60
- <button type="button" class="btn bbf-del" data-action="remove">&times;</button>\
61
- </li>\
62
- ',
63
48
 
64
- date: '\
65
- <div class="bbf-date">\
66
- <select data-type="date" class="bbf-date">{{dates}}</select>\
67
- <select data-type="month" class="bbf-month">{{months}}</select>\
68
- <select data-type="year" class="bbf-year">{{years}}</select>\
69
- </div>\
70
- ',
49
+ Form.editors.List.template = _.template('\
50
+ <div class="bbf-list">\
51
+ <ul class="unstyled clearfix" data-items></ul>\
52
+ <button class="btn bbf-add" data-action="add">Add</button>\
53
+ </div>\
54
+ ');
71
55
 
72
- dateTime: '\
73
- <div class="bbf-datetime">\
74
- <p>{{date}}</p>\
75
- <p>\
76
- <select data-type="hour" style="width: 4em">{{hours}}</select>\
77
- :\
78
- <select data-type="min" style="width: 4em">{{mins}}</select>\
79
- </p>\
80
- </div>\
81
- ',
82
56
 
83
- 'list.Modal': '\
84
- <div class="bbf-list-modal">\
85
- {{summary}}\
86
- </div>\
87
- '
88
- }, {
57
+ Form.editors.List.Item.template = _.template('\
58
+ <li class="clearfix">\
59
+ <div class="pull-left" data-editor></div>\
60
+ <button type="button" class="btn bbf-del" data-action="remove">&times;</button>\
61
+ </li>\
62
+ ');
89
63
 
90
- //CLASSNAMES
91
- error: 'error' //Set on the field tag when validation fails
92
- });
64
+
65
+ Form.editors.List.Object.template = Form.editors.List.NestedModel.template = _.template('\
66
+ <div class="bbf-list-modal"><%= summary %></div>\
67
+ ');
93
68
 
94
69
 
95
- })();
70
+ })(Backbone.Form);