commiting uncommited changes on live site
[weblabels.fsf.org.git] / crm.fsf.org / 20131203 / files / sites / all / modules-old / civicrm / packages / backbone-forms / distribution / backbone-forms.amd.min.js
1 define(["jquery","underscore","Backbone"],function($,_,Backbone){var Form=function(){return Backbone.View.extend({hasFocus:!1,initialize:function(options){if(!Form.templates.form)throw new Error("Templates not loaded");this.schema=function(){if(options.schema)return options.schema;var model=options.model;if(!model)throw new Error("Could not find schema");return _.isFunction(model.schema)?model.schema():model.schema}(),options=_.extend({template:"form",fieldsetTemplate:"fieldset",fieldTemplate:"field"},options);if(!options.fieldsets){var fields=options.fields||_.keys(this.schema);options.fieldsets=[{fields:fields}]}this.options=options,this.model=options.model,this.data=options.data,this.fields={}},render:function(){var self=this,options=this.options,template=Form.templates[options.template],$form=$(template({fieldsets:'<b class="bbf-tmp"></b>'})),$fieldsetContainer=$(".bbf-tmp",$form);return _.each(options.fieldsets,function(fieldset){$fieldsetContainer.append(self.renderFieldset(fieldset))}),$fieldsetContainer.children().unwrap(),this.setElement($form),this.hasFocus&&this.trigger("blur",this),this},renderFieldset:function(fieldset){var self=this,template=Form.templates[this.options.fieldsetTemplate],schema=this.schema,getNested=Form.helpers.getNested;_.isArray(fieldset)&&(fieldset={fields:fieldset});var $fieldset=$(template(_.extend({},fieldset,{legend:'<b class="bbf-tmp-legend"></b>',fields:'<b class="bbf-tmp-fields"></b>'})));fieldset.legend?$fieldset.find(".bbf-tmp-legend").replaceWith(fieldset.legend):$fieldset.find(".bbf-tmp-legend").parent().remove();var $fieldsContainer=$(".bbf-tmp-fields",$fieldset);return _.each(fieldset.fields,function(key){var itemSchema=function(){if(schema[key])return schema[key];var path=key.replace(/\./g,".subSchema.");return getNested(schema,path)}();if(!itemSchema)throw"Field '"+key+"' not found in schema";var field=self.fields[key]=self.createField(key,itemSchema),fieldEl=field.render().el;field.editor.on("all",function(event){args=_.toArray(arguments),args[0]=key+":"+event,args.splice(1,0,this),this.trigger.apply(this,args)},self),field.editor.on("change",function(){this.trigger("change",self)},self),field.editor.on("focus",function(){if(this.hasFocus)return;this.trigger("focus",this)},self),field.editor.on("blur",function(){if(!this.hasFocus)return;var self=this;setTimeout(function(){if(_.find(self.fields,function(field){return field.editor.hasFocus}))return;self.trigger("blur",self)},0)},self),itemSchema.type!="Hidden"&&$fieldsContainer.append(fieldEl)}),$fieldsContainer=$fieldsContainer.children().unwrap(),$fieldset},createField:function(key,schema){schema.template=schema.template||this.options.fieldTemplate;var options={form:this,key:key,schema:schema,idPrefix:this.options.idPrefix,template:this.options.fieldTemplate};return this.model?options.model=this.model:this.data?options.value=this.data[key]:options.value=null,new Form.Field(options)},validate:function(){var self=this,fields=this.fields,model=this.model,errors={};_.each(fields,function(field){var error=field.validate();error&&(errors[field.key]=error)});if(model&&model.validate){var modelErrors=model.validate(this.getValue());if(modelErrors){var isDictionary=_.isObject(modelErrors)&&!_.isArray(modelErrors);isDictionary||(errors._others=errors._others||[],errors._others.push(modelErrors)),isDictionary&&_.each(modelErrors,function(val,key){if(self.fields[key]&&!errors[key])self.fields[key].setError(val);else{errors._others=errors._others||[];var tmpErr={};tmpErr[key]=val,errors._others.push(tmpErr)}})}}return _.isEmpty(errors)?null:errors},commit:function(){var errors=this.validate();if(errors)return errors;var modelError;this.model.set(this.getValue(),{error:function(model,e){modelError=e}});if(modelError)return modelError},getValue:function(key){if(key)return this.fields[key].getValue();var values={};return _.each(this.fields,function(field){values[field.key]=field.getValue()}),values},setValue:function(data){for(var key in data)this.fields[key].setValue(data[key])},focus:function(){if(this.hasFocus)return;var fieldset=this.options.fieldsets[0];if(fieldset){var field;_.isArray(fieldset)?field=fieldset[0]:field=fieldset.fields[0],field&&this.fields[field].editor.focus()}},blur:function(){if(!this.hasFocus)return;focusedField=_.find(this.fields,function(field){return field.editor.hasFocus}),focusedField&&focusedField.editor.blur()},remove:function(){var fields=this.fields;for(var key in fields)fields[key].remove();Backbone.View.prototype.remove.call(this)},trigger:function(event){return event=="focus"?this.hasFocus=!0:event=="blur"&&(this.hasFocus=!1),Backbone.View.prototype.trigger.apply(this,arguments)}})}();return Form.helpers=function(){var helpers={};return helpers.getNested=function(obj,path){var fields=path.split("."),result=obj;for(var i=0,n=fields.length;i<n;i++)result=result[fields[i]];return result},helpers.keyToTitle=function(str){return str=str.replace(/([A-Z])/g," $1"),str=str.replace(/^./,function(str){return str.toUpperCase()}),str},helpers.compileTemplate=function(str){var _interpolateBackup=_.templateSettings.interpolate;_.templateSettings.interpolate=/\{\{(.+?)\}\}/g;var template=_.template(str);return _.templateSettings.interpolate=_interpolateBackup,template},helpers.createTemplate=function(str,context){var template=helpers.compileTemplate(str);return context?template(context):template},helpers.setTemplateCompiler=function(compiler){helpers.compileTemplate=compiler},helpers.setTemplates=function(templates,classNames){var createTemplate=helpers.createTemplate;Form.templates=Form.templates||{},Form.classNames=Form.classNames||{},_.each(templates,function(template,key,index){_.isString(template)&&(template=createTemplate(template)),Form.templates[key]=template}),_.extend(Form.classNames,classNames)},helpers.createEditor=function(schemaType,options){var constructorFn;return _.isString(schemaType)?constructorFn=Form.editors[schemaType]:constructorFn=schemaType,new constructorFn(options)},helpers.triggerCancellableEvent=function(subject,event,args,callback){if(!subject._callbacks||!subject._callbacks[event])return callback();var next=subject._callbacks[event].next;if(!next)return callback();var fn=next.callback,context=next.context||this;args.push(callback),fn.apply(context,args)},helpers.getValidator=function(validator){var validators=Form.validators;if(_.isRegExp(validator))return validators.regexp({regexp:validator});if(_.isString(validator)){if(!validators[validator])throw new Error('Validator "'+validator+'" not found');return validators[validator]()}if(_.isFunction(validator))return validator;if(_.isObject(validator)&&validator.type){var config=validator;return validators[config.type](config)}throw new Error("Invalid validator: "+validator)},helpers}(),Form.validators=function(){var validators={};return validators.errMessages={required:"Required",regexp:"Invalid",email:"Invalid email address",url:"Invalid URL",match:'Must match field "{{field}}"'},validators.required=function(options){return options=_.extend({type:"required",message:this.errMessages.required},options),function(value){options.value=value;var err={type:options.type,message:Form.helpers.createTemplate(options.message,options)};if(value===null||value===undefined||value==="")return err}},validators.regexp=function(options){if(!options.regexp)throw new Error('Missing required "regexp" option for "regexp" validator');return options=_.extend({type:"regexp",message:this.errMessages.regexp},options),function(value){options.value=value;var err={type:options.type,message:Form.helpers.createTemplate(options.message,options)};if(value===null||value===undefined||value==="")return;if(!options.regexp.test(value))return err}},validators.email=function(options){return options=_.extend({type:"email",message:this.errMessages.email,regexp:/^[\w\-]{1,}([\w\-\+.]{1,1}[\w\-]{1,}){0,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/},options),validators.regexp(options)},validators.url=function(options){return options=_.extend({type:"url",message:this.errMessages.url,regexp:/^(http|https):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i},options),validators.regexp(options)},validators.match=function(options){if(!options.field)throw new Error('Missing required "field" options for "match" validator');return options=_.extend({type:"match",message:this.errMessages.match},options),function(value,attrs){options.value=value;var err={type:options.type,message:Form.helpers.createTemplate(options.message,options)};if(value===null||value===undefined||value==="")return;if(value!=attrs[options.field])return err}},validators}(),Form.Field=function(){var helpers=Form.helpers,templates=Form.templates;return Backbone.View.extend({initialize:function(options){options=options||{},this.form=options.form,this.key=options.key,this.value=options.value,this.model=options.model,_.isString(options.schema)&&(options.schema={type:options.schema}),this.schema=_.extend({type:"Text",title:helpers.keyToTitle(this.key),template:"field"},options.schema)},render:function(){var schema=this.schema,templates=Form.templates,options={form:this.form,key:this.key,schema:schema,idPrefix:this.options.idPrefix,id:this.getId()};this.model?options.model=this.model:options.value=this.value;var editor=this.editor=helpers.createEditor(schema.type,options),$field=$(templates[schema.template]({key:this.key,title:schema.title,id:editor.id,type:schema.type,editor:'<b class="bbf-tmp-editor"></b>',help:'<b class="bbf-tmp-help"></b>'}));return $field.find(".bbf-tmp-editor").replaceWith(editor.render().el),this.$help=$(".bbf-tmp-help",$field).parent(),this.$help.empty(),this.schema.help&&this.$help.html(this.schema.help),this.schema.fieldClass&&$field.addClass(this.schema.fieldClass),this.schema.fieldAttrs&&$field.attr(this.schema.fieldAttrs),this.setElement($field),this},getId:function(){var prefix=this.options.idPrefix,id=this.key;return id=id.replace(/\./g,"_"),_.isString(prefix)||_.isNumber(prefix)?prefix+id:_.isNull(prefix)?id:this.model?this.model.cid+"_"+id:id},validate:function(){var error=this.editor.validate();return error?this.setError(error.message):this.clearError(),error},setError:function(msg){if(this.editor.hasNestedForm)return;var errClass=Form.classNames.error;this.$el.addClass(errClass),this.$help&&this.$help.html(msg)},clearError:function(){var errClass=Form.classNames.error;this.$el.removeClass(errClass);if(this.$help){this.$help.empty();var helpMsg=this.schema.help;helpMsg&&this.$help.html(helpMsg)}},commit:function(){return this.editor.commit()},getValue:function(){return this.editor.getValue()},setValue:function(value){this.editor.setValue(value)},focus:function(){this.editor.focus()},blur:function(){this.editor.blur()},remove:function(){this.editor.remove(),Backbone.View.prototype.remove.call(this)}})}(),Form.editors=function(){var helpers=Form.helpers,editors={};return editors.Base=Backbone.View.extend({defaultValue:null,hasFocus:!1,initialize:function(options){var options=options||{};if(options.model){if(!options.key)throw"Missing option: 'key'";this.model=options.model,this.value=this.model.get(options.key)}else options.value&&(this.value=options.value);this.value===undefined&&(this.value=this.defaultValue),this.key=options.key,this.form=options.form,this.schema=options.schema||{},this.validators=options.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 key=this.key||"";return key.replace(/\./g,"_")},commit:function(){var error=this.validate();if(error)return error;this.model.set(this.key,this.getValue(),{error:function(model,e){error=e}});if(error)return error},validate:function(){var $el=this.$el,error=null,value=this.getValue(),formValues=this.form?this.form.getValue():{},validators=this.validators,getValidator=Form.helpers.getValidator;return validators&&_.every(validators,function(validator){return error=getValidator(validator)(value,formValues),continueLoop=error?!1:!0}),error},trigger:function(event){return event=="focus"?this.hasFocus=!0:event=="blur"&&(this.hasFocus=!1),Backbone.View.prototype.trigger.apply(this,arguments)}}),editors.Text=editors.Base.extend({tagName:"input",defaultValue:"",previousValue:"",events:{keyup:"determineChange",keypress:function(event){var self=this;setTimeout(function(){self.determineChange()},0)},select:function(event){this.trigger("select",this)},focus:function(event){this.trigger("focus",this)},blur:function(event){this.trigger("blur",this)}},initialize:function(options){editors.Base.prototype.initialize.call(this,options);var schema=this.schema,type="text";schema&&schema.editorAttrs&&schema.editorAttrs.type&&(type=schema.editorAttrs.type),schema&&schema.dataType&&(type=schema.dataType),this.$el.attr("type",type)},render:function(){return this.setValue(this.value),this},determineChange:function(event){var currentValue=this.$el.val(),changed=currentValue!=this.previousValue;changed&&(this.previousValue=currentValue,this.trigger("change",this))},getValue:function(){return this.$el.val()},setValue:function(value){this.$el.val(value)},focus:function(){if(this.hasFocus)return;this.$el.focus()},blur:function(){if(!this.hasFocus)return;this.$el.blur()},select:function(){this.$el.select()}}),editors.Number=editors.Text.extend({defaultValue:0,events:_.extend({},editors.Text.prototype.events,{keypress:"onKeyPress"}),initialize:function(options){editors.Text.prototype.initialize.call(this,options),this.$el.attr("type","number")},onKeyPress:function(event){var self=this,delayedDetermineChange=function(){setTimeout(function(){self.determineChange()},0)};if(event.charCode==0){delayedDetermineChange();return}var newVal=this.$el.val()+String.fromCharCode(event.charCode),numeric=/^[0-9]*\.?[0-9]*?$/.test(newVal);numeric?delayedDetermineChange():event.preventDefault()},getValue:function(){var value=this.$el.val();return value===""?null:parseFloat(value,10)},setValue:function(value){value=function(){return _.isNumber(value)?value:_.isString(value)&&value!==""?parseFloat(value,10):null}(),_.isNaN(value)&&(value=null),editors.Text.prototype.setValue.call(this,value)}}),editors.Password=editors.Text.extend({initialize:function(options){editors.Text.prototype.initialize.call(this,options),this.$el.attr("type","password")}}),editors.TextArea=editors.Text.extend({tagName:"textarea"}),editors.Checkbox=editors.Base.extend({defaultValue:!1,tagName:"input",events:{click:function(event){this.trigger("change",this)},focus:function(event){this.trigger("focus",this)},blur:function(event){this.trigger("blur",this)}},initialize:function(options){editors.Base.prototype.initialize.call(this,options),this.$el.attr("type","checkbox")},render:function(){return this.setValue(this.value),this},getValue:function(){return this.$el.prop("checked")},setValue:function(value){value&&this.$el.prop("checked",!0)},focus:function(){if(this.hasFocus)return;this.$el.focus()},blur:function(){if(!this.hasFocus)return;this.$el.blur()}}),editors.Hidden=editors.Base.extend({defaultValue:"",initialize:function(options){editors.Text.prototype.initialize.call(this,options),this.$el.attr("type","hidden")},getValue:function(){return this.value},setValue:function(value){this.value=value},focus:function(){},blur:function(){}}),editors.Select=editors.Base.extend({tagName:"select",events:{change:function(event){this.trigger("change",this)},focus:function(event){this.trigger("focus",this)},blur:function(event){this.trigger("blur",this)}},initialize:function(options){editors.Base.prototype.initialize.call(this,options);if(!this.schema||!this.schema.options)throw"Missing required 'schema.options'"},render:function(){var options=this.schema.options,self=this;if(options instanceof Backbone.Collection){var collection=options;collection.length>0?this.renderOptions(options):collection.fetch({success:function(collection){self.renderOptions(options)}})}else _.isFunction(options)?options(function(result){self.renderOptions(result)}):this.renderOptions(options);return this},renderOptions:function(options){var $select=this.$el,html;_.isString(options)?html=options:_.isArray(options)?html=this._arrayToHtml(options):options instanceof Backbone.Collection&&(html=this._collectionToHtml(options)),$select.html(html),this.setValue(this.value)},getValue:function(){return this.$el.val()},setValue:function(value){this.$el.val(value)},focus:function(){if(this.hasFocus)return;this.$el.focus()},blur:function(){if(!this.hasFocus)return;this.$el.blur()},_collectionToHtml:function(collection){var array=[];collection.each(function(model){array.push({val:model.id,label:model.toString()})});var html=this._arrayToHtml(array);return html},_arrayToHtml:function(array){var html=[];return _.each(array,function(option){if(_.isObject(option)){var val=option.val?option.val:"";html.push('<option value="'+val+'">'+option.label+"</option>")}else html.push("<option>"+option+"</option>")}),html.join("")}}),editors.Radio=editors.Select.extend({tagName:"ul",className:"bbf-radio",events:{"click input[type=radio]:not(:checked)":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 self=this;setTimeout(function(){if(self.$("input[type=radio]:focus")[0])return;self.trigger("blur",self)},0)}},getValue:function(){return this.$("input[type=radio]:checked").val()},setValue:function(value){this.$("input[type=radio]").val([value])},focus:function(){if(this.hasFocus)return;var checked=this.$("input[type=radio]:checked");if(checked[0]){checked.focus();return}this.$("input[type=radio]").first().focus()},blur:function(){if(!this.hasFocus)return;this.$("input[type=radio]:focus").blur()},_arrayToHtml:function(array){var html=[],self=this;return _.each(array,function(option,index){var itemHtml="<li>";if(_.isObject(option)){var val=option.val?option.val:"";itemHtml+='<input type="radio" name="'+self.id+'" value="'+val+'" id="'+self.id+"-"+index+'" />',itemHtml+='<label for="'+self.id+"-"+index+'">'+option.label+"</label>"}else itemHtml+='<input type="radio" name="'+self.id+'" value="'+option+'" id="'+self.id+"-"+index+'" />',itemHtml+='<label for="'+self.id+"-"+index+'">'+option+"</label>";itemHtml+="</li>",html.push(itemHtml)}),html.join("")}}),editors.Checkboxes=editors.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 self=this;setTimeout(function(){if(self.$("input[type=checkbox]:focus")[0])return;self.trigger("blur",self)},0)}},getValue:function(){var values=[];return this.$("input[type=checkbox]:checked").each(function(){values.push($(this).val())}),values},setValue:function(values){_.isArray(values)||(values=[values]),this.$("input[type=checkbox]").val(values)},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(array){var html=[],self=this;return _.each(array,function(option,index){var itemHtml="<li>";if(_.isObject(option)){var val=option.val?option.val:"";itemHtml+='<input type="checkbox" name="'+self.id+'" value="'+val+'" id="'+self.id+"-"+index+'" />',itemHtml+='<label for="'+self.id+"-"+index+'">'+option.label+"</label>"}else itemHtml+='<input type="checkbox" name="'+self.id+'" value="'+option+'" id="'+self.id+"-"+index+'" />',itemHtml+='<label for="'+self.id+"-"+index+'">'+option+"</label>";itemHtml+="</li>",html.push(itemHtml)}),html.join("")}}),editors.Object=editors.Base.extend({hasNestedForm:!0,className:"bbf-object",initialize:function(options){this.value={},editors.Base.prototype.initialize.call(this,options);if(!this.schema.subSchema)throw new Error("Missing required 'schema.subSchema' option for Object editor")},render:function(){return this.form=new Form({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(value){this.value=value,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(),Backbone.View.prototype.remove.call(this)},validate:function(){return this.form.validate()},_observeFormEvents:function(){this.form.on("all",function(){args=_.toArray(arguments),args[1]=this,this.trigger.apply(this,args)},this)}}),editors.NestedModel=editors.Object.extend({initialize:function(options){editors.Base.prototype.initialize.call(this,options);if(!options.schema.model)throw'Missing required "schema.model" option for NestedModel editor'},render:function(){var data=this.value||{},key=this.key,nestedModel=this.schema.model,nestedModelSchema=nestedModel.prototype.schema;return _.isFunction(nestedModelSchema)&&(nestedModelSchema=nestedModelSchema()),this.form=new Form({schema:nestedModelSchema,model:new nestedModel(data),idPrefix:this.id+"_",fieldTemplate:"nestedField"}),this._observeFormEvents(),this.$el.html(this.form.render().el),this.hasFocus&&this.trigger("blur",this),this},commit:function(){var error=this.form.commit();return error?(this.$el.addClass("error"),error):editors.Object.prototype.commit.call(this)}}),editors.Date=editors.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 self=this;setTimeout(function(){if(self.$("select:focus")[0])return;self.trigger("blur",self)},0)}},initialize:function(options){options=options||{},editors.Base.prototype.initialize.call(this,options);var Self=editors.Date,today=new Date;this.options=_.extend({monthNames:Self.monthNames,showMonthNames:Self.showMonthNames},options),this.schema=_.extend({yearStart:today.getFullYear()-100,yearEnd:today.getFullYear()},options.schema||{}),this.value&&!_.isDate(this.value)&&(this.value=new Date(this.value));if(!this.value){var date=new Date;date.setSeconds(0),date.setMilliseconds(0),this.value=date}},render:function(){var options=this.options,schema=this.schema,datesOptions=_.map(_.range(1,32),function(date){return'<option value="'+date+'">'+date+"</option>"}),monthsOptions=_.map(_.range(0,12),function(month){var value=options.showMonthNames?options.monthNames[month]:month+1;return'<option value="'+month+'">'+value+"</option>"}),yearsOptions=_.map(_.range(schema.yearStart,schema.yearEnd+1),function(year){return'<option value="'+year+'">'+year+"</option>"}),$el=$(Form.templates.date({dates:datesOptions.join(""),months:monthsOptions.join(""),years:yearsOptions.join("")}));return this.$date=$el.find('select[data-type="date"]'),this.$month=$el.find('select[data-type="month"]'),this.$year=$el.find('select[data-type="year"]'),this.$hidden=$('<input type="hidden" name="'+this.key+'" />'),$el.append(this.$hidden),this.setValue(this.value),this.setElement($el),this.$el.attr("id",this.id),this.hasFocus&&this.trigger("blur",this),this},getValue:function(){var year=this.$year.val(),month=this.$month.val(),date=this.$date.val();return!year||!month||!date?null:new Date(year,month,date)},setValue:function(date){this.$date.val(date.getDate()),this.$month.val(date.getMonth()),this.$year.val(date.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 val=this.getValue();_.isDate(val)&&(val=val.toISOString()),this.$hidden.val(val)}},{showMonthNames:!0,monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"]}),editors.DateTime=editors.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 self=this;setTimeout(function(){if(self.$("select:focus")[0])return;self.trigger("blur",self)},0)}},initialize:function(options){options=options||{},editors.Base.prototype.initialize.call(this,options),this.options=_.extend({DateEditor:editors.DateTime.DateEditor},options),this.schema=_.extend({minsInterval:15},options.schema||{}),this.dateEditor=new this.options.DateEditor(options),this.value=this.dateEditor.value},render:function(){function pad(n){return n<10?"0"+n:n}var schema=this.schema,hoursOptions=_.map(_.range(0,24),function(hour){return'<option value="'+hour+'">'+pad(hour)+"</option>"}),minsOptions=_.map(_.range(0,60,schema.minsInterval),function(min){return'<option value="'+min+'">'+pad(min)+"</option>"}),$el=$(Form.templates.dateTime({date:'<b class="bbf-tmp"></b>',hours:hoursOptions.join(),mins:minsOptions.join()}));return $el.find(".bbf-tmp").replaceWith(this.dateEditor.render().el),this.$hour=$el.find('select[data-type="hour"]'),this.$min=$el.find('select[data-type="min"]'),this.$hidden=$el.find('input[type="hidden"]'),this.setValue(this.value),this.setElement($el),this.$el.attr("id",this.id),this.hasFocus&&this.trigger("blur",this),this},getValue:function(){var date=this.dateEditor.getValue(),hour=this.$hour.val(),min=this.$min.val();return!date||!hour||!min?null:(date.setHours(hour),date.setMinutes(min),date)},setValue:function(date){_.isDate(date)||(date=new Date(date)),this.dateEditor.setValue(date),this.$hour.val(date.getHours()),this.$min.val(date.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 val=this.getValue();_.isDate(val)&&(val=val.toISOString()),this.$hidden.val(val)},remove:function(){this.dateEditor.remove(),editors.Base.prototype.remove.call(this)}},{DateEditor:editors.Date}),editors}(),Form.setTemplates=Form.helpers.setTemplates,Form.setTemplateCompiler=Form.helpers.setTemplateCompiler,Form.templates={},Form.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> </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> </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"}),Form})