From df3b9fddcba80e07122a8f864328da9c651e3c1a Mon Sep 17 00:00:00 2001 From: Johannes Wachter Date: Tue, 29 Apr 2014 17:24:41 +0200 Subject: [PATCH 01/11] reactored deferreds and extend interface --- dist/validation.js | 49 ++++++++++++++++++++++-------------------- dist/validation.min.js | 2 +- js/element.js | 2 +- js/form.js | 38 ++++++++++++++++---------------- js/mapper.js | 5 +++-- js/types/default.js | 4 +++- 6 files changed, 53 insertions(+), 47 deletions(-) diff --git a/dist/validation.js b/dist/validation.js index 69d30bb..b6d1796 100644 --- a/dist/validation.js +++ b/dist/validation.js @@ -340,7 +340,7 @@ define('form/element',['form/util'], function(Util) { var addFunction = function(typeName, options) { this.requireCounter++; require(['type/' + typeName], function(Type) { - type = new Type(this.$el, options); + type = new Type(this.$el, options, form); type.initialized.then(function() { Util.debug('Element Type', typeName, options); @@ -1132,9 +1132,10 @@ define('form/mapper',[ // define mapper interface result = { - setData: function(data) { + setData: function(data, $el) { this.collectionsSet = {}; - return that.setData.call(this, data); + + return that.setData.call(this, data, $el); }, getData: function($el) { @@ -1295,23 +1296,17 @@ define('form',[ validationSubmitEvent: true, // avoid submit if not valid mapper: true // mapper on/off }, - dfd = null, // private functions that = { initialize: function() { - // init initialized - dfd = $.Deferred(); - this.requireCounter = 0; - this.initialized = dfd.promise(); - this.$el = $(el); this.options = $.extend(defaults, this.$el.data(), options); // enable / disable debug Util.debugEnabled = this.options.debug; - that.initFields.call(this); + this.initialized = that.initFields.call(this); if (!!this.options.validation) { this.validation = new Validation(this); @@ -1327,20 +1322,22 @@ define('form',[ }, // initialize field objects - initFields: function() { - $.each(Util.getFields(this.$el), function(key, value) { - this.requireCounter++; - that.addField.call(this, value, false).initialized.then(function() { - that.resolveInitialization.call(this); - }.bind(this)); + initFields: function($el) { + var dfd = $.Deferred(), + requireCounter = 0, + resolve = function() { + requireCounter--; + if (requireCounter === 0) { + dfd.resolve(); + } + }; + + $.each(Util.getFields($el || this.$el), function(key, value) { + requireCounter++; + that.addField.call(this, value, false).initialized.then(resolve.bind(this)); }.bind(this)); - }, - resolveInitialization: function() { - this.requireCounter--; - if (this.requireCounter === 0) { - dfd.resolve(); - } + return dfd.promise(); }, bindValidationDomEvents: function() { @@ -1383,6 +1380,10 @@ define('form',[ return element; }, + initFields: function($el) { + return that.initFields.call(this, $el); + }, + removeField: function(selector) { var $element = $(selector), el = $element.data('element'); @@ -1419,7 +1420,7 @@ define('type/default',[ - return function($el, defaults, options, name, typeInterface) { + return function($el, defaults, options, name, typeInterface, form) { var that = { initialize: function() { @@ -1440,6 +1441,8 @@ define('type/default',[ defaultInterface = { name: name, + form: form, + needsValidation: function() { return true; }, diff --git a/dist/validation.min.js b/dist/validation.min.js index 1be9589..78632c4 100644 --- a/dist/validation.min.js +++ b/dist/validation.min.js @@ -1 +1 @@ -define("form/util",[],function(){var e=["form","validation"];return{debugEnabled:!1,getFields:function(e){return $(e).find('input:not([data-form="false"], [type="submit"], [type="button"]), textarea:not([data-form="false"]), select:not([data-form="false"]), *[data-form="true"], *[data-type="collection"], *[contenteditable="true"]')},parseData:function(e,t,n){var r=$(e);return this.buildOptions(r.data(),t,"",n)},buildOptions:function(t,n,r,i){r||(r=""),i||(i={});var s=$.extend({},i,{}),o=n+this.ucFirst(r);return $.each(t,function(t,r){var i=new RegExp("^"+o);i.test(t)&&$.inArray(t,e)===-1&&(t!==o?t=t.replace(i,""):t=t.replace(new RegExp("^"+n),""),t!==""&&(t=this.lcFirst(t),s[t]=r))}.bind(this)),s},isValueField:function(e){var t=$(e);return t.is("input, select, textarea, option, button")},getValue:function(e){var t=$(e);return this.isValueField(t)?t.val():t.html()},setValue:function(e,t){var n=$(e);this.isValueField(n)?n.val(t):n.html(t)},debug:function(e,t,n){!this.debugEnabled||(e?t?n?console.log("Husky Validation:",e,t,n):console.log("Husky Validation:",e,t):console.log("Husky Validation:",e):console.log("Husky Validation"))},ucFirst:function(e){e+="";var t=e.charAt(0).toUpperCase();return t+e.substr(1)},lcFirst:function(e){return e.charAt(0).toLowerCase()+e.slice(1)},startsWith:function(e,t){return e.indexOf(t)===0},print:function(e,t){t||(t=1);var n="",r="    ",i,s,o="",u=0;while(u":(s.length>7&&(s=s.substring(0,6)+" ..."),n+=o+i+": '"+s+"';
"):n+=o+i+": {
"+o+r+print(s,t++)+"}");return n},isNumeric:function(e){return e.match(/-?\d+(.\d+)?/)}}}),define("form/element",["form/util"],function(e){return function(t,n,r){var i={type:null,validationTrigger:"focusout",validationAddClasses:!0,validationAddClassesParent:!0,validationErrorClass:"husky-validate-error",validationClass:"husky-validate",validation:!0},s=["validation","validationTrigger","validationAddClasses","validationAddClassesParent","validationClass","validationErrorClass","validationSubmitEvent"],o,u={},a,f=null,l=null,c={initialize:function(){l=$.Deferred(),this.requireCounter=0,this.initialized=l.promise(),this.$el=$(t),this.$el.data("element",this),this.options=$.extend({},i,r),!this.options.validationAddClasses||this.$el.addClass(this.options.validationClass),!this.options.validation||c.initValidation.call(this)},resolveInitialization:function(){this.requireCounter--,this.requireCounter===0&&l.resolve()},initValidation:function(){c.bindValidationDomEvents.call(this),c.initValidators.call(this),c.initType.call(this)},bindValidationDomEvents:function(){var e=this.options.validationTrigger?this.options.validationTrigger:"";if(e===""||e==="none")return;this.$el.is("select")&&(e+=(new RegExp("change","i")).test(e)?"":" change"),e=e.replace(/^\s+/g,"").replace(/\s+$/g,""),this.$el.bind(e,this.validate.bind(this))},initValidators:function(){var t=function(t,r){this.requireCounter++,require(["validator/"+t],function(i){u[t]=new i(this.$el,n,this,r),e.debug("Element Validator",t,r),c.resolveInitialization.call(this)}.bind(this))}.bind(this);$.each(this.options,function(n,r){if(!!r&&$.inArray(n,s)===-1&&e.startsWith(n,"validation")){var i=e.lcFirst(n.replace("validation","")),o=e.buildOptions(this.options,"validation",i);t(i,o)}}.bind(this)),this.$el.attr("required")==="required"&&!u.required&&t("required",{required:!0}),!!this.$el.attr("min")&&!u.min&&t("min",{min:parseInt(this.$el.attr("min"),10)}),!!this.$el.attr("max")&&!u.max&&t("max",{max:parseInt(this.$el.attr("max"),10)}),!!this.$el.attr("pattern")&&!u.pattern&&t("regex",{regex:this.$el.attr("pattern")})},initType:function(){var t=function(t,n){this.requireCounter++,require(["type/"+t],function(r){a=new r(this.$el,n),a.initialized.then(function(){e.debug("Element Type",t,n),c.resolveInitialization.call(this)}.bind(this))}.bind(this))}.bind(this),n=e.buildOptions(this.options,"type"),r,i;this.options.type?r=this.options.type:this.$el.attr("type")?(i=this.$el.attr("type"),i==="email"?r="email":i==="url"?r="url":i==="number"?r="decimal":i==="date"?(r="date",!n.format||(n.format="d")):i==="time"?(r="date",!n.format||(n.format="t")):i==="datetime"?r="date":r="string"):r="string",t(r,n)},hasConstraints:function(){var e=!!a&&a.needsValidation(),t=Object.keys(u).length>0;return t||e},needsValidation:function(){return f!==e.getValue(this.$el)},reset:function(){var e=this.$el;!this.options.validationAddClassesParent||(e=e.parent()),e.removeClass(this.options.validationErrorClass)},setValid:function(e){o=e;if(!!this.options.validationAddClasses){c.reset.call(this);var t=this.$el;!this.options.validationAddClassesParent||(t=t.parent()),e||t.addClass(this.options.validationErrorClass)}}},h={validate:function(t){if(t||c.needsValidation.call(this)){if(!c.hasConstraints.call(this))return!0;var n=!0;$.each(u,function(e,t){t.validate()||(n=!1)}),a!==null&&!a.validate()&&(n=!1),n||e.debug("Field validate",n?"true":"false",this.$el),c.setValid.call(this,n)}return this.isValid()},update:function(){if(!c.hasConstraints.call(this))return!0;var t=!0;return $.each(u,function(e,n){n.update()||(t=!1)}),a!==null&&!a.validate()&&(t=!1),t||e.debug("Field validate",t?"true":"false",this.$el),c.setValid.call(this,t),t},isValid:function(){return o},updateConstraint:function(e,t){if(!($.inArray(e,Object.keys(u))>-1))throw"No constraint with name: "+e;u[e].updateConstraint(t),this.validate()},deleteConstraint:function(e){if(!($.inArray(e,Object.keys(u))>-1))throw"No constraint with name: "+e;delete u[e],this.validate(!0)},addConstraint:function(e,t){if($.inArray(e,Object.keys(u))!==-1)throw"Constraint with name: "+e+" already exists";require(["validator/"+e],function(r){u[e]=new r(this.$el,n,this,t)}.bind(this))},hasConstraint:function(e){return!!u[e]},getConstraint:function(e){return this.hasConstraint(e)?u[e]:!1},fieldAdded:function(e){$.each(u,function(t,n){n.fieldAdded(e)})},fieldRemoved:function(e){$.each(u,function(t,n){n.fieldRemoved(e)})},setValue:function(e){a.setValue(e)},getValue:function(e){return a.getValue(e)},getType:function(){return a}};return c.initialize.call(h),h}}),define("form/validation",["form/util"],function(e){return function(t){var n,r={initialize:function(){r.bindValidationDomEvents.call(this),e.debug("INIT Validation")},bindValidationDomEvents:function(){!t.options.validationSubmitEvent||t.$el.on("submit",function(){return t.validation.validate()}.bind(this))},setValid:function(e){n=e}},i={validate:function(n){var i=!0,s=!1;return $.each(t.elements,function(e,t){t.validate(n)||(s||(t.$el.focus(),s=!0),i=!1)}),r.setValid.call(this,i),e.debug("Validation",i?"success":"error"),i},isValid:function(){return n},updateConstraint:function(e,t,n){var r=$(e);if(!r.data("element"))throw"No validation element";$(e).data("element").updateConstraint(t,n)},deleteConstraint:function(e,t){var n=$(e);if(!n.data("element"))throw"No validation element";n.data("element").deleteConstraint(t)},addConstraint:function(e,n,r){var i=$(e),s;i.data("element")?i.data("element").addConstraint(n,r):(s=t.addField(e),s.addConstraint(n,r),t.elements.push(s))}};return r.initialize.call(i),i}}),define("form/mapper",["form/util"],function(e){return function(t){var n={},r={initialize:function(){e.debug("INIT Mapper"),this.collections=[],this.collectionsSet={},this.templates={},this.elements=[],this.collectionsInitiated=$.Deferred(),t.initialized.then(function(){var e='*[data-type="collection"]',n=t.$el.find(e);n.each(r.initCollection.bind(this))}.bind(this))},initCollection:function(n,i){var s=$(i),o=s.data("element"),u=s.data("mapper-property"),a,f,l=$.Deferred(),c=0,h=function(){c--,c===0&&l.resolve()};if(!$.isArray(u)){if(typeof u!="object")throw"no valid mapper-property value";u=[u],s.data("mapper-property",u)}return o.$children=s.children().clone(!0),s.html(""),f={id:_.uniqueId("collection_"),property:u,$element:s,element:o},this.collections.push(f),c+=o.$children.length,o.$children.each(function(e,t){var n=$(t),i,s,l,c=0,p=function(){c--,c===0&&h()};if(!n.is("script"))throw"template has to be defined as