diff --git a/serializer.js b/serializer.js index 724da10..91d41cd 100644 --- a/serializer.js +++ b/serializer.js @@ -17,22 +17,33 @@ class SerializerField { * @returns {SerializerField} */ constructor(f){ + this.name; + this.parent; this.field = f; + this.required = f.required + this.type = this.field.getAttribute("type"); } /** * serialize * - * @returns {(String|Number)} + * @returns {(String|Number|Boolean|Date)} */ serialize(){ - let type = this.field.getAttribute("type"); - if(type == "number" || type == "range"){ + if(this.type == "number" || this.type == "range"){ return Number(this.field.value); - } else if(type == "date" || type == "datetime-local" || type == "month" || type == "week") { + } else if(this.type == "date" || this.type == "datetime-local" || this.type == "month" || this.type == "week") { return new Date(this.field.value); - } else if(type == "checkbox") { - return this.field.checked; + } else if(this.type == "checkbox") { + let checked = this.field.checked; + if(this.field.hasAttribute("string")){ + if(checked) { + return this.field.value + } else { + return null; + } + } + return checked; } else { return this.field.value; } @@ -50,7 +61,12 @@ class Serializer { let fields = element.querySelectorAll(`:scope input:not([type="submit"]), :scope select, :scope textarea, :scope group`); let groups = [].slice.call(element.querySelectorAll(`:scope group`)); + this.name = ":root"; + this.parent; this._fields = new Map(); + this.min = Number(element.getAttribute("min") || -1); + + this.required = element.getAttribute("required") !== null || this.min != -1; for(let f of fields){ if(f.isChildOf(element) && groups.every(g => !f.isChildOf(g))){ @@ -68,15 +84,20 @@ class Serializer { let fieldName = f.getAttribute("name"); let isArray = fieldName.match(/^\[(\d*)\]/) + fieldName = fieldName.replace(/^\[\d*\]/, ''); + let field; if(f.tagName == "GROUP"){ field = new Serializer(f) } else { - field = new SerializerField(f); + field = new SerializerField(f); } + field.name = fieldName; + field.parent = this; + + f.serializer = field if(isArray){ - fieldName = fieldName.replace(/^\[(\d*)\]/, ''); if(!this._fields.has(fieldName)){ this._fields.set(fieldName, []) } @@ -106,21 +127,132 @@ class Serializer { } for(let key in f){ if(f[key]){ - if(k == ""){ - json[key] = f[key].serialize() - continue; + let d = f[key].serialize(); + if(d !== null){ + if(k == ""){ + json[key] = d; + continue; + } + json[k][key] = d; } - json[k][key] = f[key].serialize() } } } else { - if(k == ""){ - json = f.serialize() - continue; + let d = f.serialize(); + if(f !== null){ + if(k == ""){ + json = d + continue; + } + json[k] = d } - json[k] = f.serialize() } } return json; } } + +class Validator { + /** + * validateRequired + * + * @static + * @param {(erializer|SerializerField)} field + * @returns {Object} + */ + static validateRequired(field){ + let e = { + valid: true, + errors: {}, + } + let v; + if(field instanceof Serializer){ + v = Validator.validateRequiredSerializer(field); + } else { + v = Validator.validateRequiredSerialzerField(field) + } + if(!v.valid){ + e.valid = false; + e.errors = v.errors; + } + return e; + } + + /** + * validateRequiredSerializer + * + * @static + * @param {Serializer} field + * @returns {Object} + */ + static validateRequiredSerializer(field){ + let e = { + valid: true, + errors: {}, + } + + let min = field.min; + let validFieldsCount = 0; + for(let [k, f] of field._fields){ + if(Array.isArray(f)){ + e.errors = { + message: null, + }; + let validCount = 0; + for(let sf of f){ + if(!(sf.name in e.errors)){ + e.errors[sf.name] = []; + } + + let v = Validator.validateRequired(sf) + if(!v.valid){ + console.log(e.errors) + e.errors[sf.name].push(v.errors); + continue; + } + validCount++ + } + + e.valid = min <= validCount + if(e.valid){ + e.errors = {} + } else { + e.errors.message = `Should contain atleast ${min} value(s)` + } + } else { + let v = Validator.validateRequired(f); + if(!v.valid){ + e.valid = false; + e.errors[f.name] = v.errors; + } + } + } + + return e; + } + + /** + * validateRequiredSerialzerField + * + * @static + * @param {SerializerField} field + * @returns {Object} + */ + static validateRequiredSerialzerField(field){ + let e = { + valid: true, + errors: {}, + } + + if(field.required || (field.parent && field.parent.required)){ + if(field.type != "checkbox"){ + e.valid = field.field.validity.valueMissing !== true + e.errors = "Is required" + } else { + e.valid = field.field.checked + e.errors = "Not checked" + } + } + return e; + } +}