rails-backbone-forms 0.10.1 → 0.11.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.
- data/lib/rails/backbone/forms/version.rb +1 -1
- data/vendor/assets/javascripts/backbone-forms/adapters/backbone.bootstrap-modal.js +76 -17
- data/vendor/assets/javascripts/backbone-forms/adapters/backbone.bootstrap-modal.min.js +1 -0
- data/vendor/assets/javascripts/backbone-forms/backbone-forms.js +331 -272
- data/vendor/assets/javascripts/backbone-forms/editors/list.js +84 -49
- data/vendor/assets/javascripts/backbone-forms/editors/list.min.js +1 -0
- data/vendor/assets/javascripts/backbone-forms/templates/bootstrap.js +6 -3
- data/vendor/assets/javascripts/backbone-forms/templates/default.js +2 -0
- data/vendor/assets/stylesheets/backbone-forms/templates/default.css +6 -0
- metadata +5 -6
- data/vendor/assets/javascripts/backbone-forms/editors/jquery-ui.js +0 -500
- data/vendor/assets/stylesheets/backbone-forms-bootstrap.css +0 -3
- data/vendor/assets/stylesheets/backbone-forms/editors/jquery-ui.css +0 -65
@@ -30,7 +30,7 @@
|
|
30
30
|
<h3>{{title}}</h3>\
|
31
31
|
</div>\
|
32
32
|
<% } %>\
|
33
|
-
<div class="modal-body"
|
33
|
+
<div class="modal-body">{{content}}</div>\
|
34
34
|
<div class="modal-footer">\
|
35
35
|
<% if (allowCancel) { %>\
|
36
36
|
<% if (cancelText) { %>\
|
@@ -54,19 +54,32 @@
|
|
54
54
|
event.preventDefault();
|
55
55
|
|
56
56
|
this.trigger('cancel');
|
57
|
-
|
57
|
+
|
58
|
+
if (this.options.content && this.options.content.trigger) {
|
59
|
+
this.options.content.trigger('cancel', this);
|
60
|
+
}
|
58
61
|
},
|
59
62
|
'click .cancel': function(event) {
|
60
63
|
event.preventDefault();
|
61
64
|
|
62
65
|
this.trigger('cancel');
|
63
|
-
|
66
|
+
|
67
|
+
if (this.options.content && this.options.content.trigger) {
|
68
|
+
this.options.content.trigger('cancel', this);
|
69
|
+
}
|
64
70
|
},
|
65
71
|
'click .ok': function(event) {
|
66
72
|
event.preventDefault();
|
67
73
|
|
68
74
|
this.trigger('ok');
|
69
|
-
|
75
|
+
|
76
|
+
if (this.options.content && this.options.content.trigger) {
|
77
|
+
this.options.content.trigger('ok', this);
|
78
|
+
}
|
79
|
+
|
80
|
+
if (this.options.okCloses) {
|
81
|
+
this.close();
|
82
|
+
}
|
70
83
|
}
|
71
84
|
},
|
72
85
|
|
@@ -89,6 +102,8 @@
|
|
89
102
|
this.options = _.extend({
|
90
103
|
title: null,
|
91
104
|
okText: 'OK',
|
105
|
+
focusOk: true,
|
106
|
+
okCloses: true,
|
92
107
|
cancelText: 'Cancel',
|
93
108
|
allowCancel: true,
|
94
109
|
escape: true,
|
@@ -110,11 +125,12 @@
|
|
110
125
|
//Create the modal container
|
111
126
|
$el.html(options.template(options));
|
112
127
|
|
113
|
-
var $content = this.$content = $el.find('.modal-body
|
128
|
+
var $content = this.$content = $el.find('.modal-body')
|
114
129
|
|
115
130
|
//Insert the main content if it's a view
|
116
131
|
if (content.$el) {
|
117
|
-
|
132
|
+
content.render();
|
133
|
+
$el.find('.modal-body').html(content.$el);
|
118
134
|
}
|
119
135
|
|
120
136
|
if (options.animate) $el.addClass('fade');
|
@@ -126,22 +142,30 @@
|
|
126
142
|
|
127
143
|
/**
|
128
144
|
* Renders and shows the modal
|
145
|
+
*
|
146
|
+
* @param {Function} [cb] Optional callback that runs only when OK is pressed.
|
129
147
|
*/
|
130
|
-
open: function() {
|
148
|
+
open: function(cb) {
|
131
149
|
if (!this.isRendered) this.render();
|
132
150
|
|
133
151
|
var self = this,
|
134
152
|
$el = this.$el;
|
135
153
|
|
136
154
|
//Create it
|
137
|
-
$el.modal({
|
155
|
+
$el.modal(_.extend({
|
138
156
|
keyboard: this.options.allowCancel,
|
139
157
|
backdrop: this.options.allowCancel ? true : 'static'
|
140
|
-
});
|
158
|
+
}, this.options.modalOptions));
|
141
159
|
|
142
160
|
//Focus OK button
|
143
161
|
$el.one('shown', function() {
|
144
|
-
|
162
|
+
if (self.options.focusOk) {
|
163
|
+
$el.find('.btn.ok').focus();
|
164
|
+
}
|
165
|
+
|
166
|
+
if (self.options.content && self.options.content.trigger) {
|
167
|
+
self.options.content.trigger('shown', self);
|
168
|
+
}
|
145
169
|
|
146
170
|
self.trigger('shown');
|
147
171
|
});
|
@@ -149,13 +173,40 @@
|
|
149
173
|
//Adjust the modal and backdrop z-index; for dealing with multiple modals
|
150
174
|
var numModals = Modal.count,
|
151
175
|
$backdrop = $('.modal-backdrop:eq('+numModals+')'),
|
152
|
-
backdropIndex = $backdrop.css('z-index'),
|
153
|
-
elIndex = $backdrop.css('z-index');
|
176
|
+
backdropIndex = parseInt($backdrop.css('z-index'),10),
|
177
|
+
elIndex = parseInt($backdrop.css('z-index'), 10);
|
154
178
|
|
155
179
|
$backdrop.css('z-index', backdropIndex + numModals);
|
156
180
|
this.$el.css('z-index', elIndex + numModals);
|
157
181
|
|
182
|
+
if (this.options.allowCancel) {
|
183
|
+
$backdrop.one('click', function() {
|
184
|
+
if (self.options.content && self.options.content.trigger) {
|
185
|
+
self.options.content.trigger('cancel', self);
|
186
|
+
}
|
187
|
+
|
188
|
+
self.trigger('cancel');
|
189
|
+
});
|
190
|
+
|
191
|
+
$(document).one('keyup.dismiss.modal', function (e) {
|
192
|
+
e.which == 27 && self.trigger('cancel');
|
193
|
+
|
194
|
+
if (self.options.content && self.options.content.trigger) {
|
195
|
+
e.which == 27 && self.options.content.trigger('shown', self);
|
196
|
+
}
|
197
|
+
});
|
198
|
+
}
|
199
|
+
|
200
|
+
this.on('cancel', function() {
|
201
|
+
self.close();
|
202
|
+
});
|
203
|
+
|
158
204
|
Modal.count++;
|
205
|
+
|
206
|
+
//Run callback on OK if provided
|
207
|
+
if (cb) {
|
208
|
+
self.on('ok', cb);
|
209
|
+
}
|
159
210
|
|
160
211
|
return this;
|
161
212
|
},
|
@@ -173,14 +224,22 @@
|
|
173
224
|
return;
|
174
225
|
}
|
175
226
|
|
176
|
-
$el.
|
177
|
-
|
178
|
-
|
227
|
+
$el.one('hidden', function onHidden(e) {
|
228
|
+
// Ignore events propagated from interior objects, like bootstrap tooltips
|
229
|
+
if(e.target !== e.currentTarget){
|
230
|
+
return $el.one('hidden', onHidden);
|
231
|
+
}
|
179
232
|
self.remove();
|
180
233
|
|
234
|
+
if (self.options.content && self.options.content.trigger) {
|
235
|
+
self.options.content.trigger('hidden', self);
|
236
|
+
}
|
237
|
+
|
181
238
|
self.trigger('hidden');
|
182
239
|
});
|
183
240
|
|
241
|
+
$el.modal('hide');
|
242
|
+
|
184
243
|
Modal.count--;
|
185
244
|
},
|
186
245
|
|
@@ -201,14 +260,14 @@
|
|
201
260
|
|
202
261
|
//EXPORTS
|
203
262
|
//CommonJS
|
204
|
-
if (typeof require == 'function' && module && exports) {
|
263
|
+
if (typeof require == 'function' && typeof module !== 'undefined' && exports) {
|
205
264
|
module.exports = Modal;
|
206
265
|
}
|
207
266
|
|
208
267
|
//AMD / RequireJS
|
209
268
|
if (typeof define === 'function' && define.amd) {
|
210
269
|
return define(function() {
|
211
|
-
|
270
|
+
Backbone.BootstrapModal = Modal;
|
212
271
|
})
|
213
272
|
}
|
214
273
|
|
@@ -0,0 +1 @@
|
|
1
|
+
(function(e,t,n){var r=t.templateSettings;t.templateSettings={interpolate:/\{\{(.+?)\}\}/g,evaluate:/<%([\s\S]+?)%>/g};var i=t.template(' <% if (title) { %> <div class="modal-header"> <% if (allowCancel) { %> <a class="close">×</a> <% } %> <h3>{{title}}</h3> </div> <% } %> <div class="modal-body">{{content}}</div> <div class="modal-footer"> <% if (allowCancel) { %> <% if (cancelText) { %> <a href="#" class="btn cancel">{{cancelText}}</a> <% } %> <% } %> <a href="#" class="btn ok btn-primary">{{okText}}</a> </div> ');t.templateSettings=r;var s=n.View.extend({className:"modal",events:{"click .close":function(e){e.preventDefault(),this.trigger("cancel"),this.options.content&&this.options.content.trigger&&this.options.content.trigger("cancel",this)},"click .cancel":function(e){e.preventDefault(),this.trigger("cancel"),this.options.content&&this.options.content.trigger&&this.options.content.trigger("cancel",this)},"click .ok":function(e){e.preventDefault(),this.trigger("ok"),this.options.content&&this.options.content.trigger&&this.options.content.trigger("ok",this),this.options.okCloses&&this.close()}},initialize:function(e){this.options=t.extend({title:null,okText:"OK",focusOk:!0,okCloses:!0,cancelText:"Cancel",allowCancel:!0,escape:!0,animate:!1,template:i},e)},render:function(){var e=this.$el,t=this.options,n=t.content;e.html(t.template(t));var r=this.$content=e.find(".modal-body");return n.$el&&(n.render(),e.find(".modal-body").html(n.$el)),t.animate&&e.addClass("fade"),this.isRendered=!0,this},open:function(n){this.isRendered||this.render();var r=this,i=this.$el;i.modal(t.extend({keyboard:this.options.allowCancel,backdrop:this.options.allowCancel?!0:"static"},this.options.modalOptions)),i.one("shown",function(){r.options.focusOk&&i.find(".btn.ok").focus(),r.options.content&&r.options.content.trigger&&r.options.content.trigger("shown",r),r.trigger("shown")});var o=s.count,u=e(".modal-backdrop:eq("+o+")"),a=parseInt(u.css("z-index"),10),f=parseInt(u.css("z-index"),10);return u.css("z-index",a+o),this.$el.css("z-index",f+o),this.options.allowCancel&&(u.one("click",function(){r.options.content&&r.options.content.trigger&&r.options.content.trigger("cancel",r),r.trigger("cancel")}),e(document).one("keyup.dismiss.modal",function(e){e.which==27&&r.trigger("cancel"),r.options.content&&r.options.content.trigger&&e.which==27&&r.options.content.trigger("shown",r)})),this.on("cancel",function(){r.close()}),s.count++,n&&r.on("ok",n),this},close:function(){var e=this,t=this.$el;if(this._preventClose){this._preventClose=!1;return}t.one("hidden",function n(r){if(r.target!==r.currentTarget)return t.one("hidden",n);e.remove(),e.options.content&&e.options.content.trigger&&e.options.content.trigger("hidden",e),e.trigger("hidden")}),t.modal("hide"),s.count--},preventClose:function(){this._preventClose=!0}},{count:0});typeof require=="function"&&typeof module!="undefined"&&exports&&(module.exports=s);if(typeof define=="function"&&define.amd)return define(function(){n.BootstrapModal=s});n.BootstrapModal=s})(jQuery,_,Backbone)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/**
|
2
|
-
* Backbone Forms v0.
|
2
|
+
* Backbone Forms v0.11.0
|
3
3
|
*
|
4
|
-
* Copyright (c)
|
4
|
+
* Copyright (c) 2013 Charles Davison, Pow Media Ltd
|
5
5
|
*
|
6
6
|
* License and more information at:
|
7
7
|
* http://github.com/powmedia/backbone-forms
|
@@ -29,11 +29,11 @@
|
|
29
29
|
//==================================================================================================
|
30
30
|
//FORM
|
31
31
|
//==================================================================================================
|
32
|
-
|
32
|
+
|
33
33
|
var Form = (function() {
|
34
34
|
|
35
35
|
return Backbone.View.extend({
|
36
|
-
|
36
|
+
|
37
37
|
hasFocus: false,
|
38
38
|
|
39
39
|
/**
|
@@ -43,7 +43,7 @@ var Form = (function() {
|
|
43
43
|
* @param {Model} [options.model] Model the form relates to. Required if options.data is not set
|
44
44
|
* @param {Object} [options.data] Date to populate the form. Required if options.model is not set
|
45
45
|
* @param {String[]} [options.fields] Fields to include in the form, in order
|
46
|
-
* @param {String[]|Object[]} [options.fieldsets] How to divide the fields up by section. E.g. [{ legend: 'Title', fields: ['field1', 'field2'] }]
|
46
|
+
* @param {String[]|Object[]} [options.fieldsets] How to divide the fields up by section. E.g. [{ legend: 'Title', fields: ['field1', 'field2'] }]
|
47
47
|
* @param {String} [options.idPrefix] Prefix for editor IDs. By default, the model's CID is used.
|
48
48
|
* @param {String} [options.template] Form template key/name
|
49
49
|
* @param {String} [options.fieldsetTemplate] Fieldset template key/name
|
@@ -51,19 +51,19 @@ var Form = (function() {
|
|
51
51
|
*
|
52
52
|
* @return {Form}
|
53
53
|
*/
|
54
|
-
initialize: function(options) {
|
54
|
+
initialize: function(options) {
|
55
55
|
//Check templates have been loaded
|
56
56
|
if (!Form.templates.form) throw new Error('Templates not loaded');
|
57
57
|
|
58
58
|
//Get the schema
|
59
59
|
this.schema = (function() {
|
60
60
|
if (options.schema) return options.schema;
|
61
|
-
|
61
|
+
|
62
62
|
var model = options.model;
|
63
63
|
if (!model) throw new Error('Could not find schema');
|
64
|
-
|
64
|
+
|
65
65
|
if (_.isFunction(model.schema)) return model.schema();
|
66
|
-
|
66
|
+
|
67
67
|
return model.schema;
|
68
68
|
})();
|
69
69
|
|
@@ -80,7 +80,7 @@ var Form = (function() {
|
|
80
80
|
|
81
81
|
options.fieldsets = [{ fields: fields }];
|
82
82
|
}
|
83
|
-
|
83
|
+
|
84
84
|
//Store main attributes
|
85
85
|
this.options = options;
|
86
86
|
this.model = options.model;
|
@@ -95,9 +95,9 @@ var Form = (function() {
|
|
95
95
|
var self = this,
|
96
96
|
options = this.options,
|
97
97
|
template = Form.templates[options.template];
|
98
|
-
|
98
|
+
|
99
99
|
//Create el from template
|
100
|
-
var $form =
|
100
|
+
var $form = Form.helpers.parseHTML(template({
|
101
101
|
fieldsets: '<b class="bbf-tmp"></b>'
|
102
102
|
}));
|
103
103
|
|
@@ -112,7 +112,7 @@ var Form = (function() {
|
|
112
112
|
|
113
113
|
//Set the template contents as the main element; removes the wrapper element
|
114
114
|
this.setElement($form);
|
115
|
-
|
115
|
+
|
116
116
|
if (this.hasFocus) this.trigger('blur', this);
|
117
117
|
|
118
118
|
return this;
|
@@ -126,7 +126,7 @@ var Form = (function() {
|
|
126
126
|
* { legend: 'Some Fieldset', fields: ['field1', 'field2'] }
|
127
127
|
*
|
128
128
|
* @param {Object|Array} fieldset A fieldset definition
|
129
|
-
*
|
129
|
+
*
|
130
130
|
* @return {jQuery} The fieldset DOM element
|
131
131
|
*/
|
132
132
|
renderFieldset: function(fieldset) {
|
@@ -141,7 +141,7 @@ var Form = (function() {
|
|
141
141
|
}
|
142
142
|
|
143
143
|
//Concatenating HTML as strings won't work so we need to insert field elements into a placeholder
|
144
|
-
var $fieldset =
|
144
|
+
var $fieldset = Form.helpers.parseHTML(template(_.extend({}, fieldset, {
|
145
145
|
legend: '<b class="bbf-tmp-legend"></b>',
|
146
146
|
fields: '<b class="bbf-tmp-fields"></b>'
|
147
147
|
})));
|
@@ -176,17 +176,17 @@ var Form = (function() {
|
|
176
176
|
|
177
177
|
//Render the fields with editors, apart from Hidden fields
|
178
178
|
var fieldEl = field.render().el;
|
179
|
-
|
179
|
+
|
180
180
|
field.editor.on('all', function(event) {
|
181
181
|
// args = ["change", editor]
|
182
|
-
args = _.toArray(arguments);
|
182
|
+
var args = _.toArray(arguments);
|
183
183
|
args[0] = key + ':' + event;
|
184
184
|
args.splice(1, 0, this);
|
185
185
|
// args = ["key:change", this=form, editor]
|
186
186
|
|
187
|
-
this.trigger.apply(this, args)
|
187
|
+
this.trigger.apply(this, args);
|
188
188
|
}, self);
|
189
|
-
|
189
|
+
|
190
190
|
field.editor.on('change', function() {
|
191
191
|
this.trigger('change', self);
|
192
192
|
}, self);
|
@@ -203,13 +203,13 @@ var Form = (function() {
|
|
203
203
|
self.trigger('blur', self);
|
204
204
|
}, 0);
|
205
205
|
}, self);
|
206
|
-
|
207
|
-
if (itemSchema.type
|
206
|
+
|
207
|
+
if (itemSchema.type !== 'Hidden') {
|
208
208
|
$fieldsContainer.append(fieldEl);
|
209
209
|
}
|
210
210
|
});
|
211
211
|
|
212
|
-
$fieldsContainer = $fieldsContainer.children().unwrap()
|
212
|
+
$fieldsContainer = $fieldsContainer.children().unwrap();
|
213
213
|
|
214
214
|
return $fieldset;
|
215
215
|
},
|
@@ -266,24 +266,25 @@ var Form = (function() {
|
|
266
266
|
//Get errors from default Backbone model validator
|
267
267
|
if (model && model.validate) {
|
268
268
|
var modelErrors = model.validate(this.getValue());
|
269
|
-
|
269
|
+
|
270
270
|
if (modelErrors) {
|
271
271
|
var isDictionary = _.isObject(modelErrors) && !_.isArray(modelErrors);
|
272
|
-
|
272
|
+
|
273
273
|
//If errors are not in object form then just store on the error object
|
274
274
|
if (!isDictionary) {
|
275
275
|
errors._others = errors._others || [];
|
276
276
|
errors._others.push(modelErrors);
|
277
277
|
}
|
278
|
-
|
278
|
+
|
279
279
|
//Merge programmatic errors (requires model.validate() to return an object e.g. { fieldKey: 'error' })
|
280
280
|
if (isDictionary) {
|
281
281
|
_.each(modelErrors, function(val, key) {
|
282
282
|
//Set error on field if there isn't one already
|
283
283
|
if (self.fields[key] && !errors[key]) {
|
284
284
|
self.fields[key].setError(val);
|
285
|
+
errors[key] = val;
|
285
286
|
}
|
286
|
-
|
287
|
+
|
287
288
|
else {
|
288
289
|
//Otherwise add to '_others' key
|
289
290
|
errors._others = errors._others || [];
|
@@ -302,20 +303,25 @@ var Form = (function() {
|
|
302
303
|
/**
|
303
304
|
* Update the model with all latest values.
|
304
305
|
*
|
306
|
+
* @param {Object} [options] Options to pass to Model#set (e.g. { silent: true })
|
307
|
+
*
|
305
308
|
* @return {Object} Validation errors
|
306
309
|
*/
|
307
|
-
commit: function() {
|
310
|
+
commit: function(options) {
|
308
311
|
//Validate
|
309
312
|
var errors = this.validate();
|
310
313
|
if (errors) return errors;
|
311
314
|
|
312
315
|
//Commit
|
313
316
|
var modelError;
|
314
|
-
|
317
|
+
|
318
|
+
var setOptions = _.extend({
|
315
319
|
error: function(model, e) {
|
316
320
|
modelError = e;
|
317
321
|
}
|
318
|
-
});
|
322
|
+
}, options);
|
323
|
+
|
324
|
+
this.model.set(this.getValue(), setOptions);
|
319
325
|
|
320
326
|
if (modelError) return modelError;
|
321
327
|
},
|
@@ -323,14 +329,14 @@ var Form = (function() {
|
|
323
329
|
/**
|
324
330
|
* Get all the field values as an object.
|
325
331
|
* Use this method when passing data instead of objects
|
326
|
-
*
|
332
|
+
*
|
327
333
|
* @param {String} [key] Specific field value to get
|
328
334
|
*/
|
329
335
|
getValue: function(key) {
|
330
336
|
//Return only given key if specified
|
331
337
|
if (key) return this.fields[key].getValue();
|
332
|
-
|
333
|
-
//Otherwise return entire form
|
338
|
+
|
339
|
+
//Otherwise return entire form
|
334
340
|
var values = {};
|
335
341
|
_.each(this.fields, function(field) {
|
336
342
|
values[field.key] = field.getValue();
|
@@ -338,22 +344,31 @@ var Form = (function() {
|
|
338
344
|
|
339
345
|
return values;
|
340
346
|
},
|
341
|
-
|
347
|
+
|
342
348
|
/**
|
343
349
|
* Update field values, referenced by key
|
344
|
-
* @param {Object}
|
350
|
+
* @param {Object|String} key New values to set, or property to set
|
351
|
+
* @param val Value to set
|
345
352
|
*/
|
346
|
-
setValue: function(
|
347
|
-
|
348
|
-
|
353
|
+
setValue: function(prop, val) {
|
354
|
+
var data = {};
|
355
|
+
if (typeof prop === 'string') {
|
356
|
+
data[prop] = val;
|
357
|
+
} else {
|
358
|
+
data = prop;
|
359
|
+
}
|
360
|
+
|
361
|
+
var key;
|
362
|
+
for (key in this.schema) {
|
363
|
+
if (data[key] !== undefined) {
|
349
364
|
this.fields[key].setValue(data[key]);
|
350
365
|
}
|
351
366
|
}
|
352
367
|
},
|
353
|
-
|
368
|
+
|
354
369
|
focus: function() {
|
355
370
|
if (this.hasFocus) return;
|
356
|
-
|
371
|
+
|
357
372
|
var fieldset = this.options.fieldsets[0];
|
358
373
|
if (fieldset) {
|
359
374
|
var field;
|
@@ -368,12 +383,12 @@ var Form = (function() {
|
|
368
383
|
}
|
369
384
|
}
|
370
385
|
},
|
371
|
-
|
386
|
+
|
372
387
|
blur: function() {
|
373
388
|
if (!this.hasFocus) return;
|
374
|
-
|
375
|
-
focusedField = _.find(this.fields, function(field) { return field.editor.hasFocus; });
|
376
|
-
|
389
|
+
|
390
|
+
var focusedField = _.find(this.fields, function(field) { return field.editor.hasFocus; });
|
391
|
+
|
377
392
|
if (focusedField) focusedField.editor.blur();
|
378
393
|
},
|
379
394
|
|
@@ -382,23 +397,22 @@ var Form = (function() {
|
|
382
397
|
*/
|
383
398
|
remove: function() {
|
384
399
|
var fields = this.fields;
|
385
|
-
|
400
|
+
|
386
401
|
for (var key in fields) {
|
387
402
|
fields[key].remove();
|
388
403
|
}
|
389
404
|
|
390
405
|
Backbone.View.prototype.remove.call(this);
|
391
406
|
},
|
392
|
-
|
393
|
-
|
407
|
+
|
394
408
|
trigger: function(event) {
|
395
|
-
if (event
|
409
|
+
if (event === 'focus') {
|
396
410
|
this.hasFocus = true;
|
397
411
|
}
|
398
|
-
else if (event
|
412
|
+
else if (event === 'blur') {
|
399
413
|
this.hasFocus = false;
|
400
414
|
}
|
401
|
-
|
415
|
+
|
402
416
|
return Backbone.View.prototype.trigger.apply(this, arguments);
|
403
417
|
}
|
404
418
|
});
|
@@ -429,7 +443,7 @@ Form.helpers = (function() {
|
|
429
443
|
result = result[fields[i]];
|
430
444
|
}
|
431
445
|
return result;
|
432
|
-
}
|
446
|
+
};
|
433
447
|
|
434
448
|
/**
|
435
449
|
* This function is used to transform the key from a schema into the title used in a label.
|
@@ -470,7 +484,7 @@ Form.helpers = (function() {
|
|
470
484
|
_.templateSettings.interpolate = _interpolateBackup;
|
471
485
|
|
472
486
|
return template;
|
473
|
-
}
|
487
|
+
};
|
474
488
|
|
475
489
|
/**
|
476
490
|
* Helper to create a template with the {{mustache}} style tags.
|
@@ -480,7 +494,7 @@ Form.helpers = (function() {
|
|
480
494
|
* @return {Template|String} Compiled template or the evaluated string
|
481
495
|
*/
|
482
496
|
helpers.createTemplate = function(str, context) {
|
483
|
-
var template = helpers.compileTemplate(str);
|
497
|
+
var template = helpers.compileTemplate($.trim(str));
|
484
498
|
|
485
499
|
if (!context) {
|
486
500
|
return template;
|
@@ -496,7 +510,7 @@ Form.helpers = (function() {
|
|
496
510
|
*/
|
497
511
|
helpers.setTemplateCompiler = function(compiler) {
|
498
512
|
helpers.compileTemplate = compiler;
|
499
|
-
}
|
513
|
+
};
|
500
514
|
|
501
515
|
|
502
516
|
/**
|
@@ -550,33 +564,6 @@ Form.helpers = (function() {
|
|
550
564
|
return new constructorFn(options);
|
551
565
|
};
|
552
566
|
|
553
|
-
/**
|
554
|
-
* Triggers an event that can be cancelled. Requires the user to invoke a callback. If false
|
555
|
-
* is passed to the callback, the action does not run.
|
556
|
-
*
|
557
|
-
* NOTE: This helper uses private Backbone apis so can break when Backbone is upgraded
|
558
|
-
*
|
559
|
-
* @param {Mixed} Instance of Backbone model, view, collection to trigger event on
|
560
|
-
* @param {String} Event name
|
561
|
-
* @param {Array} Arguments to pass to the event handlers
|
562
|
-
* @param {Function} Callback to run after the event handler has run.
|
563
|
-
* If any of them passed false or error, this callback won't run
|
564
|
-
*/
|
565
|
-
helpers.triggerCancellableEvent = function(subject, event, args, callback) {
|
566
|
-
//Return if there are no event listeners
|
567
|
-
if (!subject._callbacks || !subject._callbacks[event]) return callback();
|
568
|
-
|
569
|
-
var next = subject._callbacks[event].next;
|
570
|
-
if (!next) return callback();
|
571
|
-
|
572
|
-
var fn = next.callback,
|
573
|
-
context = next.context || this;
|
574
|
-
|
575
|
-
//Add the callback that will be used when done
|
576
|
-
args.push(callback);
|
577
|
-
|
578
|
-
fn.apply(context, args);
|
579
|
-
}
|
580
567
|
|
581
568
|
/**
|
582
569
|
* Returns a validation function based on the type defined in the schema
|
@@ -614,6 +601,20 @@ Form.helpers = (function() {
|
|
614
601
|
};
|
615
602
|
|
616
603
|
|
604
|
+
/**
|
605
|
+
* Given an HTML string, return a jQuery-wrapped array of DOM nodes.
|
606
|
+
*
|
607
|
+
* @param {String} html
|
608
|
+
* @return {Object}
|
609
|
+
*/
|
610
|
+
helpers.parseHTML = function(html) {
|
611
|
+
if ($.parseHTML !== undefined) {
|
612
|
+
return $($.parseHTML(html));
|
613
|
+
}
|
614
|
+
return $(html);
|
615
|
+
};
|
616
|
+
|
617
|
+
|
617
618
|
return helpers;
|
618
619
|
|
619
620
|
})();
|
@@ -633,7 +634,7 @@ Form.validators = (function() {
|
|
633
634
|
email: 'Invalid email address',
|
634
635
|
url: 'Invalid URL',
|
635
636
|
match: 'Must match field "{{field}}"'
|
636
|
-
}
|
637
|
+
};
|
637
638
|
|
638
639
|
validators.required = function(options) {
|
639
640
|
options = _.extend({
|
@@ -649,7 +650,7 @@ Form.validators = (function() {
|
|
649
650
|
message: Form.helpers.createTemplate(options.message, options)
|
650
651
|
};
|
651
652
|
|
652
|
-
if (value === null || value === undefined || value === '') return err;
|
653
|
+
if (value === null || value === undefined || value === false || value === '') return err;
|
653
654
|
};
|
654
655
|
};
|
655
656
|
|
@@ -690,7 +691,7 @@ Form.validators = (function() {
|
|
690
691
|
options = _.extend({
|
691
692
|
type: 'url',
|
692
693
|
message: this.errMessages.url,
|
693
|
-
regexp: /^(http|https):\/\/(([A-Z0-9][A-Z0-9_
|
694
|
+
regexp: /^(http|https):\/\/(([A-Z0-9][A-Z0-9_\-]*)(\.[A-Z0-9][A-Z0-9_\-]*)+)(:(\d+))?\/?/i
|
694
695
|
}, options);
|
695
696
|
|
696
697
|
return validators.regexp(options);
|
@@ -715,8 +716,8 @@ Form.validators = (function() {
|
|
715
716
|
//Don't check empty values (add a 'required' validator for this)
|
716
717
|
if (value === null || value === undefined || value === '') return;
|
717
718
|
|
718
|
-
if (value
|
719
|
-
}
|
719
|
+
if (value !== attrs[options.field]) return err;
|
720
|
+
};
|
720
721
|
};
|
721
722
|
|
722
723
|
|
@@ -748,7 +749,7 @@ Form.Field = (function() {
|
|
748
749
|
*/
|
749
750
|
/**
|
750
751
|
* Creates a new field
|
751
|
-
*
|
752
|
+
*
|
752
753
|
* @param {Object} options
|
753
754
|
* @param {Object} [options.schema] Field schema. Defaults to { type: 'Text' }
|
754
755
|
* @param {Model} [options.model] Model the field relates to. Required if options.data is not set.
|
@@ -768,7 +769,7 @@ Form.Field = (function() {
|
|
768
769
|
|
769
770
|
//Turn schema shorthand notation (e.g. 'Text') into schema object
|
770
771
|
if (_.isString(options.schema)) options.schema = { type: options.schema };
|
771
|
-
|
772
|
+
|
772
773
|
//Set schema defaults
|
773
774
|
this.schema = _.extend({
|
774
775
|
type: 'Text',
|
@@ -777,6 +778,29 @@ Form.Field = (function() {
|
|
777
778
|
}, options.schema);
|
778
779
|
},
|
779
780
|
|
781
|
+
|
782
|
+
/**
|
783
|
+
* Provides the context for rendering the field
|
784
|
+
* Override this to extend the default context
|
785
|
+
*
|
786
|
+
* @param {Object} schema
|
787
|
+
* @param {View} editor
|
788
|
+
*
|
789
|
+
* @return {Object} Locals passed to the template
|
790
|
+
*/
|
791
|
+
renderingContext: function(schema, editor) {
|
792
|
+
return {
|
793
|
+
key: this.key,
|
794
|
+
title: schema.title,
|
795
|
+
id: editor.id,
|
796
|
+
type: schema.type,
|
797
|
+
editor: '<b class="bbf-tmp-editor"></b>',
|
798
|
+
help: '<b class="bbf-tmp-help"></b>',
|
799
|
+
error: '<b class="bbf-tmp-error"></b>'
|
800
|
+
};
|
801
|
+
},
|
802
|
+
|
803
|
+
|
780
804
|
/**
|
781
805
|
* Renders the field
|
782
806
|
*/
|
@@ -802,17 +826,15 @@ Form.Field = (function() {
|
|
802
826
|
|
803
827
|
//Decide on the editor to use
|
804
828
|
var editor = this.editor = helpers.createEditor(schema.type, options);
|
805
|
-
|
829
|
+
|
806
830
|
//Create the element
|
807
|
-
var $field =
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
}));
|
815
|
-
|
831
|
+
var $field = Form.helpers.parseHTML(templates[schema.template](this.renderingContext(schema, editor)));
|
832
|
+
|
833
|
+
//Remove <label> if it's not wanted
|
834
|
+
if (schema.title === false) {
|
835
|
+
$field.find('label[for="'+editor.id+'"]').first().remove();
|
836
|
+
}
|
837
|
+
|
816
838
|
//Render editor
|
817
839
|
$field.find('.bbf-tmp-editor').replaceWith(editor.render().el);
|
818
840
|
|
@@ -820,13 +842,17 @@ Form.Field = (function() {
|
|
820
842
|
this.$help = $('.bbf-tmp-help', $field).parent();
|
821
843
|
this.$help.empty();
|
822
844
|
if (this.schema.help) this.$help.html(this.schema.help);
|
823
|
-
|
845
|
+
|
846
|
+
//Create error container
|
847
|
+
this.$error = $($('.bbf-tmp-error', $field).parent()[0]);
|
848
|
+
if (this.$error) this.$error.empty();
|
849
|
+
|
824
850
|
//Add custom CSS class names
|
825
851
|
if (this.schema.fieldClass) $field.addClass(this.schema.fieldClass);
|
826
|
-
|
852
|
+
|
827
853
|
//Add custom attributes
|
828
854
|
if (this.schema.fieldAttrs) $field.attr(this.schema.fieldAttrs);
|
829
|
-
|
855
|
+
|
830
856
|
//Replace the generated wrapper tag
|
831
857
|
this.setElement($field);
|
832
858
|
|
@@ -854,7 +880,7 @@ Form.Field = (function() {
|
|
854
880
|
|
855
881
|
return id;
|
856
882
|
},
|
857
|
-
|
883
|
+
|
858
884
|
/**
|
859
885
|
* Check the validity of the field
|
860
886
|
*
|
@@ -871,7 +897,7 @@ Form.Field = (function() {
|
|
871
897
|
|
872
898
|
return error;
|
873
899
|
},
|
874
|
-
|
900
|
+
|
875
901
|
/**
|
876
902
|
* Set the field into an error state, adding the error class and setting the error message
|
877
903
|
*
|
@@ -880,26 +906,32 @@ Form.Field = (function() {
|
|
880
906
|
setError: function(msg) {
|
881
907
|
//Object and NestedModel types set their own errors internally
|
882
908
|
if (this.editor.hasNestedForm) return;
|
883
|
-
|
909
|
+
|
884
910
|
var errClass = Form.classNames.error;
|
885
911
|
|
886
912
|
this.$el.addClass(errClass);
|
887
|
-
|
888
|
-
if (this.$
|
913
|
+
|
914
|
+
if (this.$error) {
|
915
|
+
this.$error.html(msg);
|
916
|
+
} else if (this.$help) {
|
917
|
+
this.$help.html(msg);
|
918
|
+
}
|
889
919
|
},
|
890
|
-
|
920
|
+
|
891
921
|
/**
|
892
922
|
* Clear the error state and reset the help message
|
893
923
|
*/
|
894
924
|
clearError: function() {
|
895
925
|
var errClass = Form.classNames.error;
|
896
|
-
|
926
|
+
|
897
927
|
this.$el.removeClass(errClass);
|
898
|
-
|
928
|
+
|
899
929
|
// some fields (e.g., Hidden), may not have a help el
|
900
|
-
if (this.$
|
930
|
+
if (this.$error) {
|
931
|
+
this.$error.empty();
|
932
|
+
} else if (this.$help) {
|
901
933
|
this.$help.empty();
|
902
|
-
|
934
|
+
|
903
935
|
//Reset help text if available
|
904
936
|
var helpMsg = this.schema.help;
|
905
937
|
if (helpMsg) this.$help.html(helpMsg);
|
@@ -921,7 +953,7 @@ Form.Field = (function() {
|
|
921
953
|
getValue: function() {
|
922
954
|
return this.editor.getValue();
|
923
955
|
},
|
924
|
-
|
956
|
+
|
925
957
|
/**
|
926
958
|
* Set/change the value of the editor
|
927
959
|
*
|
@@ -930,11 +962,11 @@ Form.Field = (function() {
|
|
930
962
|
setValue: function(value) {
|
931
963
|
this.editor.setValue(value);
|
932
964
|
},
|
933
|
-
|
965
|
+
|
934
966
|
focus: function() {
|
935
967
|
this.editor.focus();
|
936
968
|
},
|
937
|
-
|
969
|
+
|
938
970
|
blur: function() {
|
939
971
|
this.editor.blur();
|
940
972
|
},
|
@@ -952,6 +984,7 @@ Form.Field = (function() {
|
|
952
984
|
|
953
985
|
})();
|
954
986
|
|
987
|
+
|
955
988
|
//========================================================================
|
956
989
|
//EDITORS
|
957
990
|
//========================================================================
|
@@ -975,7 +1008,7 @@ Form.editors = (function() {
|
|
975
1008
|
editors.Base = Backbone.View.extend({
|
976
1009
|
|
977
1010
|
defaultValue: null,
|
978
|
-
|
1011
|
+
|
979
1012
|
hasFocus: false,
|
980
1013
|
|
981
1014
|
initialize: function(options) {
|
@@ -991,20 +1024,20 @@ Form.editors = (function() {
|
|
991
1024
|
else if (options.value) {
|
992
1025
|
this.value = options.value;
|
993
1026
|
}
|
994
|
-
|
1027
|
+
|
995
1028
|
if (this.value === undefined) this.value = this.defaultValue;
|
996
1029
|
|
997
1030
|
this.key = options.key;
|
998
1031
|
this.form = options.form;
|
999
1032
|
this.schema = options.schema || {};
|
1000
1033
|
this.validators = options.validators || this.schema.validators;
|
1001
|
-
|
1034
|
+
|
1002
1035
|
//Main attributes
|
1003
1036
|
this.$el.attr('name', this.getName());
|
1004
|
-
|
1037
|
+
|
1005
1038
|
//Add custom CSS class names
|
1006
1039
|
if (this.schema.editorClass) this.$el.addClass(this.schema.editorClass);
|
1007
|
-
|
1040
|
+
|
1008
1041
|
//Add custom attributes
|
1009
1042
|
if (this.schema.editorAttrs) this.$el.attr(this.schema.editorAttrs);
|
1010
1043
|
},
|
@@ -1012,15 +1045,15 @@ Form.editors = (function() {
|
|
1012
1045
|
getValue: function() {
|
1013
1046
|
throw 'Not implemented. Extend and override this method.';
|
1014
1047
|
},
|
1015
|
-
|
1048
|
+
|
1016
1049
|
setValue: function() {
|
1017
1050
|
throw 'Not implemented. Extend and override this method.';
|
1018
1051
|
},
|
1019
|
-
|
1052
|
+
|
1020
1053
|
focus: function() {
|
1021
1054
|
throw 'Not implemented. Extend and override this method.';
|
1022
1055
|
},
|
1023
|
-
|
1056
|
+
|
1024
1057
|
blur: function() {
|
1025
1058
|
throw 'Not implemented. Extend and override this method.';
|
1026
1059
|
},
|
@@ -1029,39 +1062,38 @@ Form.editors = (function() {
|
|
1029
1062
|
* Get the value for the form input 'name' attribute
|
1030
1063
|
*
|
1031
1064
|
* @return {String}
|
1032
|
-
*
|
1065
|
+
*
|
1033
1066
|
* @api private
|
1034
1067
|
*/
|
1035
1068
|
getName: function() {
|
1036
1069
|
var key = this.key || '';
|
1037
1070
|
|
1038
1071
|
//Replace periods with underscores (e.g. for when using paths)
|
1039
|
-
return key.replace(/\./g, '_')
|
1072
|
+
return key.replace(/\./g, '_');
|
1040
1073
|
},
|
1041
|
-
|
1074
|
+
|
1042
1075
|
/**
|
1043
1076
|
* Update the model with the current value
|
1044
1077
|
* NOTE: The method is defined on the editors so that they can be used independently of fields
|
1045
1078
|
*
|
1046
1079
|
* @return {Mixed} error
|
1047
1080
|
*/
|
1048
|
-
commit: function() {
|
1081
|
+
commit: function(options) {
|
1049
1082
|
var error = this.validate();
|
1050
1083
|
if (error) return error;
|
1051
|
-
|
1052
|
-
this.
|
1053
|
-
error
|
1054
|
-
error = e;
|
1055
|
-
}
|
1084
|
+
|
1085
|
+
this.listenTo(this.model, 'invalid', function(model, e) {
|
1086
|
+
error = e;
|
1056
1087
|
});
|
1057
|
-
|
1088
|
+
this.model.set(this.key, this.getValue(), options);
|
1089
|
+
|
1058
1090
|
if (error) return error;
|
1059
1091
|
},
|
1060
|
-
|
1092
|
+
|
1061
1093
|
/**
|
1062
1094
|
* Check validity
|
1063
1095
|
* NOTE: The method is defined on the editors so that they can be used independently of fields
|
1064
|
-
*
|
1096
|
+
*
|
1065
1097
|
* @return {String}
|
1066
1098
|
*/
|
1067
1099
|
validate: function() {
|
@@ -1077,22 +1109,22 @@ Form.editors = (function() {
|
|
1077
1109
|
_.every(validators, function(validator) {
|
1078
1110
|
error = getValidator(validator)(value, formValues);
|
1079
1111
|
|
1080
|
-
return
|
1112
|
+
return error ? false : true;
|
1081
1113
|
});
|
1082
1114
|
}
|
1083
1115
|
|
1084
1116
|
return error;
|
1085
1117
|
},
|
1086
|
-
|
1087
|
-
|
1118
|
+
|
1119
|
+
|
1088
1120
|
trigger: function(event) {
|
1089
|
-
if (event
|
1121
|
+
if (event === 'focus') {
|
1090
1122
|
this.hasFocus = true;
|
1091
1123
|
}
|
1092
|
-
else if (event
|
1124
|
+
else if (event === 'blur') {
|
1093
1125
|
this.hasFocus = false;
|
1094
1126
|
}
|
1095
|
-
|
1127
|
+
|
1096
1128
|
return Backbone.View.prototype.trigger.apply(this, arguments);
|
1097
1129
|
}
|
1098
1130
|
});
|
@@ -1102,11 +1134,11 @@ Form.editors = (function() {
|
|
1102
1134
|
editors.Text = editors.Base.extend({
|
1103
1135
|
|
1104
1136
|
tagName: 'input',
|
1105
|
-
|
1137
|
+
|
1106
1138
|
defaultValue: '',
|
1107
|
-
|
1139
|
+
|
1108
1140
|
previousValue: '',
|
1109
|
-
|
1141
|
+
|
1110
1142
|
events: {
|
1111
1143
|
'keyup': 'determineChange',
|
1112
1144
|
'keypress': function(event) {
|
@@ -1125,15 +1157,15 @@ Form.editors = (function() {
|
|
1125
1157
|
this.trigger('blur', this);
|
1126
1158
|
}
|
1127
1159
|
},
|
1128
|
-
|
1160
|
+
|
1129
1161
|
initialize: function(options) {
|
1130
1162
|
editors.Base.prototype.initialize.call(this, options);
|
1131
|
-
|
1163
|
+
|
1132
1164
|
var schema = this.schema;
|
1133
|
-
|
1165
|
+
|
1134
1166
|
//Allow customising text type (email, phone etc.) for HTML5 browsers
|
1135
1167
|
var type = 'text';
|
1136
|
-
|
1168
|
+
|
1137
1169
|
if (schema && schema.editorAttrs && schema.editorAttrs.type) type = schema.editorAttrs.type;
|
1138
1170
|
if (schema && schema.dataType) type = schema.dataType;
|
1139
1171
|
|
@@ -1148,14 +1180,14 @@ Form.editors = (function() {
|
|
1148
1180
|
|
1149
1181
|
return this;
|
1150
1182
|
},
|
1151
|
-
|
1183
|
+
|
1152
1184
|
determineChange: function(event) {
|
1153
1185
|
var currentValue = this.$el.val();
|
1154
|
-
var changed = (currentValue
|
1155
|
-
|
1186
|
+
var changed = (currentValue !== this.previousValue);
|
1187
|
+
|
1156
1188
|
if (changed) {
|
1157
1189
|
this.previousValue = currentValue;
|
1158
|
-
|
1190
|
+
|
1159
1191
|
this.trigger('change', this);
|
1160
1192
|
}
|
1161
1193
|
},
|
@@ -1167,27 +1199,27 @@ Form.editors = (function() {
|
|
1167
1199
|
getValue: function() {
|
1168
1200
|
return this.$el.val();
|
1169
1201
|
},
|
1170
|
-
|
1202
|
+
|
1171
1203
|
/**
|
1172
1204
|
* Sets the value of the form element
|
1173
1205
|
* @param {String}
|
1174
1206
|
*/
|
1175
|
-
setValue: function(value) {
|
1207
|
+
setValue: function(value) {
|
1176
1208
|
this.$el.val(value);
|
1177
1209
|
},
|
1178
|
-
|
1210
|
+
|
1179
1211
|
focus: function() {
|
1180
1212
|
if (this.hasFocus) return;
|
1181
1213
|
|
1182
1214
|
this.$el.focus();
|
1183
1215
|
},
|
1184
|
-
|
1216
|
+
|
1185
1217
|
blur: function() {
|
1186
1218
|
if (!this.hasFocus) return;
|
1187
1219
|
|
1188
1220
|
this.$el.blur();
|
1189
1221
|
},
|
1190
|
-
|
1222
|
+
|
1191
1223
|
select: function() {
|
1192
1224
|
this.$el.select();
|
1193
1225
|
}
|
@@ -1211,6 +1243,7 @@ Form.editors = (function() {
|
|
1211
1243
|
editors.Text.prototype.initialize.call(this, options);
|
1212
1244
|
|
1213
1245
|
this.$el.attr('type', 'number');
|
1246
|
+
this.$el.attr('step', 'any');
|
1214
1247
|
},
|
1215
1248
|
|
1216
1249
|
/**
|
@@ -1222,14 +1255,14 @@ Form.editors = (function() {
|
|
1222
1255
|
setTimeout(function() {
|
1223
1256
|
self.determineChange();
|
1224
1257
|
}, 0);
|
1225
|
-
}
|
1226
|
-
|
1258
|
+
};
|
1259
|
+
|
1227
1260
|
//Allow backspace
|
1228
|
-
if (event.charCode
|
1261
|
+
if (event.charCode === 0) {
|
1229
1262
|
delayedDetermineChange();
|
1230
1263
|
return;
|
1231
1264
|
}
|
1232
|
-
|
1265
|
+
|
1233
1266
|
//Get the whole new value so that we can prevent things like double decimals points etc.
|
1234
1267
|
var newVal = this.$el.val() + String.fromCharCode(event.charCode);
|
1235
1268
|
|
@@ -1243,12 +1276,12 @@ Form.editors = (function() {
|
|
1243
1276
|
}
|
1244
1277
|
},
|
1245
1278
|
|
1246
|
-
getValue: function() {
|
1279
|
+
getValue: function() {
|
1247
1280
|
var value = this.$el.val();
|
1248
|
-
|
1281
|
+
|
1249
1282
|
return value === "" ? null : parseFloat(value, 10);
|
1250
1283
|
},
|
1251
|
-
|
1284
|
+
|
1252
1285
|
setValue: function(value) {
|
1253
1286
|
value = (function() {
|
1254
1287
|
if (_.isNumber(value)) return value;
|
@@ -1259,7 +1292,7 @@ Form.editors = (function() {
|
|
1259
1292
|
})();
|
1260
1293
|
|
1261
1294
|
if (_.isNaN(value)) value = null;
|
1262
|
-
|
1295
|
+
|
1263
1296
|
editors.Text.prototype.setValue.call(this, value);
|
1264
1297
|
}
|
1265
1298
|
|
@@ -1284,15 +1317,15 @@ Form.editors = (function() {
|
|
1284
1317
|
tagName: 'textarea'
|
1285
1318
|
|
1286
1319
|
});
|
1287
|
-
|
1288
|
-
|
1320
|
+
|
1321
|
+
|
1289
1322
|
//CHECKBOX
|
1290
1323
|
editors.Checkbox = editors.Base.extend({
|
1291
|
-
|
1324
|
+
|
1292
1325
|
defaultValue: false,
|
1293
|
-
|
1326
|
+
|
1294
1327
|
tagName: 'input',
|
1295
|
-
|
1328
|
+
|
1296
1329
|
events: {
|
1297
1330
|
'click': function(event) {
|
1298
1331
|
this.trigger('change', this);
|
@@ -1304,10 +1337,10 @@ Form.editors = (function() {
|
|
1304
1337
|
this.trigger('blur', this);
|
1305
1338
|
}
|
1306
1339
|
},
|
1307
|
-
|
1340
|
+
|
1308
1341
|
initialize: function(options) {
|
1309
1342
|
editors.Base.prototype.initialize.call(this, options);
|
1310
|
-
|
1343
|
+
|
1311
1344
|
this.$el.attr('type', 'checkbox');
|
1312
1345
|
},
|
1313
1346
|
|
@@ -1319,35 +1352,35 @@ Form.editors = (function() {
|
|
1319
1352
|
|
1320
1353
|
return this;
|
1321
1354
|
},
|
1322
|
-
|
1355
|
+
|
1323
1356
|
getValue: function() {
|
1324
1357
|
return this.$el.prop('checked');
|
1325
1358
|
},
|
1326
|
-
|
1359
|
+
|
1327
1360
|
setValue: function(value) {
|
1328
1361
|
if (value) {
|
1329
1362
|
this.$el.prop('checked', true);
|
1330
1363
|
}
|
1331
1364
|
},
|
1332
|
-
|
1365
|
+
|
1333
1366
|
focus: function() {
|
1334
1367
|
if (this.hasFocus) return;
|
1335
1368
|
|
1336
1369
|
this.$el.focus();
|
1337
1370
|
},
|
1338
|
-
|
1371
|
+
|
1339
1372
|
blur: function() {
|
1340
1373
|
if (!this.hasFocus) return;
|
1341
1374
|
|
1342
1375
|
this.$el.blur();
|
1343
1376
|
}
|
1344
|
-
|
1377
|
+
|
1345
1378
|
});
|
1346
|
-
|
1347
|
-
|
1379
|
+
|
1380
|
+
|
1348
1381
|
//HIDDEN
|
1349
1382
|
editors.Hidden = editors.Base.extend({
|
1350
|
-
|
1383
|
+
|
1351
1384
|
defaultValue: '',
|
1352
1385
|
|
1353
1386
|
initialize: function(options) {
|
@@ -1355,21 +1388,21 @@ Form.editors = (function() {
|
|
1355
1388
|
|
1356
1389
|
this.$el.attr('type', 'hidden');
|
1357
1390
|
},
|
1358
|
-
|
1391
|
+
|
1359
1392
|
getValue: function() {
|
1360
1393
|
return this.value;
|
1361
1394
|
},
|
1362
|
-
|
1395
|
+
|
1363
1396
|
setValue: function(value) {
|
1364
1397
|
this.value = value;
|
1365
1398
|
},
|
1366
|
-
|
1399
|
+
|
1367
1400
|
focus: function() {
|
1368
|
-
|
1401
|
+
|
1369
1402
|
},
|
1370
|
-
|
1403
|
+
|
1371
1404
|
blur: function() {
|
1372
|
-
|
1405
|
+
|
1373
1406
|
}
|
1374
1407
|
|
1375
1408
|
});
|
@@ -1377,7 +1410,7 @@ Form.editors = (function() {
|
|
1377
1410
|
|
1378
1411
|
/**
|
1379
1412
|
* SELECT
|
1380
|
-
*
|
1413
|
+
*
|
1381
1414
|
* Renders a <select> with given options
|
1382
1415
|
*
|
1383
1416
|
* Requires an 'options' value on the schema.
|
@@ -1387,7 +1420,7 @@ Form.editors = (function() {
|
|
1387
1420
|
editors.Select = editors.Base.extend({
|
1388
1421
|
|
1389
1422
|
tagName: 'select',
|
1390
|
-
|
1423
|
+
|
1391
1424
|
events: {
|
1392
1425
|
'change': function(event) {
|
1393
1426
|
this.trigger('change', this);
|
@@ -1440,7 +1473,7 @@ Form.editors = (function() {
|
|
1440
1473
|
else if (_.isFunction(options)) {
|
1441
1474
|
options(function(result) {
|
1442
1475
|
self.renderOptions(result);
|
1443
|
-
});
|
1476
|
+
}, self);
|
1444
1477
|
}
|
1445
1478
|
|
1446
1479
|
//Otherwise, ready to go straight to renderOptions
|
@@ -1459,6 +1492,17 @@ Form.editors = (function() {
|
|
1459
1492
|
var $select = this.$el,
|
1460
1493
|
html;
|
1461
1494
|
|
1495
|
+
html = this._getOptionsHtml(options);
|
1496
|
+
|
1497
|
+
//Insert options
|
1498
|
+
$select.html(html);
|
1499
|
+
|
1500
|
+
//Select correct option
|
1501
|
+
this.setValue(this.value);
|
1502
|
+
},
|
1503
|
+
|
1504
|
+
_getOptionsHtml: function(options) {
|
1505
|
+
var html;
|
1462
1506
|
//Accept string of HTML
|
1463
1507
|
if (_.isString(options)) {
|
1464
1508
|
html = options;
|
@@ -1471,30 +1515,36 @@ Form.editors = (function() {
|
|
1471
1515
|
|
1472
1516
|
//Or Backbone collection
|
1473
1517
|
else if (options instanceof Backbone.Collection) {
|
1474
|
-
html = this._collectionToHtml(options)
|
1518
|
+
html = this._collectionToHtml(options);
|
1475
1519
|
}
|
1476
1520
|
|
1477
|
-
|
1478
|
-
|
1521
|
+
else if (_.isFunction(options)) {
|
1522
|
+
var newOptions;
|
1523
|
+
|
1524
|
+
options(function(opts) {
|
1525
|
+
newOptions = opts;
|
1526
|
+
}, this);
|
1527
|
+
|
1528
|
+
html = this._getOptionsHtml(newOptions);
|
1529
|
+
}
|
1479
1530
|
|
1480
|
-
|
1481
|
-
this.setValue(this.value);
|
1531
|
+
return html;
|
1482
1532
|
},
|
1483
1533
|
|
1484
1534
|
getValue: function() {
|
1485
1535
|
return this.$el.val();
|
1486
1536
|
},
|
1487
|
-
|
1537
|
+
|
1488
1538
|
setValue: function(value) {
|
1489
1539
|
this.$el.val(value);
|
1490
1540
|
},
|
1491
|
-
|
1541
|
+
|
1492
1542
|
focus: function() {
|
1493
1543
|
if (this.hasFocus) return;
|
1494
1544
|
|
1495
1545
|
this.$el.focus();
|
1496
1546
|
},
|
1497
|
-
|
1547
|
+
|
1498
1548
|
blur: function() {
|
1499
1549
|
if (!this.hasFocus) return;
|
1500
1550
|
|
@@ -1503,7 +1553,7 @@ Form.editors = (function() {
|
|
1503
1553
|
|
1504
1554
|
/**
|
1505
1555
|
* Transforms a collection into HTML ready to use in the renderOptions method
|
1506
|
-
* @param {Backbone.Collection}
|
1556
|
+
* @param {Backbone.Collection}
|
1507
1557
|
* @return {String}
|
1508
1558
|
*/
|
1509
1559
|
_collectionToHtml: function(collection) {
|
@@ -1531,13 +1581,19 @@ Form.editors = (function() {
|
|
1531
1581
|
//Generate HTML
|
1532
1582
|
_.each(array, function(option) {
|
1533
1583
|
if (_.isObject(option)) {
|
1534
|
-
|
1535
|
-
|
1584
|
+
if (option.group) {
|
1585
|
+
html.push('<optgroup label="'+option.group+'">');
|
1586
|
+
html.push(this._getOptionsHtml(option.options))
|
1587
|
+
html.push('</optgroup>');
|
1588
|
+
} else {
|
1589
|
+
var val = (option.val || option.val === 0) ? option.val : '';
|
1590
|
+
html.push('<option value="'+val+'">'+option.label+'</option>');
|
1591
|
+
}
|
1536
1592
|
}
|
1537
1593
|
else {
|
1538
1594
|
html.push('<option>'+option+'</option>');
|
1539
1595
|
}
|
1540
|
-
});
|
1596
|
+
}, this);
|
1541
1597
|
|
1542
1598
|
return html.join('');
|
1543
1599
|
}
|
@@ -1548,7 +1604,7 @@ Form.editors = (function() {
|
|
1548
1604
|
|
1549
1605
|
/**
|
1550
1606
|
* RADIO
|
1551
|
-
*
|
1607
|
+
*
|
1552
1608
|
* Renders a <ul> with given options represented as <li> objects containing radio buttons
|
1553
1609
|
*
|
1554
1610
|
* Requires an 'options' value on the schema.
|
@@ -1559,10 +1615,10 @@ Form.editors = (function() {
|
|
1559
1615
|
|
1560
1616
|
tagName: 'ul',
|
1561
1617
|
className: 'bbf-radio',
|
1562
|
-
|
1618
|
+
|
1563
1619
|
events: {
|
1564
|
-
'
|
1565
|
-
this.trigger('change', this)
|
1620
|
+
'change input[type=radio]': function() {
|
1621
|
+
this.trigger('change', this);
|
1566
1622
|
},
|
1567
1623
|
'focus input[type=radio]': function() {
|
1568
1624
|
if (this.hasFocus) return;
|
@@ -1585,22 +1641,22 @@ Form.editors = (function() {
|
|
1585
1641
|
setValue: function(value) {
|
1586
1642
|
this.$('input[type=radio]').val([value]);
|
1587
1643
|
},
|
1588
|
-
|
1644
|
+
|
1589
1645
|
focus: function() {
|
1590
1646
|
if (this.hasFocus) return;
|
1591
|
-
|
1647
|
+
|
1592
1648
|
var checked = this.$('input[type=radio]:checked');
|
1593
1649
|
if (checked[0]) {
|
1594
1650
|
checked.focus();
|
1595
1651
|
return;
|
1596
1652
|
}
|
1597
|
-
|
1653
|
+
|
1598
1654
|
this.$('input[type=radio]').first().focus();
|
1599
1655
|
},
|
1600
|
-
|
1656
|
+
|
1601
1657
|
blur: function() {
|
1602
1658
|
if (!this.hasFocus) return;
|
1603
|
-
|
1659
|
+
|
1604
1660
|
this.$('input[type=radio]:focus').blur();
|
1605
1661
|
},
|
1606
1662
|
|
@@ -1617,13 +1673,13 @@ Form.editors = (function() {
|
|
1617
1673
|
_.each(array, function(option, index) {
|
1618
1674
|
var itemHtml = '<li>';
|
1619
1675
|
if (_.isObject(option)) {
|
1620
|
-
var val = option.val ? option.val : '';
|
1621
|
-
itemHtml += ('<input type="radio" name="'+self.id+'" value="'+val+'" id="'+self.id+'-'+index+'" />')
|
1622
|
-
itemHtml += ('<label for="'+self.id+'-'+index+'">'+option.label+'</label>')
|
1676
|
+
var val = (option.val || option.val === 0) ? option.val : '';
|
1677
|
+
itemHtml += ('<input type="radio" name="'+self.id+'" value="'+val+'" id="'+self.id+'-'+index+'" />');
|
1678
|
+
itemHtml += ('<label for="'+self.id+'-'+index+'">'+option.label+'</label>');
|
1623
1679
|
}
|
1624
1680
|
else {
|
1625
|
-
itemHtml += ('<input type="radio" name="'+self.id+'" value="'+option+'" id="'+self.id+'-'+index+'" />')
|
1626
|
-
itemHtml += ('<label for="'+self.id+'-'+index+'">'+option+'</label>')
|
1681
|
+
itemHtml += ('<input type="radio" name="'+self.id+'" value="'+option+'" id="'+self.id+'-'+index+'" />');
|
1682
|
+
itemHtml += ('<label for="'+self.id+'-'+index+'">'+option+'</label>');
|
1627
1683
|
}
|
1628
1684
|
itemHtml += '</li>';
|
1629
1685
|
html.push(itemHtml);
|
@@ -1648,10 +1704,10 @@ Form.editors = (function() {
|
|
1648
1704
|
|
1649
1705
|
tagName: 'ul',
|
1650
1706
|
className: 'bbf-checkboxes',
|
1651
|
-
|
1707
|
+
|
1652
1708
|
events: {
|
1653
1709
|
'click input[type=checkbox]': function() {
|
1654
|
-
this.trigger('change', this)
|
1710
|
+
this.trigger('change', this);
|
1655
1711
|
},
|
1656
1712
|
'focus input[type=checkbox]': function() {
|
1657
1713
|
if (this.hasFocus) return;
|
@@ -1679,16 +1735,16 @@ Form.editors = (function() {
|
|
1679
1735
|
if (!_.isArray(values)) values = [values];
|
1680
1736
|
this.$('input[type=checkbox]').val(values);
|
1681
1737
|
},
|
1682
|
-
|
1738
|
+
|
1683
1739
|
focus: function() {
|
1684
1740
|
if (this.hasFocus) return;
|
1685
|
-
|
1741
|
+
|
1686
1742
|
this.$('input[type=checkbox]').first().focus();
|
1687
1743
|
},
|
1688
|
-
|
1744
|
+
|
1689
1745
|
blur: function() {
|
1690
1746
|
if (!this.hasFocus) return;
|
1691
|
-
|
1747
|
+
|
1692
1748
|
this.$('input[type=checkbox]:focus').blur();
|
1693
1749
|
},
|
1694
1750
|
|
@@ -1705,13 +1761,13 @@ Form.editors = (function() {
|
|
1705
1761
|
_.each(array, function(option, index) {
|
1706
1762
|
var itemHtml = '<li>';
|
1707
1763
|
if (_.isObject(option)) {
|
1708
|
-
var val = option.val ? option.val : '';
|
1709
|
-
itemHtml += ('<input type="checkbox" name="'+self.id+'" value="'+val+'" id="'+self.id+'-'+index+'" />')
|
1710
|
-
itemHtml += ('<label for="'+self.id+'-'+index+'">'+option.label+'</label>')
|
1764
|
+
var val = (option.val || option.val === 0) ? option.val : '';
|
1765
|
+
itemHtml += ('<input type="checkbox" name="'+self.id+'" value="'+val+'" id="'+self.id+'-'+index+'" />');
|
1766
|
+
itemHtml += ('<label for="'+self.id+'-'+index+'">'+option.label+'</label>');
|
1711
1767
|
}
|
1712
1768
|
else {
|
1713
|
-
itemHtml += ('<input type="checkbox" name="'+self.id+'" value="'+option+'" id="'+self.id+'-'+index+'" />')
|
1714
|
-
itemHtml += ('<label for="'+self.id+'-'+index+'">'+option+'</label>')
|
1769
|
+
itemHtml += ('<input type="checkbox" name="'+self.id+'" value="'+option+'" id="'+self.id+'-'+index+'" />');
|
1770
|
+
itemHtml += ('<label for="'+self.id+'-'+index+'">'+option+'</label>');
|
1715
1771
|
}
|
1716
1772
|
itemHtml += '</li>';
|
1717
1773
|
html.push(itemHtml);
|
@@ -1726,9 +1782,9 @@ Form.editors = (function() {
|
|
1726
1782
|
|
1727
1783
|
/**
|
1728
1784
|
* OBJECT
|
1729
|
-
*
|
1785
|
+
*
|
1730
1786
|
* Creates a child form. For editing Javascript objects
|
1731
|
-
*
|
1787
|
+
*
|
1732
1788
|
* @param {Object} options
|
1733
1789
|
* @param {Object} options.schema The schema for the object
|
1734
1790
|
* @param {Object} options.schema.subSchema The schema for the nested form
|
@@ -1750,7 +1806,7 @@ Form.editors = (function() {
|
|
1750
1806
|
if (!this.schema.subSchema) throw new Error("Missing required 'schema.subSchema' option for Object editor");
|
1751
1807
|
},
|
1752
1808
|
|
1753
|
-
render: function() {
|
1809
|
+
render: function() {
|
1754
1810
|
//Create the nested form
|
1755
1811
|
this.form = new Form({
|
1756
1812
|
schema: this.schema.subSchema,
|
@@ -1762,9 +1818,9 @@ Form.editors = (function() {
|
|
1762
1818
|
this._observeFormEvents();
|
1763
1819
|
|
1764
1820
|
this.$el.html(this.form.render().el);
|
1765
|
-
|
1821
|
+
|
1766
1822
|
if (this.hasFocus) this.trigger('blur', this);
|
1767
|
-
|
1823
|
+
|
1768
1824
|
return this;
|
1769
1825
|
},
|
1770
1826
|
|
@@ -1773,22 +1829,22 @@ Form.editors = (function() {
|
|
1773
1829
|
|
1774
1830
|
return this.value;
|
1775
1831
|
},
|
1776
|
-
|
1832
|
+
|
1777
1833
|
setValue: function(value) {
|
1778
1834
|
this.value = value;
|
1779
|
-
|
1835
|
+
|
1780
1836
|
this.render();
|
1781
1837
|
},
|
1782
|
-
|
1838
|
+
|
1783
1839
|
focus: function() {
|
1784
1840
|
if (this.hasFocus) return;
|
1785
|
-
|
1841
|
+
|
1786
1842
|
this.form.focus();
|
1787
1843
|
},
|
1788
|
-
|
1844
|
+
|
1789
1845
|
blur: function() {
|
1790
1846
|
if (!this.hasFocus) return;
|
1791
|
-
|
1847
|
+
|
1792
1848
|
this.form.blur();
|
1793
1849
|
},
|
1794
1850
|
|
@@ -1797,19 +1853,19 @@ Form.editors = (function() {
|
|
1797
1853
|
|
1798
1854
|
Backbone.View.prototype.remove.call(this);
|
1799
1855
|
},
|
1800
|
-
|
1856
|
+
|
1801
1857
|
validate: function() {
|
1802
1858
|
return this.form.validate();
|
1803
1859
|
},
|
1804
|
-
|
1860
|
+
|
1805
1861
|
_observeFormEvents: function() {
|
1806
1862
|
this.form.on('all', function() {
|
1807
1863
|
// args = ["key:change", form, fieldEditor]
|
1808
|
-
args = _.toArray(arguments);
|
1864
|
+
var args = _.toArray(arguments);
|
1809
1865
|
args[1] = this;
|
1810
1866
|
// args = ["key:change", this=objectEditor, fieldEditor]
|
1811
|
-
|
1812
|
-
this.trigger.apply(this, args)
|
1867
|
+
|
1868
|
+
this.trigger.apply(this, args);
|
1813
1869
|
}, this);
|
1814
1870
|
}
|
1815
1871
|
|
@@ -1819,9 +1875,9 @@ Form.editors = (function() {
|
|
1819
1875
|
|
1820
1876
|
/**
|
1821
1877
|
* NESTED MODEL
|
1822
|
-
*
|
1878
|
+
*
|
1823
1879
|
* Creates a child form. For editing nested Backbone models
|
1824
|
-
*
|
1880
|
+
*
|
1825
1881
|
* Special options:
|
1826
1882
|
* schema.model: Embedded model constructor
|
1827
1883
|
*/
|
@@ -1839,9 +1895,7 @@ Form.editors = (function() {
|
|
1839
1895
|
nestedModel = this.schema.model;
|
1840
1896
|
|
1841
1897
|
//Wrap the data in a model if it isn't already a model instance
|
1842
|
-
var modelInstance = (data.constructor
|
1843
|
-
? data
|
1844
|
-
: new nestedModel(data);
|
1898
|
+
var modelInstance = (data.constructor === nestedModel) ? data : new nestedModel(data);
|
1845
1899
|
|
1846
1900
|
this.form = new Form({
|
1847
1901
|
model: modelInstance,
|
@@ -1853,7 +1907,7 @@ Form.editors = (function() {
|
|
1853
1907
|
|
1854
1908
|
//Render form
|
1855
1909
|
this.$el.html(this.form.render().el);
|
1856
|
-
|
1910
|
+
|
1857
1911
|
if (this.hasFocus) this.trigger('blur', this);
|
1858
1912
|
|
1859
1913
|
return this;
|
@@ -1912,12 +1966,12 @@ Form.editors = (function() {
|
|
1912
1966
|
},
|
1913
1967
|
|
1914
1968
|
initialize: function(options) {
|
1915
|
-
options = options || {}
|
1969
|
+
options = options || {};
|
1916
1970
|
|
1917
1971
|
editors.Base.prototype.initialize.call(this, options);
|
1918
1972
|
|
1919
1973
|
var Self = editors.Date,
|
1920
|
-
today = new Date;
|
1974
|
+
today = new Date();
|
1921
1975
|
|
1922
1976
|
//Option defaults
|
1923
1977
|
this.options = _.extend({
|
@@ -1930,18 +1984,18 @@ Form.editors = (function() {
|
|
1930
1984
|
yearStart: today.getFullYear() - 100,
|
1931
1985
|
yearEnd: today.getFullYear()
|
1932
1986
|
}, options.schema || {});
|
1933
|
-
|
1987
|
+
|
1934
1988
|
//Cast to Date
|
1935
1989
|
if (this.value && !_.isDate(this.value)) {
|
1936
1990
|
this.value = new Date(this.value);
|
1937
1991
|
}
|
1938
|
-
|
1992
|
+
|
1939
1993
|
//Set default date
|
1940
1994
|
if (!this.value) {
|
1941
1995
|
var date = new Date();
|
1942
1996
|
date.setSeconds(0);
|
1943
1997
|
date.setMilliseconds(0);
|
1944
|
-
|
1998
|
+
|
1945
1999
|
this.value = date;
|
1946
2000
|
}
|
1947
2001
|
},
|
@@ -1959,12 +2013,15 @@ Form.editors = (function() {
|
|
1959
2013
|
return '<option value="'+month+'">' + value + '</option>';
|
1960
2014
|
});
|
1961
2015
|
|
1962
|
-
var
|
2016
|
+
var yearRange = schema.yearStart < schema.yearEnd ?
|
2017
|
+
_.range(schema.yearStart, schema.yearEnd + 1) :
|
2018
|
+
_.range(schema.yearStart, schema.yearEnd - 1, -1);
|
2019
|
+
var yearsOptions = _.map(yearRange, function(year) {
|
1963
2020
|
return '<option value="'+year+'">' + year + '</option>';
|
1964
2021
|
});
|
1965
2022
|
|
1966
2023
|
//Render the selects
|
1967
|
-
var $el =
|
2024
|
+
var $el = Form.helpers.parseHTML(Form.templates.date({
|
1968
2025
|
dates: datesOptions.join(''),
|
1969
2026
|
months: monthsOptions.join(''),
|
1970
2027
|
years: yearsOptions.join('')
|
@@ -1985,7 +2042,7 @@ Form.editors = (function() {
|
|
1985
2042
|
//Remove the wrapper tag
|
1986
2043
|
this.setElement($el);
|
1987
2044
|
this.$el.attr('id', this.id);
|
1988
|
-
|
2045
|
+
|
1989
2046
|
if (this.hasFocus) this.trigger('blur', this);
|
1990
2047
|
|
1991
2048
|
return this;
|
@@ -2003,7 +2060,7 @@ Form.editors = (function() {
|
|
2003
2060
|
|
2004
2061
|
return new Date(year, month, date);
|
2005
2062
|
},
|
2006
|
-
|
2063
|
+
|
2007
2064
|
/**
|
2008
2065
|
* @param {Date} date
|
2009
2066
|
*/
|
@@ -2014,16 +2071,16 @@ Form.editors = (function() {
|
|
2014
2071
|
|
2015
2072
|
this.updateHidden();
|
2016
2073
|
},
|
2017
|
-
|
2074
|
+
|
2018
2075
|
focus: function() {
|
2019
2076
|
if (this.hasFocus) return;
|
2020
|
-
|
2077
|
+
|
2021
2078
|
this.$('select').first().focus();
|
2022
2079
|
},
|
2023
|
-
|
2080
|
+
|
2024
2081
|
blur: function() {
|
2025
2082
|
if (!this.hasFocus) return;
|
2026
|
-
|
2083
|
+
|
2027
2084
|
this.$('select:focus').blur();
|
2028
2085
|
},
|
2029
2086
|
|
@@ -2052,7 +2109,7 @@ Form.editors = (function() {
|
|
2052
2109
|
|
2053
2110
|
/**
|
2054
2111
|
* DATETIME
|
2055
|
-
*
|
2112
|
+
*
|
2056
2113
|
* @param {Editor} [options.DateEditor] Date editor view to use (not definition)
|
2057
2114
|
* @param {Number} [options.schema.minsInterval] Interval between minutes. Default: 15
|
2058
2115
|
*/
|
@@ -2100,7 +2157,7 @@ Form.editors = (function() {
|
|
2100
2157
|
|
2101
2158
|
render: function() {
|
2102
2159
|
function pad(n) {
|
2103
|
-
return n < 10 ? '0' + n : n
|
2160
|
+
return n < 10 ? '0' + n : n;
|
2104
2161
|
}
|
2105
2162
|
|
2106
2163
|
var schema = this.schema;
|
@@ -2115,7 +2172,7 @@ Form.editors = (function() {
|
|
2115
2172
|
});
|
2116
2173
|
|
2117
2174
|
//Render time selects
|
2118
|
-
var $el =
|
2175
|
+
var $el = Form.helpers.parseHTML(Form.templates.dateTime({
|
2119
2176
|
date: '<b class="bbf-tmp"></b>',
|
2120
2177
|
hours: hoursOptions.join(),
|
2121
2178
|
mins: minsOptions.join()
|
@@ -2130,13 +2187,13 @@ Form.editors = (function() {
|
|
2130
2187
|
|
2131
2188
|
//Get the hidden date field to store values in case POSTed to server
|
2132
2189
|
this.$hidden = $el.find('input[type="hidden"]');
|
2133
|
-
|
2190
|
+
|
2134
2191
|
//Set time
|
2135
2192
|
this.setValue(this.value);
|
2136
2193
|
|
2137
2194
|
this.setElement($el);
|
2138
2195
|
this.$el.attr('id', this.id);
|
2139
|
-
|
2196
|
+
|
2140
2197
|
if (this.hasFocus) this.trigger('blur', this);
|
2141
2198
|
|
2142
2199
|
return this;
|
@@ -2158,27 +2215,27 @@ Form.editors = (function() {
|
|
2158
2215
|
|
2159
2216
|
return date;
|
2160
2217
|
},
|
2161
|
-
|
2218
|
+
|
2162
2219
|
setValue: function(date) {
|
2163
2220
|
if (!_.isDate(date)) date = new Date(date);
|
2164
|
-
|
2221
|
+
|
2165
2222
|
this.dateEditor.setValue(date);
|
2166
|
-
|
2223
|
+
|
2167
2224
|
this.$hour.val(date.getHours());
|
2168
2225
|
this.$min.val(date.getMinutes());
|
2169
2226
|
|
2170
2227
|
this.updateHidden();
|
2171
2228
|
},
|
2172
|
-
|
2229
|
+
|
2173
2230
|
focus: function() {
|
2174
2231
|
if (this.hasFocus) return;
|
2175
|
-
|
2232
|
+
|
2176
2233
|
this.$('select').first().focus();
|
2177
2234
|
},
|
2178
|
-
|
2235
|
+
|
2179
2236
|
blur: function() {
|
2180
2237
|
if (!this.hasFocus) return;
|
2181
|
-
|
2238
|
+
|
2182
2239
|
this.$('select:focus').blur();
|
2183
2240
|
},
|
2184
2241
|
|
@@ -2243,6 +2300,7 @@ Form.editors = (function() {
|
|
2243
2300
|
<label for="{{id}}">{{title}}</label>\
|
2244
2301
|
<div class="bbf-editor">{{editor}}</div>\
|
2245
2302
|
<div class="bbf-help">{{help}}</div>\
|
2303
|
+
<div class="bbf-error">{{error}}</div>\
|
2246
2304
|
</li>\
|
2247
2305
|
',
|
2248
2306
|
|
@@ -2251,6 +2309,7 @@ Form.editors = (function() {
|
|
2251
2309
|
<label for="{{id}}">{{title}}</label>\
|
2252
2310
|
<div class="bbf-editor">{{editor}}</div>\
|
2253
2311
|
<div class="bbf-help">{{help}}</div>\
|
2312
|
+
<div class="bbf-error">{{error}}</div>\
|
2254
2313
|
</li>\
|
2255
2314
|
',
|
2256
2315
|
|
@@ -2300,7 +2359,7 @@ Form.editors = (function() {
|
|
2300
2359
|
|
2301
2360
|
|
2302
2361
|
//Metadata
|
2303
|
-
Form.VERSION = '0.
|
2362
|
+
Form.VERSION = '0.11.0';
|
2304
2363
|
|
2305
2364
|
|
2306
2365
|
//Exports
|