Browse files

Build

  • Loading branch information...
1 parent 1f6622b commit 498713535383db3616e14eaee75cf64dc7ec2989 @powmedia committed Mar 8, 2013
View
7 distribution.amd/backbone-forms.js
@@ -1506,7 +1506,12 @@ Form.editors = (function() {
}
else if (_.isFunction(options)) {
- options(function(opts) { newOptions = opts; }, this);
+ var newOptions;
+
+ options(function(opts) {
+ newOptions = opts;
+ }, this);
+
html = this._getOptionsHtml(newOptions);
}
View
2 distribution.amd/backbone-forms.min.js
@@ -1 +1 @@
-define(["jquery","underscore","backbone"],function(e,t,n){var r=function(){return n.View.extend({hasFocus:!1,initialize:function(e){if(!r.templates.form)throw new Error("Templates not loaded");this.schema=function(){if(e.schema)return e.schema;var n=e.model;if(!n)throw new Error("Could not find schema");return t.isFunction(n.schema)?n.schema():n.schema}(),e=t.extend({template:"form",fieldsetTemplate:"fieldset",fieldTemplate:"field"},e);if(!e.fieldsets){var n=e.fields||t.keys(this.schema);e.fieldsets=[{fields:n}]}this.options=e,this.model=e.model,this.data=e.data,this.fields={}},render:function(){var n=this,i=this.options,s=r.templates[i.template],o=r.helpers.parseHTML(s({fieldsets:'<b class="bbf-tmp"></b>'})),u=e(".bbf-tmp",o);return t.each(i.fieldsets,function(e){u.append(n.renderFieldset(e))}),u.children().unwrap(),this.setElement(o),this.hasFocus&&this.trigger("blur",this),this},renderFieldset:function(n){var i=this,s=r.templates[this.options.fieldsetTemplate],o=this.schema,u=r.helpers.getNested;t.isArray(n)&&(n={fields:n});var a=r.helpers.parseHTML(s(t.extend({},n,{legend:'<b class="bbf-tmp-legend"></b>',fields:'<b class="bbf-tmp-fields"></b>'})));n.legend?a.find(".bbf-tmp-legend").replaceWith(n.legend):a.find(".bbf-tmp-legend").parent().remove();var f=e(".bbf-tmp-fields",a);return t.each(n.fields,function(e){var n=function(){if(o[e])return o[e];var t=e.replace(/\./g,".subSchema.");return u(o,t)}();if(!n)throw"Field '"+e+"' not found in schema";var r=i.fields[e]=i.createField(e,n),s=r.render().el;r.editor.on("all",function(n){var r=t.toArray(arguments);r[0]=e+":"+n,r.splice(1,0,this),this.trigger.apply(this,r)},i),r.editor.on("change",function(){this.trigger("change",i)},i),r.editor.on("focus",function(){if(this.hasFocus)return;this.trigger("focus",this)},i),r.editor.on("blur",function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(t.find(e.fields,function(e){return e.editor.hasFocus}))return;e.trigger("blur",e)},0)},i),n.type!=="Hidden"&&f.append(s)}),f=f.children().unwrap(),a},createField:function(e,t){t.template=t.template||this.options.fieldTemplate;var n={form:this,key:e,schema:t,idPrefix:this.options.idPrefix,template:this.options.fieldTemplate};return this.model?n.model=this.model:this.data?n.value=this.data[e]:n.value=null,new r.Field(n)},validate:function(){var e=this,n=this.fields,r=this.model,i={};t.each(n,function(e){var t=e.validate();t&&(i[e.key]=t)});if(r&&r.validate){var s=r.validate(this.getValue());if(s){var o=t.isObject(s)&&!t.isArray(s);o||(i._others=i._others||[],i._others.push(s)),o&&t.each(s,function(t,n){if(e.fields[n]&&!i[n])e.fields[n].setError(t),i[n]=t;else{i._others=i._others||[];var r={};r[n]=t,i._others.push(r)}})}}return t.isEmpty(i)?null:i},commit:function(e){var n=this.validate();if(n)return n;var r,i=t.extend({error:function(e,t){r=t}},e);this.model.set(this.getValue(),i);if(r)return r},getValue:function(e){if(e)return this.fields[e].getValue();var n={};return t.each(this.fields,function(e){n[e.key]=e.getValue()}),n},setValue:function(e,t){var n={};typeof e=="string"?n[e]=t:n=e;var r;for(r in this.schema)n[r]!==undefined&&this.fields[r].setValue(n[r])},focus:function(){if(this.hasFocus)return;var e=this.options.fieldsets[0];if(e){var n;t.isArray(e)?n=e[0]:n=e.fields[0],n&&this.fields[n].editor.focus()}},blur:function(){if(!this.hasFocus)return;var e=t.find(this.fields,function(e){return e.editor.hasFocus});e&&e.editor.blur()},remove:function(){var e=this.fields;for(var t in e)e[t].remove();n.View.prototype.remove.call(this)},trigger:function(e){return e==="focus"?this.hasFocus=!0:e==="blur"&&(this.hasFocus=!1),n.View.prototype.trigger.apply(this,arguments)}})}();return r.helpers=function(){var n={};return n.getNested=function(e,t){var n=t.split("."),r=e;for(var i=0,s=n.length;i<s;i++)r=r[n[i]];return r},n.keyToTitle=function(e){return e=e.replace(/([A-Z])/g," $1"),e=e.replace(/^./,function(e){return e.toUpperCase()}),e},n.compileTemplate=function(e){var n=t.templateSettings.interpolate;t.templateSettings.interpolate=/\{\{(.+?)\}\}/g;var r=t.template(e);return t.templateSettings.interpolate=n,r},n.createTemplate=function(t,r){var i=n.compileTemplate(e.trim(t));return r?i(r):i},n.setTemplateCompiler=function(e){n.compileTemplate=e},n.setTemplates=function(e,i){var s=n.createTemplate;r.templates=r.templates||{},r.classNames=r.classNames||{},t.each(e,function(e,n,i){t.isString(e)&&(e=s(e)),r.templates[n]=e}),t.extend(r.classNames,i)},n.createEditor=function(e,n){var i;return t.isString(e)?i=r.editors[e]:i=e,new i(n)},n.getValidator=function(e){var n=r.validators;if(t.isRegExp(e))return n.regexp({regexp:e});if(t.isString(e)){if(!n[e])throw new Error('Validator "'+e+'" not found');return n[e]()}if(t.isFunction(e))return e;if(t.isObject(e)&&e.type){var i=e;return n[i.type](i)}throw new Error("Invalid validator: "+e)},n.parseHTML=function(t){return e.parseHTML!==undefined?e(e.parseHTML(t)):e(t)},n}(),r.validators=function(){var e={};return e.errMessages={required:"Required",regexp:"Invalid",email:"Invalid email address",url:"Invalid URL",match:'Must match field "{{field}}"'},e.required=function(e){return e=t.extend({type:"required",message:this.errMessages.required},e),function(n){e.value=n;var i={type:e.type,message:r.helpers.createTemplate(e.message,e)};if(n===null||n===undefined||n===!1||n==="")return i}},e.regexp=function(e){if(!e.regexp)throw new Error('Missing required "regexp" option for "regexp" validator');return e=t.extend({type:"regexp",message:this.errMessages.regexp},e),function(n){e.value=n;var i={type:e.type,message:r.helpers.createTemplate(e.message,e)};if(n===null||n===undefined||n==="")return;if(!e.regexp.test(n))return i}},e.email=function(n){return n=t.extend({type:"email",message:this.errMessages.email,regexp:/^[\w\-]{1,}([\w\-\+.]{1,1}[\w\-]{1,}){0,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/},n),e.regexp(n)},e.url=function(n){return n=t.extend({type:"url",message:this.errMessages.url,regexp:/^(http|https):\/\/(([A-Z0-9][A-Z0-9_\-]*)(\.[A-Z0-9][A-Z0-9_\-]*)+)(:(\d+))?\/?/i},n),e.regexp(n)},e.match=function(e){if(!e.field)throw new Error('Missing required "field" options for "match" validator');return e=t.extend({type:"match",message:this.errMessages.match},e),function(n,i){e.value=n;var s={type:e.type,message:r.helpers.createTemplate(e.message,e)};if(n===null||n===undefined||n==="")return;if(n!==i[e.field])return s}},e}(),r.Field=function(){var i=r.helpers,s=r.templates;return n.View.extend({initialize:function(e){e=e||{},this.form=e.form,this.key=e.key,this.value=e.value,this.model=e.model,t.isString(e.schema)&&(e.schema={type:e.schema}),this.schema=t.extend({type:"Text",title:i.keyToTitle(this.key),template:"field"},e.schema)},renderingContext:function(e,t){return{key:this.key,title:e.title,id:t.id,type:e.type,editor:'<b class="bbf-tmp-editor"></b>',help:'<b class="bbf-tmp-help"></b>',error:'<b class="bbf-tmp-error"></b>'}},render:function(){var t=this.schema,n=r.templates,s={form:this.form,key:this.key,schema:t,idPrefix:this.options.idPrefix,id:this.getId()};this.model?s.model=this.model:s.value=this.value;var o=this.editor=i.createEditor(t.type,s),u=r.helpers.parseHTML(n[t.template](this.renderingContext(t,o)));return t.title===!1&&u.find('label[for="'+o.id+'"]').first().remove(),u.find(".bbf-tmp-editor").replaceWith(o.render().el),this.$help=e(".bbf-tmp-help",u).parent(),this.$help.empty(),this.schema.help&&this.$help.html(this.schema.help),this.$error=e(e(".bbf-tmp-error",u).parent()[0]),this.$error&&this.$error.empty(),this.schema.fieldClass&&u.addClass(this.schema.fieldClass),this.schema.fieldAttrs&&u.attr(this.schema.fieldAttrs),this.setElement(u),this},getId:function(){var e=this.options.idPrefix,n=this.key;return n=n.replace(/\./g,"_"),t.isString(e)||t.isNumber(e)?e+n:t.isNull(e)?n:this.model?this.model.cid+"_"+n:n},validate:function(){var e=this.editor.validate();return e?this.setError(e.message):this.clearError(),e},setError:function(e){if(this.editor.hasNestedForm)return;var t=r.classNames.error;this.$el.addClass(t),this.$error?this.$error.html(e):this.$help&&this.$help.html(e)},clearError:function(){var e=r.classNames.error;this.$el.removeClass(e);if(this.$error)this.$error.empty();else if(this.$help){this.$help.empty();var t=this.schema.help;t&&this.$help.html(t)}},commit:function(){return this.editor.commit()},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(),n.View.prototype.remove.call(this)}})}(),r.editors=function(){var i=r.helpers,s={};return s.Base=n.View.extend({defaultValue:null,hasFocus:!1,initialize:function(e){var e=e||{};if(e.model){if(!e.key)throw"Missing option: 'key'";this.model=e.model,this.value=this.model.get(e.key)}else e.value&&(this.value=e.value);this.value===undefined&&(this.value=this.defaultValue),this.key=e.key,this.form=e.form,this.schema=e.schema||{},this.validators=e.validators||this.schema.validators,this.$el.attr("name",this.getName()),this.schema.editorClass&&this.$el.addClass(this.schema.editorClass),this.schema.editorAttrs&&this.$el.attr(this.schema.editorAttrs)},getValue:function(){throw"Not implemented. Extend and override this method."},setValue:function(){throw"Not implemented. Extend and override this method."},focus:function(){throw"Not implemented. Extend and override this method."},blur:function(){throw"Not implemented. Extend and override this method."},getName:function(){var e=this.key||"";return e.replace(/\./g,"_")},commit:function(e){var t=this.validate();if(t)return t;this.listenTo(this.model,"invalid",function(e,n){t=n}),this.model.set(this.key,this.getValue(),e);if(t)return t},validate:function(){var e=this.$el,n=null,i=this.getValue(),s=this.form?this.form.getValue():{},o=this.validators,u=r.helpers.getValidator;return o&&t.every(o,function(e){return n=u(e)(i,s),n?!1:!0}),n},trigger:function(e){return e==="focus"?this.hasFocus=!0:e==="blur"&&(this.hasFocus=!1),n.View.prototype.trigger.apply(this,arguments)}}),s.Text=s.Base.extend({tagName:"input",defaultValue:"",previousValue:"",events:{keyup:"determineChange",keypress:function(e){var t=this;setTimeout(function(){t.determineChange()},0)},select:function(e){this.trigger("select",this)},focus:function(e){this.trigger("focus",this)},blur:function(e){this.trigger("blur",this)}},initialize:function(e){s.Base.prototype.initialize.call(this,e);var t=this.schema,n="text";t&&t.editorAttrs&&t.editorAttrs.type&&(n=t.editorAttrs.type),t&&t.dataType&&(n=t.dataType),this.$el.attr("type",n)},render:function(){return this.setValue(this.value),this},determineChange:function(e){var t=this.$el.val(),n=t!==this.previousValue;n&&(this.previousValue=t,this.trigger("change",this))},getValue:function(){return this.$el.val()},setValue:function(e){this.$el.val(e)},focus:function(){if(this.hasFocus)return;this.$el.focus()},blur:function(){if(!this.hasFocus)return;this.$el.blur()},select:function(){this.$el.select()}}),s.Number=s.Text.extend({defaultValue:0,events:t.extend({},s.Text.prototype.events,{keypress:"onKeyPress"}),initialize:function(e){s.Text.prototype.initialize.call(this,e),this.$el.attr("type","number"),this.$el.attr("step","any")},onKeyPress:function(e){var t=this,n=function(){setTimeout(function(){t.determineChange()},0)};if(e.charCode===0){n();return}var r=this.$el.val()+String.fromCharCode(e.charCode),i=/^[0-9]*\.?[0-9]*?$/.test(r);i?n():e.preventDefault()},getValue:function(){var e=this.$el.val();return e===""?null:parseFloat(e,10)},setValue:function(e){e=function(){return t.isNumber(e)?e:t.isString(e)&&e!==""?parseFloat(e,10):null}(),t.isNaN(e)&&(e=null),s.Text.prototype.setValue.call(this,e)}}),s.Password=s.Text.extend({initialize:function(e){s.Text.prototype.initialize.call(this,e),this.$el.attr("type","password")}}),s.TextArea=s.Text.extend({tagName:"textarea"}),s.Checkbox=s.Base.extend({defaultValue:!1,tagName:"input",events:{click:function(e){this.trigger("change",this)},focus:function(e){this.trigger("focus",this)},blur:function(e){this.trigger("blur",this)}},initialize:function(e){s.Base.prototype.initialize.call(this,e),this.$el.attr("type","checkbox")},render:function(){return this.setValue(this.value),this},getValue:function(){return this.$el.prop("checked")},setValue:function(e){e&&this.$el.prop("checked",!0)},focus:function(){if(this.hasFocus)return;this.$el.focus()},blur:function(){if(!this.hasFocus)return;this.$el.blur()}}),s.Hidden=s.Base.extend({defaultValue:"",initialize:function(e){s.Text.prototype.initialize.call(this,e),this.$el.attr("type","hidden")},getValue:function(){return this.value},setValue:function(e){this.value=e},focus:function(){},blur:function(){}}),s.Select=s.Base.extend({tagName:"select",events:{change:function(e){this.trigger("change",this)},focus:function(e){this.trigger("focus",this)},blur:function(e){this.trigger("blur",this)}},initialize:function(e){s.Base.prototype.initialize.call(this,e);if(!this.schema||!this.schema.options)throw"Missing required 'schema.options'"},render:function(){return this.setOptions(this.schema.options),this},setOptions:function(e){var r=this;if(e instanceof n.Collection){var i=e;i.length>0?this.renderOptions(e):i.fetch({success:function(t){r.renderOptions(e)}})}else t.isFunction(e)?e(function(e){r.renderOptions(e)},r):this.renderOptions(e)},renderOptions:function(e){var t=this.$el,n;n=this._getOptionsHtml(e),t.html(n),this.setValue(this.value)},_getOptionsHtml:function(e){var r;return t.isString(e)?r=e:t.isArray(e)?r=this._arrayToHtml(e):e instanceof n.Collection?r=this._collectionToHtml(e):t.isFunction(e)&&(e(function(e){newOptions=e},this),r=this._getOptionsHtml(newOptions)),r},getValue:function(){return this.$el.val()},setValue:function(e){this.$el.val(e)},focus:function(){if(this.hasFocus)return;this.$el.focus()},blur:function(){if(!this.hasFocus)return;this.$el.blur()},_collectionToHtml:function(e){var t=[];e.each(function(e){t.push({val:e.id,label:e.toString()})});var n=this._arrayToHtml(t);return n},_arrayToHtml:function(e){var n=[];return t.each(e,function(e){if(t.isObject(e))if(e.group)n.push('<optgroup label="'+e.group+'">'),n.push(this._getOptionsHtml(e.options)),n.push("</optgroup>");else{var r=e.val||e.val===0?e.val:"";n.push('<option value="'+r+'">'+e.label+"</option>")}else n.push("<option>"+e+"</option>")},this),n.join("")}}),s.Radio=s.Select.extend({tagName:"ul",className:"bbf-radio",events:{"change input[type=radio]":function(){this.trigger("change",this)},"focus input[type=radio]":function(){if(this.hasFocus)return;this.trigger("focus",this)},"blur input[type=radio]":function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(e.$("input[type=radio]:focus")[0])return;e.trigger("blur",e)},0)}},getValue:function(){return this.$("input[type=radio]:checked").val()},setValue:function(e){this.$("input[type=radio]").val([e])},focus:function(){if(this.hasFocus)return;var e=this.$("input[type=radio]:checked");if(e[0]){e.focus();return}this.$("input[type=radio]").first().focus()},blur:function(){if(!this.hasFocus)return;this.$("input[type=radio]:focus").blur()},_arrayToHtml:function(e){var n=[],r=this;return t.each(e,function(e,i){var s="<li>";if(t.isObject(e)){var o=e.val||e.val===0?e.val:"";s+='<input type="radio" name="'+r.id+'" value="'+o+'" id="'+r.id+"-"+i+'" />',s+='<label for="'+r.id+"-"+i+'">'+e.label+"</label>"}else s+='<input type="radio" name="'+r.id+'" value="'+e+'" id="'+r.id+"-"+i+'" />',s+='<label for="'+r.id+"-"+i+'">'+e+"</label>";s+="</li>",n.push(s)}),n.join("")}}),s.Checkboxes=s.Select.extend({tagName:"ul",className:"bbf-checkboxes",events:{"click input[type=checkbox]":function(){this.trigger("change",this)},"focus input[type=checkbox]":function(){if(this.hasFocus)return;this.trigger("focus",this)},"blur input[type=checkbox]":function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(e.$("input[type=checkbox]:focus")[0])return;e.trigger("blur",e)},0)}},getValue:function(){var t=[];return this.$("input[type=checkbox]:checked").each(function(){t.push(e(this).val())}),t},setValue:function(e){t.isArray(e)||(e=[e]),this.$("input[type=checkbox]").val(e)},focus:function(){if(this.hasFocus)return;this.$("input[type=checkbox]").first().focus()},blur:function(){if(!this.hasFocus)return;this.$("input[type=checkbox]:focus").blur()},_arrayToHtml:function(e){var n=[],r=this;return t.each(e,function(e,i){var s="<li>";if(t.isObject(e)){var o=e.val||e.val===0?e.val:"";s+='<input type="checkbox" name="'+r.id+'" value="'+o+'" id="'+r.id+"-"+i+'" />',s+='<label for="'+r.id+"-"+i+'">'+e.label+"</label>"}else s+='<input type="checkbox" name="'+r.id+'" value="'+e+'" id="'+r.id+"-"+i+'" />',s+='<label for="'+r.id+"-"+i+'">'+e+"</label>";s+="</li>",n.push(s)}),n.join("")}}),s.Object=s.Base.extend({hasNestedForm:!0,className:"bbf-object",initialize:function(e){this.value={},s.Base.prototype.initialize.call(this,e);if(!this.schema.subSchema)throw new Error("Missing required 'schema.subSchema' option for Object editor")},render:function(){return this.form=new r({schema:this.schema.subSchema,data:this.value,idPrefix:this.id+"_",fieldTemplate:"nestedField"}),this._observeFormEvents(),this.$el.html(this.form.render().el),this.hasFocus&&this.trigger("blur",this),this},getValue:function(){return this.form?this.form.getValue():this.value},setValue:function(e){this.value=e,this.render()},focus:function(){if(this.hasFocus)return;this.form.focus()},blur:function(){if(!this.hasFocus)return;this.form.blur()},remove:function(){this.form.remove(),n.View.prototype.remove.call(this)},validate:function(){return this.form.validate()},_observeFormEvents:function(){this.form.on("all",function(){var e=t.toArray(arguments);e[1]=this,this.trigger.apply(this,e)},this)}}),s.NestedModel=s.Object.extend({initialize:function(e){s.Base.prototype.initialize.call(this,e);if(!e.schema.model)throw'Missing required "schema.model" option for NestedModel editor'},render:function(){var e=this.value||{},t=this.key,n=this.schema.model,i=e.constructor===n?e:new n(e);return this.form=new r({model:i,idPrefix:this.id+"_",fieldTemplate:"nestedField"}),this._observeFormEvents(),this.$el.html(this.form.render().el),this.hasFocus&&this.trigger("blur",this),this},commit:function(){var e=this.form.commit();return e?(this.$el.addClass("error"),e):s.Object.prototype.commit.call(this)}}),s.Date=s.Base.extend({events:{"change select":function(){this.updateHidden(),this.trigger("change",this)},"focus select":function(){if(this.hasFocus)return;this.trigger("focus",this)},"blur select":function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(e.$("select:focus")[0])return;e.trigger("blur",e)},0)}},initialize:function(e){e=e||{},s.Base.prototype.initialize.call(this,e);var n=s.Date,r=new Date;this.options=t.extend({monthNames:n.monthNames,showMonthNames:n.showMonthNames},e),this.schema=t.extend({yearStart:r.getFullYear()-100,yearEnd:r.getFullYear()},e.schema||{}),this.value&&!t.isDate(this.value)&&(this.value=new Date(this.value));if(!this.value){var i=new Date;i.setSeconds(0),i.setMilliseconds(0),this.value=i}},render:function(){var n=this.options,i=this.schema,s=t.map(t.range(1,32),function(e){return'<option value="'+e+'">'+e+"</option>"}),o=t.map(t.range(0,12),function(e){var t=n.showMonthNames?n.monthNames[e]:e+1;return'<option value="'+e+'">'+t+"</option>"}),u=i.yearStart<i.yearEnd?t.range(i.yearStart,i.yearEnd+1):t.range(i.yearStart,i.yearEnd-1,-1),a=t.map(u,function(e){return'<option value="'+e+'">'+e+"</option>"}),f=r.helpers.parseHTML(r.templates.date({dates:s.join(""),months:o.join(""),years:a.join("")}));return this.$date=f.find('select[data-type="date"]'),this.$month=f.find('select[data-type="month"]'),this.$year=f.find('select[data-type="year"]'),this.$hidden=e('<input type="hidden" name="'+this.key+'" />'),f.append(this.$hidden),this.setValue(this.value),this.setElement(f),this.$el.attr("id",this.id),this.hasFocus&&this.trigger("blur",this),this},getValue:function(){var e=this.$year.val(),t=this.$month.val(),n=this.$date.val();return!e||!t||!n?null:new Date(e,t,n)},setValue:function(e){this.$date.val(e.getDate()),this.$month.val(e.getMonth()),this.$year.val(e.getFullYear()),this.updateHidden()},focus:function(){if(this.hasFocus)return;this.$("select").first().focus()},blur:function(){if(!this.hasFocus)return;this.$("select:focus").blur()},updateHidden:function(){var e=this.getValue();t.isDate(e)&&(e=e.toISOString()),this.$hidden.val(e)}},{showMonthNames:!0,monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"]}),s.DateTime=s.Base.extend({events:{"change select":function(){this.updateHidden(),this.trigger("change",this)},"focus select":function(){if(this.hasFocus)return;this.trigger("focus",this)},"blur select":function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(e.$("select:focus")[0])return;e.trigger("blur",e)},0)}},initialize:function(e){e=e||{},s.Base.prototype.initialize.call(this,e),this.options=t.extend({DateEditor:s.DateTime.DateEditor},e),this.schema=t.extend({minsInterval:15},e.schema||{}),this.dateEditor=new this.options.DateEditor(e),this.value=this.dateEditor.value},render:function(){function e(e){return e<10?"0"+e:e}var n=this.schema,i=t.map(t.range(0,24),function(t){return'<option value="'+t+'">'+e(t)+"</option>"}),s=t.map(t.range(0,60,n.minsInterval),function(t){return'<option value="'+t+'">'+e(t)+"</option>"}),o=r.helpers.parseHTML(r.templates.dateTime({date:'<b class="bbf-tmp"></b>',hours:i.join(),mins:s.join()}));return o.find(".bbf-tmp").replaceWith(this.dateEditor.render().el),this.$hour=o.find('select[data-type="hour"]'),this.$min=o.find('select[data-type="min"]'),this.$hidden=o.find('input[type="hidden"]'),this.setValue(this.value),this.setElement(o),this.$el.attr("id",this.id),this.hasFocus&&this.trigger("blur",this),this},getValue:function(){var e=this.dateEditor.getValue(),t=this.$hour.val(),n=this.$min.val();return!e||!t||!n?null:(e.setHours(t),e.setMinutes(n),e)},setValue:function(e){t.isDate(e)||(e=new Date(e)),this.dateEditor.setValue(e),this.$hour.val(e.getHours()),this.$min.val(e.getMinutes()),this.updateHidden()},focus:function(){if(this.hasFocus)return;this.$("select").first().focus()},blur:function(){if(!this.hasFocus)return;this.$("select:focus").blur()},updateHidden:function(){var e=this.getValue();t.isDate(e)&&(e=e.toISOString()),this.$hidden.val(e)},remove:function(){this.dateEditor.remove(),s.Base.prototype.remove.call(this)}},{DateEditor:s.Date}),s}(),r.setTemplates=r.helpers.setTemplates,r.setTemplateCompiler=r.helpers.setTemplateCompiler,r.templates={},r.setTemplates({form:' <form class="bbf-form">{{fieldsets}}</form> ',fieldset:" <fieldset> <legend>{{legend}}</legend> <ul>{{fields}}</ul> </fieldset> ",field:' <li class="bbf-field field-{{key}}"> <label for="{{id}}">{{title}}</label> <div class="bbf-editor">{{editor}}</div> <div class="bbf-help">{{help}}</div> <div class="bbf-error">{{error}}</div> </li> ',nestedField:' <li class="bbf-field bbf-nested-field field-{{key}}" title="{{title}}"> <label for="{{id}}">{{title}}</label> <div class="bbf-editor">{{editor}}</div> <div class="bbf-help">{{help}}</div> <div class="bbf-error">{{error}}</div> </li> ',list:' <div class="bbf-list"> <ul>{{items}}</ul> <div class="bbf-actions"><button type="button" data-action="add">Add</div> </div> ',listItem:' <li> <button type="button" data-action="remove" class="bbf-remove">&times;</button> <div class="bbf-editor-container">{{editor}}</div> </li> ',date:' <div class="bbf-date"> <select data-type="date" class="bbf-date">{{dates}}</select> <select data-type="month" class="bbf-month">{{months}}</select> <select data-type="year" class="bbf-year">{{years}}</select> </div> ',dateTime:' <div class="bbf-datetime"> <div class="bbf-date-container">{{date}}</div> <select data-type="hour">{{hours}}</select> : <select data-type="min">{{mins}}</select> </div> ',"list.Modal":' <div class="bbf-list-modal"> {{summary}} </div> '},{error:"bbf-error"}),r.VERSION="0.11.0",n.Form=r,r})
+define(["jquery","underscore","backbone"],function(e,t,n){var r=function(){return n.View.extend({hasFocus:!1,initialize:function(e){if(!r.templates.form)throw new Error("Templates not loaded");this.schema=function(){if(e.schema)return e.schema;var n=e.model;if(!n)throw new Error("Could not find schema");return t.isFunction(n.schema)?n.schema():n.schema}(),e=t.extend({template:"form",fieldsetTemplate:"fieldset",fieldTemplate:"field"},e);if(!e.fieldsets){var n=e.fields||t.keys(this.schema);e.fieldsets=[{fields:n}]}this.options=e,this.model=e.model,this.data=e.data,this.fields={}},render:function(){var n=this,i=this.options,s=r.templates[i.template],o=r.helpers.parseHTML(s({fieldsets:'<b class="bbf-tmp"></b>'})),u=e(".bbf-tmp",o);return t.each(i.fieldsets,function(e){u.append(n.renderFieldset(e))}),u.children().unwrap(),this.setElement(o),this.hasFocus&&this.trigger("blur",this),this},renderFieldset:function(n){var i=this,s=r.templates[this.options.fieldsetTemplate],o=this.schema,u=r.helpers.getNested;t.isArray(n)&&(n={fields:n});var a=r.helpers.parseHTML(s(t.extend({},n,{legend:'<b class="bbf-tmp-legend"></b>',fields:'<b class="bbf-tmp-fields"></b>'})));n.legend?a.find(".bbf-tmp-legend").replaceWith(n.legend):a.find(".bbf-tmp-legend").parent().remove();var f=e(".bbf-tmp-fields",a);return t.each(n.fields,function(e){var n=function(){if(o[e])return o[e];var t=e.replace(/\./g,".subSchema.");return u(o,t)}();if(!n)throw"Field '"+e+"' not found in schema";var r=i.fields[e]=i.createField(e,n),s=r.render().el;r.editor.on("all",function(n){var r=t.toArray(arguments);r[0]=e+":"+n,r.splice(1,0,this),this.trigger.apply(this,r)},i),r.editor.on("change",function(){this.trigger("change",i)},i),r.editor.on("focus",function(){if(this.hasFocus)return;this.trigger("focus",this)},i),r.editor.on("blur",function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(t.find(e.fields,function(e){return e.editor.hasFocus}))return;e.trigger("blur",e)},0)},i),n.type!=="Hidden"&&f.append(s)}),f=f.children().unwrap(),a},createField:function(e,t){t.template=t.template||this.options.fieldTemplate;var n={form:this,key:e,schema:t,idPrefix:this.options.idPrefix,template:this.options.fieldTemplate};return this.model?n.model=this.model:this.data?n.value=this.data[e]:n.value=null,new r.Field(n)},validate:function(){var e=this,n=this.fields,r=this.model,i={};t.each(n,function(e){var t=e.validate();t&&(i[e.key]=t)});if(r&&r.validate){var s=r.validate(this.getValue());if(s){var o=t.isObject(s)&&!t.isArray(s);o||(i._others=i._others||[],i._others.push(s)),o&&t.each(s,function(t,n){if(e.fields[n]&&!i[n])e.fields[n].setError(t),i[n]=t;else{i._others=i._others||[];var r={};r[n]=t,i._others.push(r)}})}}return t.isEmpty(i)?null:i},commit:function(e){var n=this.validate();if(n)return n;var r,i=t.extend({error:function(e,t){r=t}},e);this.model.set(this.getValue(),i);if(r)return r},getValue:function(e){if(e)return this.fields[e].getValue();var n={};return t.each(this.fields,function(e){n[e.key]=e.getValue()}),n},setValue:function(e,t){var n={};typeof e=="string"?n[e]=t:n=e;var r;for(r in this.schema)n[r]!==undefined&&this.fields[r].setValue(n[r])},focus:function(){if(this.hasFocus)return;var e=this.options.fieldsets[0];if(e){var n;t.isArray(e)?n=e[0]:n=e.fields[0],n&&this.fields[n].editor.focus()}},blur:function(){if(!this.hasFocus)return;var e=t.find(this.fields,function(e){return e.editor.hasFocus});e&&e.editor.blur()},remove:function(){var e=this.fields;for(var t in e)e[t].remove();n.View.prototype.remove.call(this)},trigger:function(e){return e==="focus"?this.hasFocus=!0:e==="blur"&&(this.hasFocus=!1),n.View.prototype.trigger.apply(this,arguments)}})}();return r.helpers=function(){var n={};return n.getNested=function(e,t){var n=t.split("."),r=e;for(var i=0,s=n.length;i<s;i++)r=r[n[i]];return r},n.keyToTitle=function(e){return e=e.replace(/([A-Z])/g," $1"),e=e.replace(/^./,function(e){return e.toUpperCase()}),e},n.compileTemplate=function(e){var n=t.templateSettings.interpolate;t.templateSettings.interpolate=/\{\{(.+?)\}\}/g;var r=t.template(e);return t.templateSettings.interpolate=n,r},n.createTemplate=function(t,r){var i=n.compileTemplate(e.trim(t));return r?i(r):i},n.setTemplateCompiler=function(e){n.compileTemplate=e},n.setTemplates=function(e,i){var s=n.createTemplate;r.templates=r.templates||{},r.classNames=r.classNames||{},t.each(e,function(e,n,i){t.isString(e)&&(e=s(e)),r.templates[n]=e}),t.extend(r.classNames,i)},n.createEditor=function(e,n){var i;return t.isString(e)?i=r.editors[e]:i=e,new i(n)},n.getValidator=function(e){var n=r.validators;if(t.isRegExp(e))return n.regexp({regexp:e});if(t.isString(e)){if(!n[e])throw new Error('Validator "'+e+'" not found');return n[e]()}if(t.isFunction(e))return e;if(t.isObject(e)&&e.type){var i=e;return n[i.type](i)}throw new Error("Invalid validator: "+e)},n.parseHTML=function(t){return e.parseHTML!==undefined?e(e.parseHTML(t)):e(t)},n}(),r.validators=function(){var e={};return e.errMessages={required:"Required",regexp:"Invalid",email:"Invalid email address",url:"Invalid URL",match:'Must match field "{{field}}"'},e.required=function(e){return e=t.extend({type:"required",message:this.errMessages.required},e),function(n){e.value=n;var i={type:e.type,message:r.helpers.createTemplate(e.message,e)};if(n===null||n===undefined||n===!1||n==="")return i}},e.regexp=function(e){if(!e.regexp)throw new Error('Missing required "regexp" option for "regexp" validator');return e=t.extend({type:"regexp",message:this.errMessages.regexp},e),function(n){e.value=n;var i={type:e.type,message:r.helpers.createTemplate(e.message,e)};if(n===null||n===undefined||n==="")return;if(!e.regexp.test(n))return i}},e.email=function(n){return n=t.extend({type:"email",message:this.errMessages.email,regexp:/^[\w\-]{1,}([\w\-\+.]{1,1}[\w\-]{1,}){0,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/},n),e.regexp(n)},e.url=function(n){return n=t.extend({type:"url",message:this.errMessages.url,regexp:/^(http|https):\/\/(([A-Z0-9][A-Z0-9_\-]*)(\.[A-Z0-9][A-Z0-9_\-]*)+)(:(\d+))?\/?/i},n),e.regexp(n)},e.match=function(e){if(!e.field)throw new Error('Missing required "field" options for "match" validator');return e=t.extend({type:"match",message:this.errMessages.match},e),function(n,i){e.value=n;var s={type:e.type,message:r.helpers.createTemplate(e.message,e)};if(n===null||n===undefined||n==="")return;if(n!==i[e.field])return s}},e}(),r.Field=function(){var i=r.helpers,s=r.templates;return n.View.extend({initialize:function(e){e=e||{},this.form=e.form,this.key=e.key,this.value=e.value,this.model=e.model,t.isString(e.schema)&&(e.schema={type:e.schema}),this.schema=t.extend({type:"Text",title:i.keyToTitle(this.key),template:"field"},e.schema)},renderingContext:function(e,t){return{key:this.key,title:e.title,id:t.id,type:e.type,editor:'<b class="bbf-tmp-editor"></b>',help:'<b class="bbf-tmp-help"></b>',error:'<b class="bbf-tmp-error"></b>'}},render:function(){var t=this.schema,n=r.templates,s={form:this.form,key:this.key,schema:t,idPrefix:this.options.idPrefix,id:this.getId()};this.model?s.model=this.model:s.value=this.value;var o=this.editor=i.createEditor(t.type,s),u=r.helpers.parseHTML(n[t.template](this.renderingContext(t,o)));return t.title===!1&&u.find('label[for="'+o.id+'"]').first().remove(),u.find(".bbf-tmp-editor").replaceWith(o.render().el),this.$help=e(".bbf-tmp-help",u).parent(),this.$help.empty(),this.schema.help&&this.$help.html(this.schema.help),this.$error=e(e(".bbf-tmp-error",u).parent()[0]),this.$error&&this.$error.empty(),this.schema.fieldClass&&u.addClass(this.schema.fieldClass),this.schema.fieldAttrs&&u.attr(this.schema.fieldAttrs),this.setElement(u),this},getId:function(){var e=this.options.idPrefix,n=this.key;return n=n.replace(/\./g,"_"),t.isString(e)||t.isNumber(e)?e+n:t.isNull(e)?n:this.model?this.model.cid+"_"+n:n},validate:function(){var e=this.editor.validate();return e?this.setError(e.message):this.clearError(),e},setError:function(e){if(this.editor.hasNestedForm)return;var t=r.classNames.error;this.$el.addClass(t),this.$error?this.$error.html(e):this.$help&&this.$help.html(e)},clearError:function(){var e=r.classNames.error;this.$el.removeClass(e);if(this.$error)this.$error.empty();else if(this.$help){this.$help.empty();var t=this.schema.help;t&&this.$help.html(t)}},commit:function(){return this.editor.commit()},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(),n.View.prototype.remove.call(this)}})}(),r.editors=function(){var i=r.helpers,s={};return s.Base=n.View.extend({defaultValue:null,hasFocus:!1,initialize:function(e){var e=e||{};if(e.model){if(!e.key)throw"Missing option: 'key'";this.model=e.model,this.value=this.model.get(e.key)}else e.value&&(this.value=e.value);this.value===undefined&&(this.value=this.defaultValue),this.key=e.key,this.form=e.form,this.schema=e.schema||{},this.validators=e.validators||this.schema.validators,this.$el.attr("name",this.getName()),this.schema.editorClass&&this.$el.addClass(this.schema.editorClass),this.schema.editorAttrs&&this.$el.attr(this.schema.editorAttrs)},getValue:function(){throw"Not implemented. Extend and override this method."},setValue:function(){throw"Not implemented. Extend and override this method."},focus:function(){throw"Not implemented. Extend and override this method."},blur:function(){throw"Not implemented. Extend and override this method."},getName:function(){var e=this.key||"";return e.replace(/\./g,"_")},commit:function(e){var t=this.validate();if(t)return t;this.listenTo(this.model,"invalid",function(e,n){t=n}),this.model.set(this.key,this.getValue(),e);if(t)return t},validate:function(){var e=this.$el,n=null,i=this.getValue(),s=this.form?this.form.getValue():{},o=this.validators,u=r.helpers.getValidator;return o&&t.every(o,function(e){return n=u(e)(i,s),n?!1:!0}),n},trigger:function(e){return e==="focus"?this.hasFocus=!0:e==="blur"&&(this.hasFocus=!1),n.View.prototype.trigger.apply(this,arguments)}}),s.Text=s.Base.extend({tagName:"input",defaultValue:"",previousValue:"",events:{keyup:"determineChange",keypress:function(e){var t=this;setTimeout(function(){t.determineChange()},0)},select:function(e){this.trigger("select",this)},focus:function(e){this.trigger("focus",this)},blur:function(e){this.trigger("blur",this)}},initialize:function(e){s.Base.prototype.initialize.call(this,e);var t=this.schema,n="text";t&&t.editorAttrs&&t.editorAttrs.type&&(n=t.editorAttrs.type),t&&t.dataType&&(n=t.dataType),this.$el.attr("type",n)},render:function(){return this.setValue(this.value),this},determineChange:function(e){var t=this.$el.val(),n=t!==this.previousValue;n&&(this.previousValue=t,this.trigger("change",this))},getValue:function(){return this.$el.val()},setValue:function(e){this.$el.val(e)},focus:function(){if(this.hasFocus)return;this.$el.focus()},blur:function(){if(!this.hasFocus)return;this.$el.blur()},select:function(){this.$el.select()}}),s.Number=s.Text.extend({defaultValue:0,events:t.extend({},s.Text.prototype.events,{keypress:"onKeyPress"}),initialize:function(e){s.Text.prototype.initialize.call(this,e),this.$el.attr("type","number"),this.$el.attr("step","any")},onKeyPress:function(e){var t=this,n=function(){setTimeout(function(){t.determineChange()},0)};if(e.charCode===0){n();return}var r=this.$el.val()+String.fromCharCode(e.charCode),i=/^[0-9]*\.?[0-9]*?$/.test(r);i?n():e.preventDefault()},getValue:function(){var e=this.$el.val();return e===""?null:parseFloat(e,10)},setValue:function(e){e=function(){return t.isNumber(e)?e:t.isString(e)&&e!==""?parseFloat(e,10):null}(),t.isNaN(e)&&(e=null),s.Text.prototype.setValue.call(this,e)}}),s.Password=s.Text.extend({initialize:function(e){s.Text.prototype.initialize.call(this,e),this.$el.attr("type","password")}}),s.TextArea=s.Text.extend({tagName:"textarea"}),s.Checkbox=s.Base.extend({defaultValue:!1,tagName:"input",events:{click:function(e){this.trigger("change",this)},focus:function(e){this.trigger("focus",this)},blur:function(e){this.trigger("blur",this)}},initialize:function(e){s.Base.prototype.initialize.call(this,e),this.$el.attr("type","checkbox")},render:function(){return this.setValue(this.value),this},getValue:function(){return this.$el.prop("checked")},setValue:function(e){e&&this.$el.prop("checked",!0)},focus:function(){if(this.hasFocus)return;this.$el.focus()},blur:function(){if(!this.hasFocus)return;this.$el.blur()}}),s.Hidden=s.Base.extend({defaultValue:"",initialize:function(e){s.Text.prototype.initialize.call(this,e),this.$el.attr("type","hidden")},getValue:function(){return this.value},setValue:function(e){this.value=e},focus:function(){},blur:function(){}}),s.Select=s.Base.extend({tagName:"select",events:{change:function(e){this.trigger("change",this)},focus:function(e){this.trigger("focus",this)},blur:function(e){this.trigger("blur",this)}},initialize:function(e){s.Base.prototype.initialize.call(this,e);if(!this.schema||!this.schema.options)throw"Missing required 'schema.options'"},render:function(){return this.setOptions(this.schema.options),this},setOptions:function(e){var r=this;if(e instanceof n.Collection){var i=e;i.length>0?this.renderOptions(e):i.fetch({success:function(t){r.renderOptions(e)}})}else t.isFunction(e)?e(function(e){r.renderOptions(e)},r):this.renderOptions(e)},renderOptions:function(e){var t=this.$el,n;n=this._getOptionsHtml(e),t.html(n),this.setValue(this.value)},_getOptionsHtml:function(e){var r;if(t.isString(e))r=e;else if(t.isArray(e))r=this._arrayToHtml(e);else if(e instanceof n.Collection)r=this._collectionToHtml(e);else if(t.isFunction(e)){var i;e(function(e){i=e},this),r=this._getOptionsHtml(i)}return r},getValue:function(){return this.$el.val()},setValue:function(e){this.$el.val(e)},focus:function(){if(this.hasFocus)return;this.$el.focus()},blur:function(){if(!this.hasFocus)return;this.$el.blur()},_collectionToHtml:function(e){var t=[];e.each(function(e){t.push({val:e.id,label:e.toString()})});var n=this._arrayToHtml(t);return n},_arrayToHtml:function(e){var n=[];return t.each(e,function(e){if(t.isObject(e))if(e.group)n.push('<optgroup label="'+e.group+'">'),n.push(this._getOptionsHtml(e.options)),n.push("</optgroup>");else{var r=e.val||e.val===0?e.val:"";n.push('<option value="'+r+'">'+e.label+"</option>")}else n.push("<option>"+e+"</option>")},this),n.join("")}}),s.Radio=s.Select.extend({tagName:"ul",className:"bbf-radio",events:{"change input[type=radio]":function(){this.trigger("change",this)},"focus input[type=radio]":function(){if(this.hasFocus)return;this.trigger("focus",this)},"blur input[type=radio]":function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(e.$("input[type=radio]:focus")[0])return;e.trigger("blur",e)},0)}},getValue:function(){return this.$("input[type=radio]:checked").val()},setValue:function(e){this.$("input[type=radio]").val([e])},focus:function(){if(this.hasFocus)return;var e=this.$("input[type=radio]:checked");if(e[0]){e.focus();return}this.$("input[type=radio]").first().focus()},blur:function(){if(!this.hasFocus)return;this.$("input[type=radio]:focus").blur()},_arrayToHtml:function(e){var n=[],r=this;return t.each(e,function(e,i){var s="<li>";if(t.isObject(e)){var o=e.val||e.val===0?e.val:"";s+='<input type="radio" name="'+r.id+'" value="'+o+'" id="'+r.id+"-"+i+'" />',s+='<label for="'+r.id+"-"+i+'">'+e.label+"</label>"}else s+='<input type="radio" name="'+r.id+'" value="'+e+'" id="'+r.id+"-"+i+'" />',s+='<label for="'+r.id+"-"+i+'">'+e+"</label>";s+="</li>",n.push(s)}),n.join("")}}),s.Checkboxes=s.Select.extend({tagName:"ul",className:"bbf-checkboxes",events:{"click input[type=checkbox]":function(){this.trigger("change",this)},"focus input[type=checkbox]":function(){if(this.hasFocus)return;this.trigger("focus",this)},"blur input[type=checkbox]":function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(e.$("input[type=checkbox]:focus")[0])return;e.trigger("blur",e)},0)}},getValue:function(){var t=[];return this.$("input[type=checkbox]:checked").each(function(){t.push(e(this).val())}),t},setValue:function(e){t.isArray(e)||(e=[e]),this.$("input[type=checkbox]").val(e)},focus:function(){if(this.hasFocus)return;this.$("input[type=checkbox]").first().focus()},blur:function(){if(!this.hasFocus)return;this.$("input[type=checkbox]:focus").blur()},_arrayToHtml:function(e){var n=[],r=this;return t.each(e,function(e,i){var s="<li>";if(t.isObject(e)){var o=e.val||e.val===0?e.val:"";s+='<input type="checkbox" name="'+r.id+'" value="'+o+'" id="'+r.id+"-"+i+'" />',s+='<label for="'+r.id+"-"+i+'">'+e.label+"</label>"}else s+='<input type="checkbox" name="'+r.id+'" value="'+e+'" id="'+r.id+"-"+i+'" />',s+='<label for="'+r.id+"-"+i+'">'+e+"</label>";s+="</li>",n.push(s)}),n.join("")}}),s.Object=s.Base.extend({hasNestedForm:!0,className:"bbf-object",initialize:function(e){this.value={},s.Base.prototype.initialize.call(this,e);if(!this.schema.subSchema)throw new Error("Missing required 'schema.subSchema' option for Object editor")},render:function(){return this.form=new r({schema:this.schema.subSchema,data:this.value,idPrefix:this.id+"_",fieldTemplate:"nestedField"}),this._observeFormEvents(),this.$el.html(this.form.render().el),this.hasFocus&&this.trigger("blur",this),this},getValue:function(){return this.form?this.form.getValue():this.value},setValue:function(e){this.value=e,this.render()},focus:function(){if(this.hasFocus)return;this.form.focus()},blur:function(){if(!this.hasFocus)return;this.form.blur()},remove:function(){this.form.remove(),n.View.prototype.remove.call(this)},validate:function(){return this.form.validate()},_observeFormEvents:function(){this.form.on("all",function(){var e=t.toArray(arguments);e[1]=this,this.trigger.apply(this,e)},this)}}),s.NestedModel=s.Object.extend({initialize:function(e){s.Base.prototype.initialize.call(this,e);if(!e.schema.model)throw'Missing required "schema.model" option for NestedModel editor'},render:function(){var e=this.value||{},t=this.key,n=this.schema.model,i=e.constructor===n?e:new n(e);return this.form=new r({model:i,idPrefix:this.id+"_",fieldTemplate:"nestedField"}),this._observeFormEvents(),this.$el.html(this.form.render().el),this.hasFocus&&this.trigger("blur",this),this},commit:function(){var e=this.form.commit();return e?(this.$el.addClass("error"),e):s.Object.prototype.commit.call(this)}}),s.Date=s.Base.extend({events:{"change select":function(){this.updateHidden(),this.trigger("change",this)},"focus select":function(){if(this.hasFocus)return;this.trigger("focus",this)},"blur select":function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(e.$("select:focus")[0])return;e.trigger("blur",e)},0)}},initialize:function(e){e=e||{},s.Base.prototype.initialize.call(this,e);var n=s.Date,r=new Date;this.options=t.extend({monthNames:n.monthNames,showMonthNames:n.showMonthNames},e),this.schema=t.extend({yearStart:r.getFullYear()-100,yearEnd:r.getFullYear()},e.schema||{}),this.value&&!t.isDate(this.value)&&(this.value=new Date(this.value));if(!this.value){var i=new Date;i.setSeconds(0),i.setMilliseconds(0),this.value=i}},render:function(){var n=this.options,i=this.schema,s=t.map(t.range(1,32),function(e){return'<option value="'+e+'">'+e+"</option>"}),o=t.map(t.range(0,12),function(e){var t=n.showMonthNames?n.monthNames[e]:e+1;return'<option value="'+e+'">'+t+"</option>"}),u=i.yearStart<i.yearEnd?t.range(i.yearStart,i.yearEnd+1):t.range(i.yearStart,i.yearEnd-1,-1),a=t.map(u,function(e){return'<option value="'+e+'">'+e+"</option>"}),f=r.helpers.parseHTML(r.templates.date({dates:s.join(""),months:o.join(""),years:a.join("")}));return this.$date=f.find('select[data-type="date"]'),this.$month=f.find('select[data-type="month"]'),this.$year=f.find('select[data-type="year"]'),this.$hidden=e('<input type="hidden" name="'+this.key+'" />'),f.append(this.$hidden),this.setValue(this.value),this.setElement(f),this.$el.attr("id",this.id),this.hasFocus&&this.trigger("blur",this),this},getValue:function(){var e=this.$year.val(),t=this.$month.val(),n=this.$date.val();return!e||!t||!n?null:new Date(e,t,n)},setValue:function(e){this.$date.val(e.getDate()),this.$month.val(e.getMonth()),this.$year.val(e.getFullYear()),this.updateHidden()},focus:function(){if(this.hasFocus)return;this.$("select").first().focus()},blur:function(){if(!this.hasFocus)return;this.$("select:focus").blur()},updateHidden:function(){var e=this.getValue();t.isDate(e)&&(e=e.toISOString()),this.$hidden.val(e)}},{showMonthNames:!0,monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"]}),s.DateTime=s.Base.extend({events:{"change select":function(){this.updateHidden(),this.trigger("change",this)},"focus select":function(){if(this.hasFocus)return;this.trigger("focus",this)},"blur select":function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(e.$("select:focus")[0])return;e.trigger("blur",e)},0)}},initialize:function(e){e=e||{},s.Base.prototype.initialize.call(this,e),this.options=t.extend({DateEditor:s.DateTime.DateEditor},e),this.schema=t.extend({minsInterval:15},e.schema||{}),this.dateEditor=new this.options.DateEditor(e),this.value=this.dateEditor.value},render:function(){function e(e){return e<10?"0"+e:e}var n=this.schema,i=t.map(t.range(0,24),function(t){return'<option value="'+t+'">'+e(t)+"</option>"}),s=t.map(t.range(0,60,n.minsInterval),function(t){return'<option value="'+t+'">'+e(t)+"</option>"}),o=r.helpers.parseHTML(r.templates.dateTime({date:'<b class="bbf-tmp"></b>',hours:i.join(),mins:s.join()}));return o.find(".bbf-tmp").replaceWith(this.dateEditor.render().el),this.$hour=o.find('select[data-type="hour"]'),this.$min=o.find('select[data-type="min"]'),this.$hidden=o.find('input[type="hidden"]'),this.setValue(this.value),this.setElement(o),this.$el.attr("id",this.id),this.hasFocus&&this.trigger("blur",this),this},getValue:function(){var e=this.dateEditor.getValue(),t=this.$hour.val(),n=this.$min.val();return!e||!t||!n?null:(e.setHours(t),e.setMinutes(n),e)},setValue:function(e){t.isDate(e)||(e=new Date(e)),this.dateEditor.setValue(e),this.$hour.val(e.getHours()),this.$min.val(e.getMinutes()),this.updateHidden()},focus:function(){if(this.hasFocus)return;this.$("select").first().focus()},blur:function(){if(!this.hasFocus)return;this.$("select:focus").blur()},updateHidden:function(){var e=this.getValue();t.isDate(e)&&(e=e.toISOString()),this.$hidden.val(e)},remove:function(){this.dateEditor.remove(),s.Base.prototype.remove.call(this)}},{DateEditor:s.Date}),s}(),r.setTemplates=r.helpers.setTemplates,r.setTemplateCompiler=r.helpers.setTemplateCompiler,r.templates={},r.setTemplates({form:' <form class="bbf-form">{{fieldsets}}</form> ',fieldset:" <fieldset> <legend>{{legend}}</legend> <ul>{{fields}}</ul> </fieldset> ",field:' <li class="bbf-field field-{{key}}"> <label for="{{id}}">{{title}}</label> <div class="bbf-editor">{{editor}}</div> <div class="bbf-help">{{help}}</div> <div class="bbf-error">{{error}}</div> </li> ',nestedField:' <li class="bbf-field bbf-nested-field field-{{key}}" title="{{title}}"> <label for="{{id}}">{{title}}</label> <div class="bbf-editor">{{editor}}</div> <div class="bbf-help">{{help}}</div> <div class="bbf-error">{{error}}</div> </li> ',list:' <div class="bbf-list"> <ul>{{items}}</ul> <div class="bbf-actions"><button type="button" data-action="add">Add</div> </div> ',listItem:' <li> <button type="button" data-action="remove" class="bbf-remove">&times;</button> <div class="bbf-editor-container">{{editor}}</div> </li> ',date:' <div class="bbf-date"> <select data-type="date" class="bbf-date">{{dates}}</select> <select data-type="month" class="bbf-month">{{months}}</select> <select data-type="year" class="bbf-year">{{years}}</select> </div> ',dateTime:' <div class="bbf-datetime"> <div class="bbf-date-container">{{date}}</div> <select data-type="hour">{{hours}}</select> : <select data-type="min">{{mins}}</select> </div> ',"list.Modal":' <div class="bbf-list-modal"> {{summary}} </div> '},{error:"bbf-error"}),r.VERSION="0.11.0",n.Form=r,r})
View
112 distribution.amd/editors/list.js
@@ -373,10 +373,10 @@ define(['jquery', 'underscore', 'backbone', 'backbone-forms'], function($, _, Ba
/**
- * Modal object editor for use with the List editor.
- * To use it, set the 'itemType' property in a List schema to 'Object' or 'NestedModel'
+ * Base modal object editor for use with the List editor; used by Object
+ * and NestedModal list types
*/
- editors.List.Modal = editors.List.Object = editors.List.NestedModel = editors.Base.extend({
+ editors.List.Modal = editors.Base.extend({
events: {
'click': 'openEditor'
},
@@ -390,26 +390,9 @@ define(['jquery', 'underscore', 'backbone', 'backbone-forms'], function($, _, Ba
*/
initialize: function(options) {
editors.Base.prototype.initialize.call(this, options);
-
- var schema = this.schema;
//Dependencies
if (!editors.List.Modal.ModalAdapter) throw 'A ModalAdapter is required';
-
- //Get nested schema if Object
- if (schema.itemType === 'Object') {
- if (!schema.subSchema) throw 'Missing required option "schema.subSchema"';
-
- this.nestedSchema = schema.subSchema;
- }
-
- //Get nested schema if NestedModel
- if (schema.itemType === 'NestedModel') {
- if (!schema.model) throw 'Missing required option "schema.model"';
-
- this.nestedSchema = schema.model.prototype.schema;
- if (_.isFunction(this.nestedSchema)) this.nestedSchema = this.nestedSchema();
- }
},
/**
@@ -484,62 +467,66 @@ define(['jquery', 'underscore', 'backbone', 'backbone-forms'], function($, _, Ba
//If there's a specified toString use that
if (schema.itemToString) return schema.itemToString(value);
- //Otherwise check if it's NestedModel with it's own toString() method
- if (schema.itemType === 'NestedModel') {
- return new (schema.model)(value).toString();
- }
-
//Otherwise use the generic method or custom overridden method
return this.itemToString(value);
},
openEditor: function() {
var self = this;
- var form = new Form({
+ var form = this.modalForm = new Form({
schema: this.nestedSchema,
data: this.value
});
- var modal = this.modal = new Backbone.BootstrapModal({
+ var modal = this.modal = new editors.List.Modal.ModalAdapter({
content: form,
animate: true
- }).open();
+ });
+
+ modal.open();
this.trigger('open', this);
this.trigger('focus', this);
- modal.on('cancel', function() {
- this.modal = null;
-
- this.trigger('close', this);
- this.trigger('blur', this);
- }, this);
+ modal.on('cancel', this.onModalClosed, this);
- modal.on('ok', _.bind(this.onModalSubmitted, this, form, modal));
+ modal.on('ok', _.bind(this.onModalSubmitted, this));
},
/**
* Called when the user clicks 'OK'.
* Runs validation and tells the list when ready to add the item
*/
- onModalSubmitted: function(form, modal) {
- var isNew = !this.value;
+ onModalSubmitted: function() {
+ var modal = this.modal,
+ form = this.modalForm,
+ isNew = !this.value;
//Stop if there are validation errors
var error = form.validate();
if (error) return modal.preventClose();
- this.modal = null;
- //If OK, render the list item
+ //Store form value
this.value = form.getValue();
+ //Render item
this.renderSummary();
if (isNew) this.trigger('readyToAdd');
this.trigger('change', this);
-
+
+ this.onModalClosed();
+ },
+
+ /**
+ * Cleans up references, triggers events. To be called whenever the modal closes
+ */
+ onModalClosed: function() {
+ this.modal = null;
+ this.modalForm = null;
+
this.trigger('close', this);
this.trigger('blur', this);
},
@@ -563,7 +550,6 @@ define(['jquery', 'underscore', 'backbone', 'backbone-forms'], function($, _, Ba
if (this.modal) {
this.modal.trigger('cancel');
- this.modal.close();
}
}
}, {
@@ -578,6 +564,50 @@ define(['jquery', 'underscore', 'backbone', 'backbone-forms'], function($, _, Ba
isAsync: true
});
+
+ editors.List.Object = editors.List.Modal.extend({
+ initialize: function () {
+ editors.List.Modal.prototype.initialize.apply(this, arguments);
+
+ var schema = this.schema;
+
+ if (!schema.subSchema) throw 'Missing required option "schema.subSchema"';
+
+ this.nestedSchema = schema.subSchema;
+ }
+ });
+
+
+ editors.List.NestedModel = editors.List.Modal.extend({
+ initialize: function() {
+ editors.List.Modal.prototype.initialize.apply(this, arguments);
+
+ var schema = this.schema;
+
+ if (!schema.model) throw 'Missing required option "schema.model"';
+
+ var nestedSchema = schema.model.prototype.schema;
+
+ this.nestedSchema = (_.isFunction(nestedSchema)) ? nestedSchema() : nestedSchema;
+ },
+
+ /**
+ * Returns the string representation of the object value
+ */
+ getStringValue: function() {
+ var schema = this.schema,
+ value = this.getValue();
+
+ if (_.isEmpty(value)) return null;
+
+ //If there's a specified toString use that
+ if (schema.itemToString) return schema.itemToString(value);
+
+ //Otherwise use the model
+ return new (schema.model)(value).toString();
+ },
+ });
+
})();
View
2 distribution.amd/editors/list.min.js
@@ -1 +1 @@
-define(["jquery","underscore","backbone","backbone-forms"],function(e,t,n){(function(){var e=n.Form,r=e.editors;r.List=r.Base.extend({events:{'click [data-action="add"]':function(e){e.preventDefault(),this.addItem(null,!0)}},initialize:function(e){r.Base.prototype.initialize.call(this,e);var n=this.schema;if(!n)throw"Missing required option 'schema'";this.schema=t.extend({listTemplate:"list",listItemTemplate:"listItem"},n),this.Editor=function(){var e=n.itemType;return e?r.List[e]?r.List[e]:r[e]:r.Text}(),this.items=[]},render:function(){var n=this,r=this.value||[],i=e.helpers.parseHTML(e.templates[this.schema.listTemplate]({items:'<b class="bbf-tmp"></b>'}));return this.$list=i.find(".bbf-tmp").parent().empty(),r.length?t.each(r,function(e){n.addItem(e)}):this.Editor.isAsync||this.addItem(),this.setElement(i),this.$el.attr("id",this.id),this.$el.attr("name",this.key),this.hasFocus&&this.trigger("blur",this),this},addItem:function(e,n){var i=this,s=(new r.List.Item({list:this,schema:this.schema,value:e,Editor:this.Editor,key:this.key})).render(),o=function(){i.items.push(s),i.$list.append(s.el),s.editor.on("all",function(e){if(e==="change")return;var n=t.toArray(arguments);n[0]="item:"+e,n.splice(1,0,i),r.List.prototype.trigger.apply(this,n)},i),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)},i),s.editor.on("focus",function(){if(this.hasFocus)return;this.trigger("focus",this)},i),s.editor.on("blur",function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(t.find(e.items,function(e){return e.editor.hasFocus}))return;e.trigger("blur",e)},0)},i);if(n||e)s.addEventTriggered=!0;n&&(i.trigger("add",i,s.editor),i.trigger("change",i))};return this.Editor.isAsync?s.editor.on("readyToAdd",o,this):o(),s},removeItem:function(e){var n=this.schema.confirmDelete;if(n&&!confirm(n))return;var r=t.indexOf(this.items,e);this.items[r].remove(),this.items.splice(r,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=t.map(this.items,function(e){return e.getValue()});return t.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=t.find(this.items,function(e){return e.editor.hasFocus});e&&e.editor.blur()},remove:function(){t.invoke(this.items,"remove"),r.Base.prototype.remove.call(this)},validate:function(){if(!this.validators)return null;var e=t.map(this.items,function(e){return e.validate()}),n=t.compact(e).length?!0:!1;if(!n)return null;var r={type:"list",message:"Some of the items in the list failed validation",errors:e};return r}}),r.List.Item=n.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||r.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(),n.View.prototype.remove.call(this)},validate:function(){var n=this.getValue(),r=this.list.form?this.list.form.getValue():{},i=this.schema.validators,s=e.helpers.getValidator;if(!i)return null;var o=null;return t.every(i,function(e){return o=s(e)(n,r),o?!1:!0}),o?this.setError(o):this.clearError(),o?o: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)}}),r.List.Modal=r.List.Object=r.List.NestedModel=r.Base.extend({events:{click:"openEditor"},initialize:function(e){r.Base.prototype.initialize.call(this,e);var n=this.schema;if(!r.List.Modal.ModalAdapter)throw"A ModalAdapter is required";if(n.itemType==="Object"){if(!n.subSchema)throw'Missing required option "schema.subSchema"';this.nestedSchema=n.subSchema}if(n.itemType==="NestedModel"){if(!n.model)throw'Missing required option "schema.model"';this.nestedSchema=n.model.prototype.schema,t.isFunction(this.nestedSchema)&&(this.nestedSchema=this.nestedSchema())}},render:function(){var e=this;return t.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(n){n=n||{};var r=[];return t.each(this.nestedSchema,function(i,s){var o=i.title?i.title:e.helpers.keyToTitle(s),u=n[s];if(t.isUndefined(u)||t.isNull(u))u="";r.push(o+": "+u)}),r.join("<br />")},getStringValue:function(){var e=this.schema,n=this.getValue();return t.isEmpty(n)?"[Empty]":e.itemToString?e.itemToString(n):e.itemType==="NestedModel"?(new e.model(n)).toString():this.itemToString(n)},openEditor:function(){var r=this,i=new e({schema:this.nestedSchema,data:this.value}),s=this.modal=(new n.BootstrapModal({content:i,animate:!0})).open();this.trigger("open",this),this.trigger("focus",this),s.on("cancel",function(){this.modal=null,this.trigger("close",this),this.trigger("blur",this)},this),s.on("ok",t.bind(this.onModalSubmitted,this,i,s))},onModalSubmitted:function(e,t){var n=!this.value,r=e.validate();if(r)return t.preventClose();this.modal=null,this.value=e.getValue(),this.renderSummary(),n&&this.trigger("readyToAdd"),this.trigger("change",this),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"),this.modal.close())}},{ModalAdapter:n.BootstrapModal,isAsync:!0})})()})
+define(["jquery","underscore","backbone","backbone-forms"],function(e,t,n){(function(){var e=n.Form,r=e.editors;r.List=r.Base.extend({events:{'click [data-action="add"]':function(e){e.preventDefault(),this.addItem(null,!0)}},initialize:function(e){r.Base.prototype.initialize.call(this,e);var n=this.schema;if(!n)throw"Missing required option 'schema'";this.schema=t.extend({listTemplate:"list",listItemTemplate:"listItem"},n),this.Editor=function(){var e=n.itemType;return e?r.List[e]?r.List[e]:r[e]:r.Text}(),this.items=[]},render:function(){var n=this,r=this.value||[],i=e.helpers.parseHTML(e.templates[this.schema.listTemplate]({items:'<b class="bbf-tmp"></b>'}));return this.$list=i.find(".bbf-tmp").parent().empty(),r.length?t.each(r,function(e){n.addItem(e)}):this.Editor.isAsync||this.addItem(),this.setElement(i),this.$el.attr("id",this.id),this.$el.attr("name",this.key),this.hasFocus&&this.trigger("blur",this),this},addItem:function(e,n){var i=this,s=(new r.List.Item({list:this,schema:this.schema,value:e,Editor:this.Editor,key:this.key})).render(),o=function(){i.items.push(s),i.$list.append(s.el),s.editor.on("all",function(e){if(e==="change")return;var n=t.toArray(arguments);n[0]="item:"+e,n.splice(1,0,i),r.List.prototype.trigger.apply(this,n)},i),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)},i),s.editor.on("focus",function(){if(this.hasFocus)return;this.trigger("focus",this)},i),s.editor.on("blur",function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(t.find(e.items,function(e){return e.editor.hasFocus}))return;e.trigger("blur",e)},0)},i);if(n||e)s.addEventTriggered=!0;n&&(i.trigger("add",i,s.editor),i.trigger("change",i))};return this.Editor.isAsync?s.editor.on("readyToAdd",o,this):o(),s},removeItem:function(e){var n=this.schema.confirmDelete;if(n&&!confirm(n))return;var r=t.indexOf(this.items,e);this.items[r].remove(),this.items.splice(r,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=t.map(this.items,function(e){return e.getValue()});return t.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=t.find(this.items,function(e){return e.editor.hasFocus});e&&e.editor.blur()},remove:function(){t.invoke(this.items,"remove"),r.Base.prototype.remove.call(this)},validate:function(){if(!this.validators)return null;var e=t.map(this.items,function(e){return e.validate()}),n=t.compact(e).length?!0:!1;if(!n)return null;var r={type:"list",message:"Some of the items in the list failed validation",errors:e};return r}}),r.List.Item=n.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||r.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(),n.View.prototype.remove.call(this)},validate:function(){var n=this.getValue(),r=this.list.form?this.list.form.getValue():{},i=this.schema.validators,s=e.helpers.getValidator;if(!i)return null;var o=null;return t.every(i,function(e){return o=s(e)(n,r),o?!1:!0}),o?this.setError(o):this.clearError(),o?o: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)}}),r.List.Modal=r.Base.extend({events:{click:"openEditor"},initialize:function(e){r.Base.prototype.initialize.call(this,e);if(!r.List.Modal.ModalAdapter)throw"A ModalAdapter is required"},render:function(){var e=this;return t.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(n){n=n||{};var r=[];return t.each(this.nestedSchema,function(i,s){var o=i.title?i.title:e.helpers.keyToTitle(s),u=n[s];if(t.isUndefined(u)||t.isNull(u))u="";r.push(o+": "+u)}),r.join("<br />")},getStringValue:function(){var e=this.schema,n=this.getValue();return t.isEmpty(n)?"[Empty]":e.itemToString?e.itemToString(n):this.itemToString(n)},openEditor:function(){var n=this,i=this.modalForm=new e({schema:this.nestedSchema,data:this.value}),s=this.modal=new r.List.Modal.ModalAdapter({content:i,animate:!0});s.open(),this.trigger("open",this),this.trigger("focus",this),s.on("cancel",this.onModalClosed,this),s.on("ok",t.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:n.BootstrapModal,isAsync:!0}),r.List.Object=r.List.Modal.extend({initialize:function(){r.List.Modal.prototype.initialize.apply(this,arguments);var e=this.schema;if(!e.subSchema)throw'Missing required option "schema.subSchema"';this.nestedSchema=e.subSchema}}),r.List.NestedModel=r.List.Modal.extend({initialize:function(){r.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=t.isFunction(n)?n():n},getStringValue:function(){var e=this.schema,n=this.getValue();return t.isEmpty(n)?null:e.itemToString?e.itemToString(n):(new e.model(n)).toString()}})})()})
View
7 distribution/backbone-forms.js
@@ -1519,7 +1519,12 @@ Form.editors = (function() {
}
else if (_.isFunction(options)) {
- options(function(opts) { newOptions = opts; }, this);
+ var newOptions;
+
+ options(function(opts) {
+ newOptions = opts;
+ }, this);
+
html = this._getOptionsHtml(newOptions);
}
View
2 distribution/backbone-forms.min.js
@@ -1 +1 @@
-(function(e){if(typeof exports!="undefined"&&typeof require!="undefined")var t=e.jQuery||e.Zepto||e.ender||require("jquery"),n=e._||require("underscore"),r=e.Backbone||require("backbone");else var t=e.jQuery,n=e._,r=e.Backbone;var i=function(){return r.View.extend({hasFocus:!1,initialize:function(e){if(!i.templates.form)throw new Error("Templates not loaded");this.schema=function(){if(e.schema)return e.schema;var t=e.model;if(!t)throw new Error("Could not find schema");return n.isFunction(t.schema)?t.schema():t.schema}(),e=n.extend({template:"form",fieldsetTemplate:"fieldset",fieldTemplate:"field"},e);if(!e.fieldsets){var t=e.fields||n.keys(this.schema);e.fieldsets=[{fields:t}]}this.options=e,this.model=e.model,this.data=e.data,this.fields={}},render:function(){var e=this,r=this.options,s=i.templates[r.template],o=i.helpers.parseHTML(s({fieldsets:'<b class="bbf-tmp"></b>'})),u=t(".bbf-tmp",o);return n.each(r.fieldsets,function(t){u.append(e.renderFieldset(t))}),u.children().unwrap(),this.setElement(o),this.hasFocus&&this.trigger("blur",this),this},renderFieldset:function(e){var r=this,s=i.templates[this.options.fieldsetTemplate],o=this.schema,u=i.helpers.getNested;n.isArray(e)&&(e={fields:e});var a=i.helpers.parseHTML(s(n.extend({},e,{legend:'<b class="bbf-tmp-legend"></b>',fields:'<b class="bbf-tmp-fields"></b>'})));e.legend?a.find(".bbf-tmp-legend").replaceWith(e.legend):a.find(".bbf-tmp-legend").parent().remove();var f=t(".bbf-tmp-fields",a);return n.each(e.fields,function(e){var t=function(){if(o[e])return o[e];var t=e.replace(/\./g,".subSchema.");return u(o,t)}();if(!t)throw"Field '"+e+"' not found in schema";var i=r.fields[e]=r.createField(e,t),s=i.render().el;i.editor.on("all",function(t){var r=n.toArray(arguments);r[0]=e+":"+t,r.splice(1,0,this),this.trigger.apply(this,r)},r),i.editor.on("change",function(){this.trigger("change",r)},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(n.find(e.fields,function(e){return e.editor.hasFocus}))return;e.trigger("blur",e)},0)},r),t.type!=="Hidden"&&f.append(s)}),f=f.children().unwrap(),a},createField:function(e,t){t.template=t.template||this.options.fieldTemplate;var n={form:this,key:e,schema:t,idPrefix:this.options.idPrefix,template:this.options.fieldTemplate};return this.model?n.model=this.model:this.data?n.value=this.data[e]:n.value=null,new i.Field(n)},validate:function(){var e=this,t=this.fields,r=this.model,i={};n.each(t,function(e){var t=e.validate();t&&(i[e.key]=t)});if(r&&r.validate){var s=r.validate(this.getValue());if(s){var o=n.isObject(s)&&!n.isArray(s);o||(i._others=i._others||[],i._others.push(s)),o&&n.each(s,function(t,n){if(e.fields[n]&&!i[n])e.fields[n].setError(t),i[n]=t;else{i._others=i._others||[];var r={};r[n]=t,i._others.push(r)}})}}return n.isEmpty(i)?null:i},commit:function(e){var t=this.validate();if(t)return t;var r,i=n.extend({error:function(e,t){r=t}},e);this.model.set(this.getValue(),i);if(r)return r},getValue:function(e){if(e)return this.fields[e].getValue();var t={};return n.each(this.fields,function(e){t[e.key]=e.getValue()}),t},setValue:function(e,t){var n={};typeof e=="string"?n[e]=t:n=e;var r;for(r in this.schema)n[r]!==undefined&&this.fields[r].setValue(n[r])},focus:function(){if(this.hasFocus)return;var e=this.options.fieldsets[0];if(e){var t;n.isArray(e)?t=e[0]:t=e.fields[0],t&&this.fields[t].editor.focus()}},blur:function(){if(!this.hasFocus)return;var e=n.find(this.fields,function(e){return e.editor.hasFocus});e&&e.editor.blur()},remove:function(){var e=this.fields;for(var t in e)e[t].remove();r.View.prototype.remove.call(this)},trigger:function(e){return e==="focus"?this.hasFocus=!0:e==="blur"&&(this.hasFocus=!1),r.View.prototype.trigger.apply(this,arguments)}})}();i.helpers=function(){var e={};return e.getNested=function(e,t){var n=t.split("."),r=e;for(var i=0,s=n.length;i<s;i++)r=r[n[i]];return r},e.keyToTitle=function(e){return e=e.replace(/([A-Z])/g," $1"),e=e.replace(/^./,function(e){return e.toUpperCase()}),e},e.compileTemplate=function(e){var t=n.templateSettings.interpolate;n.templateSettings.interpolate=/\{\{(.+?)\}\}/g;var r=n.template(e);return n.templateSettings.interpolate=t,r},e.createTemplate=function(n,r){var i=e.compileTemplate(t.trim(n));return r?i(r):i},e.setTemplateCompiler=function(t){e.compileTemplate=t},e.setTemplates=function(t,r){var s=e.createTemplate;i.templates=i.templates||{},i.classNames=i.classNames||{},n.each(t,function(e,t,r){n.isString(e)&&(e=s(e)),i.templates[t]=e}),n.extend(i.classNames,r)},e.createEditor=function(e,t){var r;return n.isString(e)?r=i.editors[e]:r=e,new r(t)},e.getValidator=function(e){var t=i.validators;if(n.isRegExp(e))return t.regexp({regexp:e});if(n.isString(e)){if(!t[e])throw new Error('Validator "'+e+'" not found');return t[e]()}if(n.isFunction(e))return e;if(n.isObject(e)&&e.type){var r=e;return t[r.type](r)}throw new Error("Invalid validator: "+e)},e.parseHTML=function(e){return t.parseHTML!==undefined?t(t.parseHTML(e)):t(e)},e}(),i.validators=function(){var e={};return e.errMessages={required:"Required",regexp:"Invalid",email:"Invalid email address",url:"Invalid URL",match:'Must match field "{{field}}"'},e.required=function(e){return e=n.extend({type:"required",message:this.errMessages.required},e),function(n){e.value=n;var r={type:e.type,message:i.helpers.createTemplate(e.message,e)};if(n===null||n===undefined||n===!1||n==="")return r}},e.regexp=function(e){if(!e.regexp)throw new Error('Missing required "regexp" option for "regexp" validator');return e=n.extend({type:"regexp",message:this.errMessages.regexp},e),function(n){e.value=n;var r={type:e.type,message:i.helpers.createTemplate(e.message,e)};if(n===null||n===undefined||n==="")return;if(!e.regexp.test(n))return r}},e.email=function(t){return t=n.extend({type:"email",message:this.errMessages.email,regexp:/^[\w\-]{1,}([\w\-\+.]{1,1}[\w\-]{1,}){0,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/},t),e.regexp(t)},e.url=function(t){return t=n.extend({type:"url",message:this.errMessages.url,regexp:/^(http|https):\/\/(([A-Z0-9][A-Z0-9_\-]*)(\.[A-Z0-9][A-Z0-9_\-]*)+)(:(\d+))?\/?/i},t),e.regexp(t)},e.match=function(e){if(!e.field)throw new Error('Missing required "field" options for "match" validator');return e=n.extend({type:"match",message:this.errMessages.match},e),function(n,r){e.value=n;var s={type:e.type,message:i.helpers.createTemplate(e.message,e)};if(n===null||n===undefined||n==="")return;if(n!==r[e.field])return s}},e}(),i.Field=function(){var e=i.helpers,s=i.templates;return r.View.extend({initialize:function(t){t=t||{},this.form=t.form,this.key=t.key,this.value=t.value,this.model=t.model,n.isString(t.schema)&&(t.schema={type:t.schema}),this.schema=n.extend({type:"Text",title:e.keyToTitle(this.key),template:"field"},t.schema)},renderingContext:function(e,t){return{key:this.key,title:e.title,id:t.id,type:e.type,editor:'<b class="bbf-tmp-editor"></b>',help:'<b class="bbf-tmp-help"></b>',error:'<b class="bbf-tmp-error"></b>'}},render:function(){var n=this.schema,r=i.templates,s={form:this.form,key:this.key,schema:n,idPrefix:this.options.idPrefix,id:this.getId()};this.model?s.model=this.model:s.value=this.value;var o=this.editor=e.createEditor(n.type,s),u=i.helpers.parseHTML(r[n.template](this.renderingContext(n,o)));return n.title===!1&&u.find('label[for="'+o.id+'"]').first().remove(),u.find(".bbf-tmp-editor").replaceWith(o.render().el),this.$help=t(".bbf-tmp-help",u).parent(),this.$help.empty(),this.schema.help&&this.$help.html(this.schema.help),this.$error=t(t(".bbf-tmp-error",u).parent()[0]),this.$error&&this.$error.empty(),this.schema.fieldClass&&u.addClass(this.schema.fieldClass),this.schema.fieldAttrs&&u.attr(this.schema.fieldAttrs),this.setElement(u),this},getId:function(){var e=this.options.idPrefix,t=this.key;return t=t.replace(/\./g,"_"),n.isString(e)||n.isNumber(e)?e+t:n.isNull(e)?t:this.model?this.model.cid+"_"+t:t},validate:function(){var e=this.editor.validate();return e?this.setError(e.message):this.clearError(),e},setError:function(e){if(this.editor.hasNestedForm)return;var t=i.classNames.error;this.$el.addClass(t),this.$error?this.$error.html(e):this.$help&&this.$help.html(e)},clearError:function(){var e=i.classNames.error;this.$el.removeClass(e);if(this.$error)this.$error.empty();else if(this.$help){this.$help.empty();var t=this.schema.help;t&&this.$help.html(t)}},commit:function(){return this.editor.commit()},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(),r.View.prototype.remove.call(this)}})}(),i.editors=function(){var e=i.helpers,s={};return s.Base=r.View.extend({defaultValue:null,hasFocus:!1,initialize:function(e){var e=e||{};if(e.model){if(!e.key)throw"Missing option: 'key'";this.model=e.model,this.value=this.model.get(e.key)}else e.value&&(this.value=e.value);this.value===undefined&&(this.value=this.defaultValue),this.key=e.key,this.form=e.form,this.schema=e.schema||{},this.validators=e.validators||this.schema.validators,this.$el.attr("name",this.getName()),this.schema.editorClass&&this.$el.addClass(this.schema.editorClass),this.schema.editorAttrs&&this.$el.attr(this.schema.editorAttrs)},getValue:function(){throw"Not implemented. Extend and override this method."},setValue:function(){throw"Not implemented. Extend and override this method."},focus:function(){throw"Not implemented. Extend and override this method."},blur:function(){throw"Not implemented. Extend and override this method."},getName:function(){var e=this.key||"";return e.replace(/\./g,"_")},commit:function(e){var t=this.validate();if(t)return t;this.listenTo(this.model,"invalid",function(e,n){t=n}),this.model.set(this.key,this.getValue(),e);if(t)return t},validate:function(){var e=this.$el,t=null,r=this.getValue(),s=this.form?this.form.getValue():{},o=this.validators,u=i.helpers.getValidator;return o&&n.every(o,function(e){return t=u(e)(r,s),t?!1:!0}),t},trigger:function(e){return e==="focus"?this.hasFocus=!0:e==="blur"&&(this.hasFocus=!1),r.View.prototype.trigger.apply(this,arguments)}}),s.Text=s.Base.extend({tagName:"input",defaultValue:"",previousValue:"",events:{keyup:"determineChange",keypress:function(e){var t=this;setTimeout(function(){t.determineChange()},0)},select:function(e){this.trigger("select",this)},focus:function(e){this.trigger("focus",this)},blur:function(e){this.trigger("blur",this)}},initialize:function(e){s.Base.prototype.initialize.call(this,e);var t=this.schema,n="text";t&&t.editorAttrs&&t.editorAttrs.type&&(n=t.editorAttrs.type),t&&t.dataType&&(n=t.dataType),this.$el.attr("type",n)},render:function(){return this.setValue(this.value),this},determineChange:function(e){var t=this.$el.val(),n=t!==this.previousValue;n&&(this.previousValue=t,this.trigger("change",this))},getValue:function(){return this.$el.val()},setValue:function(e){this.$el.val(e)},focus:function(){if(this.hasFocus)return;this.$el.focus()},blur:function(){if(!this.hasFocus)return;this.$el.blur()},select:function(){this.$el.select()}}),s.Number=s.Text.extend({defaultValue:0,events:n.extend({},s.Text.prototype.events,{keypress:"onKeyPress"}),initialize:function(e){s.Text.prototype.initialize.call(this,e),this.$el.attr("type","number"),this.$el.attr("step","any")},onKeyPress:function(e){var t=this,n=function(){setTimeout(function(){t.determineChange()},0)};if(e.charCode===0){n();return}var r=this.$el.val()+String.fromCharCode(e.charCode),i=/^[0-9]*\.?[0-9]*?$/.test(r);i?n():e.preventDefault()},getValue:function(){var e=this.$el.val();return e===""?null:parseFloat(e,10)},setValue:function(e){e=function(){return n.isNumber(e)?e:n.isString(e)&&e!==""?parseFloat(e,10):null}(),n.isNaN(e)&&(e=null),s.Text.prototype.setValue.call(this,e)}}),s.Password=s.Text.extend({initialize:function(e){s.Text.prototype.initialize.call(this,e),this.$el.attr("type","password")}}),s.TextArea=s.Text.extend({tagName:"textarea"}),s.Checkbox=s.Base.extend({defaultValue:!1,tagName:"input",events:{click:function(e){this.trigger("change",this)},focus:function(e){this.trigger("focus",this)},blur:function(e){this.trigger("blur",this)}},initialize:function(e){s.Base.prototype.initialize.call(this,e),this.$el.attr("type","checkbox")},render:function(){return this.setValue(this.value),this},getValue:function(){return this.$el.prop("checked")},setValue:function(e){e&&this.$el.prop("checked",!0)},focus:function(){if(this.hasFocus)return;this.$el.focus()},blur:function(){if(!this.hasFocus)return;this.$el.blur()}}),s.Hidden=s.Base.extend({defaultValue:"",initialize:function(e){s.Text.prototype.initialize.call(this,e),this.$el.attr("type","hidden")},getValue:function(){return this.value},setValue:function(e){this.value=e},focus:function(){},blur:function(){}}),s.Select=s.Base.extend({tagName:"select",events:{change:function(e){this.trigger("change",this)},focus:function(e){this.trigger("focus",this)},blur:function(e){this.trigger("blur",this)}},initialize:function(e){s.Base.prototype.initialize.call(this,e);if(!this.schema||!this.schema.options)throw"Missing required 'schema.options'"},render:function(){return this.setOptions(this.schema.options),this},setOptions:function(e){var t=this;if(e instanceof r.Collection){var i=e;i.length>0?this.renderOptions(e):i.fetch({success:function(n){t.renderOptions(e)}})}else n.isFunction(e)?e(function(e){t.renderOptions(e)},t):this.renderOptions(e)},renderOptions:function(e){var t=this.$el,n;n=this._getOptionsHtml(e),t.html(n),this.setValue(this.value)},_getOptionsHtml:function(e){var t;return n.isString(e)?t=e:n.isArray(e)?t=this._arrayToHtml(e):e instanceof r.Collection?t=this._collectionToHtml(e):n.isFunction(e)&&(e(function(e){newOptions=e},this),t=this._getOptionsHtml(newOptions)),t},getValue:function(){return this.$el.val()},setValue:function(e){this.$el.val(e)},focus:function(){if(this.hasFocus)return;this.$el.focus()},blur:function(){if(!this.hasFocus)return;this.$el.blur()},_collectionToHtml:function(e){var t=[];e.each(function(e){t.push({val:e.id,label:e.toString()})});var n=this._arrayToHtml(t);return n},_arrayToHtml:function(e){var t=[];return n.each(e,function(e){if(n.isObject(e))if(e.group)t.push('<optgroup label="'+e.group+'">'),t.push(this._getOptionsHtml(e.options)),t.push("</optgroup>");else{var r=e.val||e.val===0?e.val:"";t.push('<option value="'+r+'">'+e.label+"</option>")}else t.push("<option>"+e+"</option>")},this),t.join("")}}),s.Radio=s.Select.extend({tagName:"ul",className:"bbf-radio",events:{"change input[type=radio]":function(){this.trigger("change",this)},"focus input[type=radio]":function(){if(this.hasFocus)return;this.trigger("focus",this)},"blur input[type=radio]":function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(e.$("input[type=radio]:focus")[0])return;e.trigger("blur",e)},0)}},getValue:function(){return this.$("input[type=radio]:checked").val()},setValue:function(e){this.$("input[type=radio]").val([e])},focus:function(){if(this.hasFocus)return;var e=this.$("input[type=radio]:checked");if(e[0]){e.focus();return}this.$("input[type=radio]").first().focus()},blur:function(){if(!this.hasFocus)return;this.$("input[type=radio]:focus").blur()},_arrayToHtml:function(e){var t=[],r=this;return n.each(e,function(e,i){var s="<li>";if(n.isObject(e)){var o=e.val||e.val===0?e.val:"";s+='<input type="radio" name="'+r.id+'" value="'+o+'" id="'+r.id+"-"+i+'" />',s+='<label for="'+r.id+"-"+i+'">'+e.label+"</label>"}else s+='<input type="radio" name="'+r.id+'" value="'+e+'" id="'+r.id+"-"+i+'" />',s+='<label for="'+r.id+"-"+i+'">'+e+"</label>";s+="</li>",t.push(s)}),t.join("")}}),s.Checkboxes=s.Select.extend({tagName:"ul",className:"bbf-checkboxes",events:{"click input[type=checkbox]":function(){this.trigger("change",this)},"focus input[type=checkbox]":function(){if(this.hasFocus)return;this.trigger("focus",this)},"blur input[type=checkbox]":function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(e.$("input[type=checkbox]:focus")[0])return;e.trigger("blur",e)},0)}},getValue:function(){var e=[];return this.$("input[type=checkbox]:checked").each(function(){e.push(t(this).val())}),e},setValue:function(e){n.isArray(e)||(e=[e]),this.$("input[type=checkbox]").val(e)},focus:function(){if(this.hasFocus)return;this.$("input[type=checkbox]").first().focus()},blur:function(){if(!this.hasFocus)return;this.$("input[type=checkbox]:focus").blur()},_arrayToHtml:function(e){var t=[],r=this;return n.each(e,function(e,i){var s="<li>";if(n.isObject(e)){var o=e.val||e.val===0?e.val:"";s+='<input type="checkbox" name="'+r.id+'" value="'+o+'" id="'+r.id+"-"+i+'" />',s+='<label for="'+r.id+"-"+i+'">'+e.label+"</label>"}else s+='<input type="checkbox" name="'+r.id+'" value="'+e+'" id="'+r.id+"-"+i+'" />',s+='<label for="'+r.id+"-"+i+'">'+e+"</label>";s+="</li>",t.push(s)}),t.join("")}}),s.Object=s.Base.extend({hasNestedForm:!0,className:"bbf-object",initialize:function(e){this.value={},s.Base.prototype.initialize.call(this,e);if(!this.schema.subSchema)throw new Error("Missing required 'schema.subSchema' option for Object editor")},render:function(){return this.form=new i({schema:this.schema.subSchema,data:this.value,idPrefix:this.id+"_",fieldTemplate:"nestedField"}),this._observeFormEvents(),this.$el.html(this.form.render().el),this.hasFocus&&this.trigger("blur",this),this},getValue:function(){return this.form?this.form.getValue():this.value},setValue:function(e){this.value=e,this.render()},focus:function(){if(this.hasFocus)return;this.form.focus()},blur:function(){if(!this.hasFocus)return;this.form.blur()},remove:function(){this.form.remove(),r.View.prototype.remove.call(this)},validate:function(){return this.form.validate()},_observeFormEvents:function(){this.form.on("all",function(){var e=n.toArray(arguments);e[1]=this,this.trigger.apply(this,e)},this)}}),s.NestedModel=s.Object.extend({initialize:function(e){s.Base.prototype.initialize.call(this,e);if(!e.schema.model)throw'Missing required "schema.model" option for NestedModel editor'},render:function(){var e=this.value||{},t=this.key,n=this.schema.model,r=e.constructor===n?e:new n(e);return this.form=new i({model:r,idPrefix:this.id+"_",fieldTemplate:"nestedField"}),this._observeFormEvents(),this.$el.html(this.form.render().el),this.hasFocus&&this.trigger("blur",this),this},commit:function(){var e=this.form.commit();return e?(this.$el.addClass("error"),e):s.Object.prototype.commit.call(this)}}),s.Date=s.Base.extend({events:{"change select":function(){this.updateHidden(),this.trigger("change",this)},"focus select":function(){if(this.hasFocus)return;this.trigger("focus",this)},"blur select":function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(e.$("select:focus")[0])return;e.trigger("blur",e)},0)}},initialize:function(e){e=e||{},s.Base.prototype.initialize.call(this,e);var t=s.Date,r=new Date;this.options=n.extend({monthNames:t.monthNames,showMonthNames:t.showMonthNames},e),this.schema=n.extend({yearStart:r.getFullYear()-100,yearEnd:r.getFullYear()},e.schema||{}),this.value&&!n.isDate(this.value)&&(this.value=new Date(this.value));if(!this.value){var i=new Date;i.setSeconds(0),i.setMilliseconds(0),this.value=i}},render:function(){var e=this.options,r=this.schema,s=n.map(n.range(1,32),function(e){return'<option value="'+e+'">'+e+"</option>"}),o=n.map(n.range(0,12),function(t){var n=e.showMonthNames?e.monthNames[t]:t+1;return'<option value="'+t+'">'+n+"</option>"}),u=r.yearStart<r.yearEnd?n.range(r.yearStart,r.yearEnd+1):n.range(r.yearStart,r.yearEnd-1,-1),a=n.map(u,function(e){return'<option value="'+e+'">'+e+"</option>"}),f=i.helpers.parseHTML(i.templates.date({dates:s.join(""),months:o.join(""),years:a.join("")}));return this.$date=f.find('select[data-type="date"]'),this.$month=f.find('select[data-type="month"]'),this.$year=f.find('select[data-type="year"]'),this.$hidden=t('<input type="hidden" name="'+this.key+'" />'),f.append(this.$hidden),this.setValue(this.value),this.setElement(f),this.$el.attr("id",this.id),this.hasFocus&&this.trigger("blur",this),this},getValue:function(){var e=this.$year.val(),t=this.$month.val(),n=this.$date.val();return!e||!t||!n?null:new Date(e,t,n)},setValue:function(e){this.$date.val(e.getDate()),this.$month.val(e.getMonth()),this.$year.val(e.getFullYear()),this.updateHidden()},focus:function(){if(this.hasFocus)return;this.$("select").first().focus()},blur:function(){if(!this.hasFocus)return;this.$("select:focus").blur()},updateHidden:function(){var e=this.getValue();n.isDate(e)&&(e=e.toISOString()),this.$hidden.val(e)}},{showMonthNames:!0,monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"]}),s.DateTime=s.Base.extend({events:{"change select":function(){this.updateHidden(),this.trigger("change",this)},"focus select":function(){if(this.hasFocus)return;this.trigger("focus",this)},"blur select":function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(e.$("select:focus")[0])return;e.trigger("blur",e)},0)}},initialize:function(e){e=e||{},s.Base.prototype.initialize.call(this,e),this.options=n.extend({DateEditor:s.DateTime.DateEditor},e),this.schema=n.extend({minsInterval:15},e.schema||{}),this.dateEditor=new this.options.DateEditor(e),this.value=this.dateEditor.value},render:function(){function e(e){return e<10?"0"+e:e}var t=this.schema,r=n.map(n.range(0,24),function(t){return'<option value="'+t+'">'+e(t)+"</option>"}),s=n.map(n.range(0,60,t.minsInterval),function(t){return'<option value="'+t+'">'+e(t)+"</option>"}),o=i.helpers.parseHTML(i.templates.dateTime({date:'<b class="bbf-tmp"></b>',hours:r.join(),mins:s.join()}));return o.find(".bbf-tmp").replaceWith(this.dateEditor.render().el),this.$hour=o.find('select[data-type="hour"]'),this.$min=o.find('select[data-type="min"]'),this.$hidden=o.find('input[type="hidden"]'),this.setValue(this.value),this.setElement(o),this.$el.attr("id",this.id),this.hasFocus&&this.trigger("blur",this),this},getValue:function(){var e=this.dateEditor.getValue(),t=this.$hour.val(),n=this.$min.val();return!e||!t||!n?null:(e.setHours(t),e.setMinutes(n),e)},setValue:function(e){n.isDate(e)||(e=new Date(e)),this.dateEditor.setValue(e),this.$hour.val(e.getHours()),this.$min.val(e.getMinutes()),this.updateHidden()},focus:function(){if(this.hasFocus)return;this.$("select").first().focus()},blur:function(){if(!this.hasFocus)return;this.$("select:focus").blur()},updateHidden:function(){var e=this.getValue();n.isDate(e)&&(e=e.toISOString()),this.$hidden.val(e)},remove:function(){this.dateEditor.remove(),s.Base.prototype.remove.call(this)}},{DateEditor:s.Date}),s}(),i.setTemplates=i.helpers.setTemplates,i.setTemplateCompiler=i.helpers.setTemplateCompiler,i.templates={},i.setTemplates({form:' <form class="bbf-form">{{fieldsets}}</form> ',fieldset:" <fieldset> <legend>{{legend}}</legend> <ul>{{fields}}</ul> </fieldset> ",field:' <li class="bbf-field field-{{key}}"> <label for="{{id}}">{{title}}</label> <div class="bbf-editor">{{editor}}</div> <div class="bbf-help">{{help}}</div> <div class="bbf-error">{{error}}</div> </li> ',nestedField:' <li class="bbf-field bbf-nested-field field-{{key}}" title="{{title}}"> <label for="{{id}}">{{title}}</label> <div class="bbf-editor">{{editor}}</div> <div class="bbf-help">{{help}}</div> <div class="bbf-error">{{error}}</div> </li> ',list:' <div class="bbf-list"> <ul>{{items}}</ul> <div class="bbf-actions"><button type="button" data-action="add">Add</div> </div> ',listItem:' <li> <button type="button" data-action="remove" class="bbf-remove">&times;</button> <div class="bbf-editor-container">{{editor}}</div> </li> ',date:' <div class="bbf-date"> <select data-type="date" class="bbf-date">{{dates}}</select> <select data-type="month" class="bbf-month">{{months}}</select> <select data-type="year" class="bbf-year">{{years}}</select> </div> ',dateTime:' <div class="bbf-datetime"> <div class="bbf-date-container">{{date}}</div> <select data-type="hour">{{hours}}</select> : <select data-type="min">{{mins}}</select> </div> ',"list.Modal":' <div class="bbf-list-modal"> {{summary}} </div> '},{error:"bbf-error"}),i.VERSION="0.11.0",r.Form=i})(this)
+(function(e){if(typeof exports!="undefined"&&typeof require!="undefined")var t=e.jQuery||e.Zepto||e.ender||require("jquery"),n=e._||require("underscore"),r=e.Backbone||require("backbone");else var t=e.jQuery,n=e._,r=e.Backbone;var i=function(){return r.View.extend({hasFocus:!1,initialize:function(e){if(!i.templates.form)throw new Error("Templates not loaded");this.schema=function(){if(e.schema)return e.schema;var t=e.model;if(!t)throw new Error("Could not find schema");return n.isFunction(t.schema)?t.schema():t.schema}(),e=n.extend({template:"form",fieldsetTemplate:"fieldset",fieldTemplate:"field"},e);if(!e.fieldsets){var t=e.fields||n.keys(this.schema);e.fieldsets=[{fields:t}]}this.options=e,this.model=e.model,this.data=e.data,this.fields={}},render:function(){var e=this,r=this.options,s=i.templates[r.template],o=i.helpers.parseHTML(s({fieldsets:'<b class="bbf-tmp"></b>'})),u=t(".bbf-tmp",o);return n.each(r.fieldsets,function(t){u.append(e.renderFieldset(t))}),u.children().unwrap(),this.setElement(o),this.hasFocus&&this.trigger("blur",this),this},renderFieldset:function(e){var r=this,s=i.templates[this.options.fieldsetTemplate],o=this.schema,u=i.helpers.getNested;n.isArray(e)&&(e={fields:e});var a=i.helpers.parseHTML(s(n.extend({},e,{legend:'<b class="bbf-tmp-legend"></b>',fields:'<b class="bbf-tmp-fields"></b>'})));e.legend?a.find(".bbf-tmp-legend").replaceWith(e.legend):a.find(".bbf-tmp-legend").parent().remove();var f=t(".bbf-tmp-fields",a);return n.each(e.fields,function(e){var t=function(){if(o[e])return o[e];var t=e.replace(/\./g,".subSchema.");return u(o,t)}();if(!t)throw"Field '"+e+"' not found in schema";var i=r.fields[e]=r.createField(e,t),s=i.render().el;i.editor.on("all",function(t){var r=n.toArray(arguments);r[0]=e+":"+t,r.splice(1,0,this),this.trigger.apply(this,r)},r),i.editor.on("change",function(){this.trigger("change",r)},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(n.find(e.fields,function(e){return e.editor.hasFocus}))return;e.trigger("blur",e)},0)},r),t.type!=="Hidden"&&f.append(s)}),f=f.children().unwrap(),a},createField:function(e,t){t.template=t.template||this.options.fieldTemplate;var n={form:this,key:e,schema:t,idPrefix:this.options.idPrefix,template:this.options.fieldTemplate};return this.model?n.model=this.model:this.data?n.value=this.data[e]:n.value=null,new i.Field(n)},validate:function(){var e=this,t=this.fields,r=this.model,i={};n.each(t,function(e){var t=e.validate();t&&(i[e.key]=t)});if(r&&r.validate){var s=r.validate(this.getValue());if(s){var o=n.isObject(s)&&!n.isArray(s);o||(i._others=i._others||[],i._others.push(s)),o&&n.each(s,function(t,n){if(e.fields[n]&&!i[n])e.fields[n].setError(t),i[n]=t;else{i._others=i._others||[];var r={};r[n]=t,i._others.push(r)}})}}return n.isEmpty(i)?null:i},commit:function(e){var t=this.validate();if(t)return t;var r,i=n.extend({error:function(e,t){r=t}},e);this.model.set(this.getValue(),i);if(r)return r},getValue:function(e){if(e)return this.fields[e].getValue();var t={};return n.each(this.fields,function(e){t[e.key]=e.getValue()}),t},setValue:function(e,t){var n={};typeof e=="string"?n[e]=t:n=e;var r;for(r in this.schema)n[r]!==undefined&&this.fields[r].setValue(n[r])},focus:function(){if(this.hasFocus)return;var e=this.options.fieldsets[0];if(e){var t;n.isArray(e)?t=e[0]:t=e.fields[0],t&&this.fields[t].editor.focus()}},blur:function(){if(!this.hasFocus)return;var e=n.find(this.fields,function(e){return e.editor.hasFocus});e&&e.editor.blur()},remove:function(){var e=this.fields;for(var t in e)e[t].remove();r.View.prototype.remove.call(this)},trigger:function(e){return e==="focus"?this.hasFocus=!0:e==="blur"&&(this.hasFocus=!1),r.View.prototype.trigger.apply(this,arguments)}})}();i.helpers=function(){var e={};return e.getNested=function(e,t){var n=t.split("."),r=e;for(var i=0,s=n.length;i<s;i++)r=r[n[i]];return r},e.keyToTitle=function(e){return e=e.replace(/([A-Z])/g," $1"),e=e.replace(/^./,function(e){return e.toUpperCase()}),e},e.compileTemplate=function(e){var t=n.templateSettings.interpolate;n.templateSettings.interpolate=/\{\{(.+?)\}\}/g;var r=n.template(e);return n.templateSettings.interpolate=t,r},e.createTemplate=function(n,r){var i=e.compileTemplate(t.trim(n));return r?i(r):i},e.setTemplateCompiler=function(t){e.compileTemplate=t},e.setTemplates=function(t,r){var s=e.createTemplate;i.templates=i.templates||{},i.classNames=i.classNames||{},n.each(t,function(e,t,r){n.isString(e)&&(e=s(e)),i.templates[t]=e}),n.extend(i.classNames,r)},e.createEditor=function(e,t){var r;return n.isString(e)?r=i.editors[e]:r=e,new r(t)},e.getValidator=function(e){var t=i.validators;if(n.isRegExp(e))return t.regexp({regexp:e});if(n.isString(e)){if(!t[e])throw new Error('Validator "'+e+'" not found');return t[e]()}if(n.isFunction(e))return e;if(n.isObject(e)&&e.type){var r=e;return t[r.type](r)}throw new Error("Invalid validator: "+e)},e.parseHTML=function(e){return t.parseHTML!==undefined?t(t.parseHTML(e)):t(e)},e}(),i.validators=function(){var e={};return e.errMessages={required:"Required",regexp:"Invalid",email:"Invalid email address",url:"Invalid URL",match:'Must match field "{{field}}"'},e.required=function(e){return e=n.extend({type:"required",message:this.errMessages.required},e),function(n){e.value=n;var r={type:e.type,message:i.helpers.createTemplate(e.message,e)};if(n===null||n===undefined||n===!1||n==="")return r}},e.regexp=function(e){if(!e.regexp)throw new Error('Missing required "regexp" option for "regexp" validator');return e=n.extend({type:"regexp",message:this.errMessages.regexp},e),function(n){e.value=n;var r={type:e.type,message:i.helpers.createTemplate(e.message,e)};if(n===null||n===undefined||n==="")return;if(!e.regexp.test(n))return r}},e.email=function(t){return t=n.extend({type:"email",message:this.errMessages.email,regexp:/^[\w\-]{1,}([\w\-\+.]{1,1}[\w\-]{1,}){0,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/},t),e.regexp(t)},e.url=function(t){return t=n.extend({type:"url",message:this.errMessages.url,regexp:/^(http|https):\/\/(([A-Z0-9][A-Z0-9_\-]*)(\.[A-Z0-9][A-Z0-9_\-]*)+)(:(\d+))?\/?/i},t),e.regexp(t)},e.match=function(e){if(!e.field)throw new Error('Missing required "field" options for "match" validator');return e=n.extend({type:"match",message:this.errMessages.match},e),function(n,r){e.value=n;var s={type:e.type,message:i.helpers.createTemplate(e.message,e)};if(n===null||n===undefined||n==="")return;if(n!==r[e.field])return s}},e}(),i.Field=function(){var e=i.helpers,s=i.templates;return r.View.extend({initialize:function(t){t=t||{},this.form=t.form,this.key=t.key,this.value=t.value,this.model=t.model,n.isString(t.schema)&&(t.schema={type:t.schema}),this.schema=n.extend({type:"Text",title:e.keyToTitle(this.key),template:"field"},t.schema)},renderingContext:function(e,t){return{key:this.key,title:e.title,id:t.id,type:e.type,editor:'<b class="bbf-tmp-editor"></b>',help:'<b class="bbf-tmp-help"></b>',error:'<b class="bbf-tmp-error"></b>'}},render:function(){var n=this.schema,r=i.templates,s={form:this.form,key:this.key,schema:n,idPrefix:this.options.idPrefix,id:this.getId()};this.model?s.model=this.model:s.value=this.value;var o=this.editor=e.createEditor(n.type,s),u=i.helpers.parseHTML(r[n.template](this.renderingContext(n,o)));return n.title===!1&&u.find('label[for="'+o.id+'"]').first().remove(),u.find(".bbf-tmp-editor").replaceWith(o.render().el),this.$help=t(".bbf-tmp-help",u).parent(),this.$help.empty(),this.schema.help&&this.$help.html(this.schema.help),this.$error=t(t(".bbf-tmp-error",u).parent()[0]),this.$error&&this.$error.empty(),this.schema.fieldClass&&u.addClass(this.schema.fieldClass),this.schema.fieldAttrs&&u.attr(this.schema.fieldAttrs),this.setElement(u),this},getId:function(){var e=this.options.idPrefix,t=this.key;return t=t.replace(/\./g,"_"),n.isString(e)||n.isNumber(e)?e+t:n.isNull(e)?t:this.model?this.model.cid+"_"+t:t},validate:function(){var e=this.editor.validate();return e?this.setError(e.message):this.clearError(),e},setError:function(e){if(this.editor.hasNestedForm)return;var t=i.classNames.error;this.$el.addClass(t),this.$error?this.$error.html(e):this.$help&&this.$help.html(e)},clearError:function(){var e=i.classNames.error;this.$el.removeClass(e);if(this.$error)this.$error.empty();else if(this.$help){this.$help.empty();var t=this.schema.help;t&&this.$help.html(t)}},commit:function(){return this.editor.commit()},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(),r.View.prototype.remove.call(this)}})}(),i.editors=function(){var e=i.helpers,s={};return s.Base=r.View.extend({defaultValue:null,hasFocus:!1,initialize:function(e){var e=e||{};if(e.model){if(!e.key)throw"Missing option: 'key'";this.model=e.model,this.value=this.model.get(e.key)}else e.value&&(this.value=e.value);this.value===undefined&&(this.value=this.defaultValue),this.key=e.key,this.form=e.form,this.schema=e.schema||{},this.validators=e.validators||this.schema.validators,this.$el.attr("name",this.getName()),this.schema.editorClass&&this.$el.addClass(this.schema.editorClass),this.schema.editorAttrs&&this.$el.attr(this.schema.editorAttrs)},getValue:function(){throw"Not implemented. Extend and override this method."},setValue:function(){throw"Not implemented. Extend and override this method."},focus:function(){throw"Not implemented. Extend and override this method."},blur:function(){throw"Not implemented. Extend and override this method."},getName:function(){var e=this.key||"";return e.replace(/\./g,"_")},commit:function(e){var t=this.validate();if(t)return t;this.listenTo(this.model,"invalid",function(e,n){t=n}),this.model.set(this.key,this.getValue(),e);if(t)return t},validate:function(){var e=this.$el,t=null,r=this.getValue(),s=this.form?this.form.getValue():{},o=this.validators,u=i.helpers.getValidator;return o&&n.every(o,function(e){return t=u(e)(r,s),t?!1:!0}),t},trigger:function(e){return e==="focus"?this.hasFocus=!0:e==="blur"&&(this.hasFocus=!1),r.View.prototype.trigger.apply(this,arguments)}}),s.Text=s.Base.extend({tagName:"input",defaultValue:"",previousValue:"",events:{keyup:"determineChange",keypress:function(e){var t=this;setTimeout(function(){t.determineChange()},0)},select:function(e){this.trigger("select",this)},focus:function(e){this.trigger("focus",this)},blur:function(e){this.trigger("blur",this)}},initialize:function(e){s.Base.prototype.initialize.call(this,e);var t=this.schema,n="text";t&&t.editorAttrs&&t.editorAttrs.type&&(n=t.editorAttrs.type),t&&t.dataType&&(n=t.dataType),this.$el.attr("type",n)},render:function(){return this.setValue(this.value),this},determineChange:function(e){var t=this.$el.val(),n=t!==this.previousValue;n&&(this.previousValue=t,this.trigger("change",this))},getValue:function(){return this.$el.val()},setValue:function(e){this.$el.val(e)},focus:function(){if(this.hasFocus)return;this.$el.focus()},blur:function(){if(!this.hasFocus)return;this.$el.blur()},select:function(){this.$el.select()}}),s.Number=s.Text.extend({defaultValue:0,events:n.extend({},s.Text.prototype.events,{keypress:"onKeyPress"}),initialize:function(e){s.Text.prototype.initialize.call(this,e),this.$el.attr("type","number"),this.$el.attr("step","any")},onKeyPress:function(e){var t=this,n=function(){setTimeout(function(){t.determineChange()},0)};if(e.charCode===0){n();return}var r=this.$el.val()+String.fromCharCode(e.charCode),i=/^[0-9]*\.?[0-9]*?$/.test(r);i?n():e.preventDefault()},getValue:function(){var e=this.$el.val();return e===""?null:parseFloat(e,10)},setValue:function(e){e=function(){return n.isNumber(e)?e:n.isString(e)&&e!==""?parseFloat(e,10):null}(),n.isNaN(e)&&(e=null),s.Text.prototype.setValue.call(this,e)}}),s.Password=s.Text.extend({initialize:function(e){s.Text.prototype.initialize.call(this,e),this.$el.attr("type","password")}}),s.TextArea=s.Text.extend({tagName:"textarea"}),s.Checkbox=s.Base.extend({defaultValue:!1,tagName:"input",events:{click:function(e){this.trigger("change",this)},focus:function(e){this.trigger("focus",this)},blur:function(e){this.trigger("blur",this)}},initialize:function(e){s.Base.prototype.initialize.call(this,e),this.$el.attr("type","checkbox")},render:function(){return this.setValue(this.value),this},getValue:function(){return this.$el.prop("checked")},setValue:function(e){e&&this.$el.prop("checked",!0)},focus:function(){if(this.hasFocus)return;this.$el.focus()},blur:function(){if(!this.hasFocus)return;this.$el.blur()}}),s.Hidden=s.Base.extend({defaultValue:"",initialize:function(e){s.Text.prototype.initialize.call(this,e),this.$el.attr("type","hidden")},getValue:function(){return this.value},setValue:function(e){this.value=e},focus:function(){},blur:function(){}}),s.Select=s.Base.extend({tagName:"select",events:{change:function(e){this.trigger("change",this)},focus:function(e){this.trigger("focus",this)},blur:function(e){this.trigger("blur",this)}},initialize:function(e){s.Base.prototype.initialize.call(this,e);if(!this.schema||!this.schema.options)throw"Missing required 'schema.options'"},render:function(){return this.setOptions(this.schema.options),this},setOptions:function(e){var t=this;if(e instanceof r.Collection){var i=e;i.length>0?this.renderOptions(e):i.fetch({success:function(n){t.renderOptions(e)}})}else n.isFunction(e)?e(function(e){t.renderOptions(e)},t):this.renderOptions(e)},renderOptions:function(e){var t=this.$el,n;n=this._getOptionsHtml(e),t.html(n),this.setValue(this.value)},_getOptionsHtml:function(e){var t;if(n.isString(e))t=e;else if(n.isArray(e))t=this._arrayToHtml(e);else if(e instanceof r.Collection)t=this._collectionToHtml(e);else if(n.isFunction(e)){var i;e(function(e){i=e},this),t=this._getOptionsHtml(i)}return t},getValue:function(){return this.$el.val()},setValue:function(e){this.$el.val(e)},focus:function(){if(this.hasFocus)return;this.$el.focus()},blur:function(){if(!this.hasFocus)return;this.$el.blur()},_collectionToHtml:function(e){var t=[];e.each(function(e){t.push({val:e.id,label:e.toString()})});var n=this._arrayToHtml(t);return n},_arrayToHtml:function(e){var t=[];return n.each(e,function(e){if(n.isObject(e))if(e.group)t.push('<optgroup label="'+e.group+'">'),t.push(this._getOptionsHtml(e.options)),t.push("</optgroup>");else{var r=e.val||e.val===0?e.val:"";t.push('<option value="'+r+'">'+e.label+"</option>")}else t.push("<option>"+e+"</option>")},this),t.join("")}}),s.Radio=s.Select.extend({tagName:"ul",className:"bbf-radio",events:{"change input[type=radio]":function(){this.trigger("change",this)},"focus input[type=radio]":function(){if(this.hasFocus)return;this.trigger("focus",this)},"blur input[type=radio]":function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(e.$("input[type=radio]:focus")[0])return;e.trigger("blur",e)},0)}},getValue:function(){return this.$("input[type=radio]:checked").val()},setValue:function(e){this.$("input[type=radio]").val([e])},focus:function(){if(this.hasFocus)return;var e=this.$("input[type=radio]:checked");if(e[0]){e.focus();return}this.$("input[type=radio]").first().focus()},blur:function(){if(!this.hasFocus)return;this.$("input[type=radio]:focus").blur()},_arrayToHtml:function(e){var t=[],r=this;return n.each(e,function(e,i){var s="<li>";if(n.isObject(e)){var o=e.val||e.val===0?e.val:"";s+='<input type="radio" name="'+r.id+'" value="'+o+'" id="'+r.id+"-"+i+'" />',s+='<label for="'+r.id+"-"+i+'">'+e.label+"</label>"}else s+='<input type="radio" name="'+r.id+'" value="'+e+'" id="'+r.id+"-"+i+'" />',s+='<label for="'+r.id+"-"+i+'">'+e+"</label>";s+="</li>",t.push(s)}),t.join("")}}),s.Checkboxes=s.Select.extend({tagName:"ul",className:"bbf-checkboxes",events:{"click input[type=checkbox]":function(){this.trigger("change",this)},"focus input[type=checkbox]":function(){if(this.hasFocus)return;this.trigger("focus",this)},"blur input[type=checkbox]":function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(e.$("input[type=checkbox]:focus")[0])return;e.trigger("blur",e)},0)}},getValue:function(){var e=[];return this.$("input[type=checkbox]:checked").each(function(){e.push(t(this).val())}),e},setValue:function(e){n.isArray(e)||(e=[e]),this.$("input[type=checkbox]").val(e)},focus:function(){if(this.hasFocus)return;this.$("input[type=checkbox]").first().focus()},blur:function(){if(!this.hasFocus)return;this.$("input[type=checkbox]:focus").blur()},_arrayToHtml:function(e){var t=[],r=this;return n.each(e,function(e,i){var s="<li>";if(n.isObject(e)){var o=e.val||e.val===0?e.val:"";s+='<input type="checkbox" name="'+r.id+'" value="'+o+'" id="'+r.id+"-"+i+'" />',s+='<label for="'+r.id+"-"+i+'">'+e.label+"</label>"}else s+='<input type="checkbox" name="'+r.id+'" value="'+e+'" id="'+r.id+"-"+i+'" />',s+='<label for="'+r.id+"-"+i+'">'+e+"</label>";s+="</li>",t.push(s)}),t.join("")}}),s.Object=s.Base.extend({hasNestedForm:!0,className:"bbf-object",initialize:function(e){this.value={},s.Base.prototype.initialize.call(this,e);if(!this.schema.subSchema)throw new Error("Missing required 'schema.subSchema' option for Object editor")},render:function(){return this.form=new i({schema:this.schema.subSchema,data:this.value,idPrefix:this.id+"_",fieldTemplate:"nestedField"}),this._observeFormEvents(),this.$el.html(this.form.render().el),this.hasFocus&&this.trigger("blur",this),this},getValue:function(){return this.form?this.form.getValue():this.value},setValue:function(e){this.value=e,this.render()},focus:function(){if(this.hasFocus)return;this.form.focus()},blur:function(){if(!this.hasFocus)return;this.form.blur()},remove:function(){this.form.remove(),r.View.prototype.remove.call(this)},validate:function(){return this.form.validate()},_observeFormEvents:function(){this.form.on("all",function(){var e=n.toArray(arguments);e[1]=this,this.trigger.apply(this,e)},this)}}),s.NestedModel=s.Object.extend({initialize:function(e){s.Base.prototype.initialize.call(this,e);if(!e.schema.model)throw'Missing required "schema.model" option for NestedModel editor'},render:function(){var e=this.value||{},t=this.key,n=this.schema.model,r=e.constructor===n?e:new n(e);return this.form=new i({model:r,idPrefix:this.id+"_",fieldTemplate:"nestedField"}),this._observeFormEvents(),this.$el.html(this.form.render().el),this.hasFocus&&this.trigger("blur",this),this},commit:function(){var e=this.form.commit();return e?(this.$el.addClass("error"),e):s.Object.prototype.commit.call(this)}}),s.Date=s.Base.extend({events:{"change select":function(){this.updateHidden(),this.trigger("change",this)},"focus select":function(){if(this.hasFocus)return;this.trigger("focus",this)},"blur select":function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(e.$("select:focus")[0])return;e.trigger("blur",e)},0)}},initialize:function(e){e=e||{},s.Base.prototype.initialize.call(this,e);var t=s.Date,r=new Date;this.options=n.extend({monthNames:t.monthNames,showMonthNames:t.showMonthNames},e),this.schema=n.extend({yearStart:r.getFullYear()-100,yearEnd:r.getFullYear()},e.schema||{}),this.value&&!n.isDate(this.value)&&(this.value=new Date(this.value));if(!this.value){var i=new Date;i.setSeconds(0),i.setMilliseconds(0),this.value=i}},render:function(){var e=this.options,r=this.schema,s=n.map(n.range(1,32),function(e){return'<option value="'+e+'">'+e+"</option>"}),o=n.map(n.range(0,12),function(t){var n=e.showMonthNames?e.monthNames[t]:t+1;return'<option value="'+t+'">'+n+"</option>"}),u=r.yearStart<r.yearEnd?n.range(r.yearStart,r.yearEnd+1):n.range(r.yearStart,r.yearEnd-1,-1),a=n.map(u,function(e){return'<option value="'+e+'">'+e+"</option>"}),f=i.helpers.parseHTML(i.templates.date({dates:s.join(""),months:o.join(""),years:a.join("")}));return this.$date=f.find('select[data-type="date"]'),this.$month=f.find('select[data-type="month"]'),this.$year=f.find('select[data-type="year"]'),this.$hidden=t('<input type="hidden" name="'+this.key+'" />'),f.append(this.$hidden),this.setValue(this.value),this.setElement(f),this.$el.attr("id",this.id),this.hasFocus&&this.trigger("blur",this),this},getValue:function(){var e=this.$year.val(),t=this.$month.val(),n=this.$date.val();return!e||!t||!n?null:new Date(e,t,n)},setValue:function(e){this.$date.val(e.getDate()),this.$month.val(e.getMonth()),this.$year.val(e.getFullYear()),this.updateHidden()},focus:function(){if(this.hasFocus)return;this.$("select").first().focus()},blur:function(){if(!this.hasFocus)return;this.$("select:focus").blur()},updateHidden:function(){var e=this.getValue();n.isDate(e)&&(e=e.toISOString()),this.$hidden.val(e)}},{showMonthNames:!0,monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"]}),s.DateTime=s.Base.extend({events:{"change select":function(){this.updateHidden(),this.trigger("change",this)},"focus select":function(){if(this.hasFocus)return;this.trigger("focus",this)},"blur select":function(){if(!this.hasFocus)return;var e=this;setTimeout(function(){if(e.$("select:focus")[0])return;e.trigger("blur",e)},0)}},initialize:function(e){e=e||{},s.Base.prototype.initialize.call(this,e),this.options=n.extend({DateEditor:s.DateTime.DateEditor},e),this.schema=n.extend({minsInterval:15},e.schema||{}),this.dateEditor=new this.options.DateEditor(e),this.value=this.dateEditor.value},render:function(){function e(e){return e<10?"0"+e:e}var t=this.schema,r=n.map(n.range(0,24),function(t){return'<option value="'+t+'">'+e(t)+"</option>"}),s=n.map(n.range(0,60,t.minsInterval),function(t){return'<option value="'+t+'">'+e(t)+"</option>"}),o=i.helpers.parseHTML(i.templates.dateTime({date:'<b class="bbf-tmp"></b>',hours:r.join(),mins:s.join()}));return o.find(".bbf-tmp").replaceWith(this.dateEditor.render().el),this.$hour=o.find('select[data-type="hour"]'),this.$min=o.find('select[data-type="min"]'),this.$hidden=o.find('input[type="hidden"]'),this.setValue(this.value),this.setElement(o),this.$el.attr("id",this.id),this.hasFocus&&this.trigger("blur",this),this},getValue:function(){var e=this.dateEditor.getValue(),t=this.$hour.val(),n=this.$min.val();return!e||!t||!n?null:(e.setHours(t),e.setMinutes(n),e)},setValue:function(e){n.isDate(e)||(e=new Date(e)),this.dateEditor.setValue(e),this.$hour.val(e.getHours()),this.$min.val(e.getMinutes()),this.updateHidden()},focus:function(){if(this.hasFocus)return;this.$("select").first().focus()},blur:function(){if(!this.hasFocus)return;this.$("select:focus").blur()},updateHidden:function(){var e=this.getValue();n.isDate(e)&&(e=e.toISOString()),this.$hidden.val(e)},remove:function(){this.dateEditor.remove(),s.Base.prototype.remove.call(this)}},{DateEditor:s.Date}),s}(),i.setTemplates=i.helpers.setTemplates,i.setTemplateCompiler=i.helpers.setTemplateCompiler,i.templates={},i.setTemplates({form:' <form class="bbf-form">{{fieldsets}}</form> ',fieldset:" <fieldset> <legend>{{legend}}</legend> <ul>{{fields}}</ul> </fieldset> ",field:' <li class="bbf-field field-{{key}}"> <label for="{{id}}">{{title}}</label> <div class="bbf-editor">{{editor}}</div> <div class="bbf-help">{{help}}</div> <div class="bbf-error">{{error}}</div> </li> ',nestedField:' <li class="bbf-field bbf-nested-field field-{{key}}" title="{{title}}"> <label for="{{id}}">{{title}}</label> <div class="bbf-editor">{{editor}}</div> <div class="bbf-help">{{help}}</div> <div class="bbf-error">{{error}}</div> </li> ',list:' <div class="bbf-list"> <ul>{{items}}</ul> <div class="bbf-actions"><button type="button" data-action="add">Add</div> </div> ',listItem:' <li> <button type="button" data-action="remove" class="bbf-remove">&times;</button> <div class="bbf-editor-container">{{editor}}</div> </li> ',date:' <div class="bbf-date"> <select data-type="date" class="bbf-date">{{dates}}</select> <select data-type="month" class="bbf-month">{{months}}</select> <select data-type="year" class="bbf-year">{{years}}</select> </div> ',dateTime:' <div class="bbf-datetime"> <div class="bbf-date-container">{{date}}</div> <select data-type="hour">{{hours}}</select> : <select data-type="min">{{mins}}</select> </div> ',"list.Modal":' <div class="bbf-list-modal"> {{summary}} </div> '},{error:"bbf-error"}),i.VERSION="0.11.0",r.Form=i})(this)
View
112 distribution/editors/list.js
@@ -371,10 +371,10 @@
/**
- * Modal object editor for use with the List editor.
- * To use it, set the 'itemType' property in a List schema to 'Object' or 'NestedModel'
+ * Base modal object editor for use with the List editor; used by Object
+ * and NestedModal list types
*/
- editors.List.Modal = editors.List.Object = editors.List.NestedModel = editors.Base.extend({
+ editors.List.Modal = editors.Base.extend({
events: {
'click': 'openEditor'
},
@@ -388,26 +388,9 @@
*/
initialize: function(options) {
editors.Base.prototype.initialize.call(this, options);
-
- var schema = this.schema;
//Dependencies
if (!editors.List.Modal.ModalAdapter) throw 'A ModalAdapter is required';
-
- //Get nested schema if Object
- if (schema.itemType === 'Object') {
- if (!schema.subSchema) throw 'Missing required option "schema.subSchema"';
-
- this.nestedSchema = schema.subSchema;
- }
-
- //Get nested schema if NestedModel
- if (schema.itemType === 'NestedModel') {
- if (!schema.model) throw 'Missing required option "schema.model"';
-
- this.nestedSchema = schema.model.prototype.schema;
- if (_.isFunction(this.nestedSchema)) this.nestedSchema = this.nestedSchema();
- }
},
/**
@@ -482,62 +465,66 @@
//If there's a specified toString use that
if (schema.itemToString) return schema.itemToString(value);
- //Otherwise check if it's NestedModel with it's own toString() method
- if (schema.itemType === 'NestedModel') {
- return new (schema.model)(value).toString();
- }
-
//Otherwise use the generic method or custom overridden method
return this.itemToString(value);
},
openEditor: function() {
var self = this;
- var form = new Form({
+ var form = this.modalForm = new Form({
schema: this.nestedSchema,
data: this.value
});
- var modal = this.modal = new Backbone.BootstrapModal({
+ var modal = this.modal = new editors.List.Modal.ModalAdapter({
content: form,
animate: true
- }).open();
+ });
+
+ modal.open();
this.trigger('open', this);
this.trigger('focus', this);
- modal.on('cancel', function() {
- this.modal = null;
-
- this.trigger('close', this);
- this.trigger('blur', this);
- }, this);
+ modal.on('cancel', this.onModalClosed, this);
- modal.on('ok', _.bind(this.onModalSubmitted, this, form, modal));
+ modal.on('ok', _.bind(this.onModalSubmitted, this));
},
/**
* Called when the user clicks 'OK'.
* Runs validation and tells the list when ready to add the item
*/
- onModalSubmitted: function(form, modal) {
- var isNew = !this.value;
+ onModalSubmitted: function() {
+ var modal = this.modal,
+ form = this.modalForm,
+ isNew = !this.value;
//Stop if there are validation errors
var error = form.validate();
if (error) return modal.preventClose();
- this.modal = null;
- //If OK, render the list item
+ //Store form value
this.value = form.getValue();
+ //Render item
this.renderSummary();
if (isNew) this.trigger('readyToAdd');
this.trigger('change', this);
-
+
+ this.onModalClosed();
+ },
+
+ /**
+ * Cleans up references, triggers events. To be called whenever the modal closes
+ */
+ onModalClosed: function() {
+ this.modal = null;
+ this.modalForm = null;
+
this.trigger('close', this);
this.trigger('blur', this);
},
@@ -561,7 +548,6 @@
if (this.modal) {
this.modal.trigger('cancel');
- this.modal.close();
}
}
}, {
@@ -576,4 +562,48 @@
isAsync: true
});
+
+ editors.List.Object = editors.List.Modal.extend({
+ initialize: function () {
+ editors.List.Modal.prototype.initialize.apply(this, arguments);
+
+ var schema = this.schema;
+
+ if (!schema.subSchema) throw 'Missing required option "schema.subSchema"';
+
+ this.nestedSchema = schema.subSchema;
+ }
+ });
+
+
+ editors.List.NestedModel = editors.List.Modal.extend({
+ initialize: function() {
+ editors.List.Modal.prototype.initialize.apply(this, arguments);
+
+ var schema = this.schema;
+
+ if (!schema.model) throw 'Missing required option "schema.model"';
+
+ var nestedSchema = schema.model.prototype.schema;
+
+ this.nestedSchema = (_.isFunction(nestedSchema)) ? nestedSchema() : nestedSchema;
+ },
+
+ /**
+ * Returns the string representation of the object value
+ */
+ getStringValue: function() {
+ var schema = this.schema,
+ value = this.getValue();
+
+ if (_.isEmpty(value)) return null;
+
+ //If there's a specified toString use that
+ if (schema.itemToString) return schema.itemToString(value);
+
+ //Otherwise use the model
+ return new (schema.model)(value).toString();
+ },
+ });
+
})();
View
2 distribution/editors/list.min.js
@@ -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},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.List.Object=t.List.NestedModel=t.Base.extend({events:{click:"openEditor"},initialize:function(e){t.Base.prototype.initialize.call(this,e);var n=this.schema;if(!t.List.Modal.ModalAdapter)throw"A ModalAdapter is required";if(n.itemType==="Object"){if(!n.subSchema)throw'Missing required option "schema.subSchema"';this.nestedSchema=n.subSchema}if(n.itemType==="NestedModel"){if(!n.model)throw'Missing required option "schema.model"';this.nestedSchema=n.model.prototype.schema,_.isFunction(this.nestedSchema)&&(this.nestedSchema=this.nestedSchema())}},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):e.itemType==="NestedModel"?(new e.model(t)).toString():this.itemToString(t)},openEditor:function(){var t=this,n=new e({schema:this.nestedSchema,data:this.value}),r=this.modal=(new Backbone.BootstrapModal({content:n,animate:!0})).open();this.trigger("open",this),this.trigger("focus",this),r.on("cancel",function(){this.modal=null,this.trigger("close",this),this.trigger("blur",this)},this),r.on("ok",_.bind(this.onModalSubmitted,this,n,r))},onModalSubmitted:function(e,t){var n=!this.value,r=e.validate();if(r)return t.preventClose();this.modal=null,this.value=e.getValue(),this.renderSummary(),n&&this.trigger("readyToAdd"),this.trigger("change",this),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"),this.modal.close())}},{ModalAdapter:Backbone.BootstrapModal,isAsync:!0})})()
+(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},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()}})})()

0 comments on commit 4987135

Please sign in to comment.