From 1771eeb338d4c5e637d29bcc0c3f741071e209bb Mon Sep 17 00:00:00 2001 From: robinknaapen Date: Wed, 2 May 2018 18:04:48 +0200 Subject: [PATCH] Add support for select --- serializer.js | 187 ++++++++++++++++++++---------------- tests/main.go | 25 ++++- tests/templates/test.gohtml | 8 ++ 3 files changed, 131 insertions(+), 89 deletions(-) diff --git a/serializer.js b/serializer.js index 6aad771..a206ffc 100644 --- a/serializer.js +++ b/serializer.js @@ -1,4 +1,4 @@ -HTMLElement.prototype.isChildOf = function(parent){ +HTMLElement.prototype.isChildOf = function(parent) { var node = this.parentNode; while (node != null) { if (node == parent) { @@ -7,7 +7,7 @@ HTMLElement.prototype.isChildOf = function(parent){ node = node.parentNode; } return false; -} +}; class SerializerField { /** @@ -16,11 +16,11 @@ class SerializerField { * @param {HTMLElement} f Input field (input|select|textarea) * @returns {SerializerField} */ - constructor(f){ + constructor(f) { this.name; this.parent; this.field = f; - this.required = f.required + this.required = f.required; this.type = this.field.getAttribute("type"); } @@ -29,23 +29,36 @@ class SerializerField { * * @returns {(String|Number|Boolean|Date)} */ - serialize(){ - if(this.type == "number" || this.type == "range"){ + serialize() { + if (this.field.tagName == "SELECT" && this.field.multiple) { + return Array.apply(null, this.field.options).filter(o => o.selected).map(o => o.value) + } + + if (this.type == "number" || this.type == "range") { return Number(this.field.value); - } else if(this.type == "date" || this.type == "datetime-local" || this.type == "month" || this.type == "week") { + } + + if ( + this.type == "date" || + this.type == "datetime-local" || + this.type == "month" || + this.type == "week" + ) { return new Date(this.field.value); - } else if(this.type == "checkbox") { + } + + if (this.type == "checkbox") { let checked = this.field.checked; - if(this.field.hasAttribute("string")){ - if(!checked) { + if (this.field.hasAttribute("string")) { + if (!checked) { return null; } - return this.field.value + return this.field.value; } return checked; - } else { - return this.field.value; - } + } + + return this.field.value; } } @@ -56,8 +69,10 @@ class Serializer { * @param {HTMLElement} element * @returns {Serializer} */ - constructor(element){ - let fields = element.querySelectorAll(`:scope input:not([type="submit"]), :scope select, :scope textarea, :scope group`); + constructor(element) { + 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"; @@ -67,8 +82,8 @@ class Serializer { this.required = element.getAttribute("required") !== null || this.min != -1; - for(let f of fields){ - if(f.isChildOf(element) && groups.every(g => !f.isChildOf(g))){ + for (let f of fields) { + if (f.isChildOf(element) && groups.every(g => !f.isChildOf(g))) { this.addField(f); } } @@ -79,39 +94,41 @@ class Serializer { * * @param {HTMLElement} f */ - addField(f){ + addField(f) { let fieldName = f.getAttribute("name"); - let isArray = fieldName.match(/^\[(\d*)\]/) + let isArray = fieldName.match(/^\[(\d*)\]/); - fieldName = fieldName.replace(/^\[\d*\]/, ''); + fieldName = fieldName.replace(/^\[\d*\]/, ""); + + console.log(f) let field; - if(f.tagName == "GROUP"){ - field = new Serializer(f) + if (f.tagName == "GROUP") { + field = new Serializer(f); } else { field = new SerializerField(f); } - if(field.type == "file"){ + if (field.type == "file") { return; } field.name = fieldName; field.parent = this; - f.serializer = field + f.serializer = field; - if(isArray){ - if(!this._fields.has(fieldName)){ - this._fields.set(fieldName, []) + if (isArray) { + if (!this._fields.has(fieldName)) { + this._fields.set(fieldName, []); } - if(isArray[1] != ""){ - this._fields.get(fieldName)[isArray[1]] = field + if (isArray[1] != "") { + this._fields.get(fieldName)[isArray[1]] = field; } else { - this._fields.get(fieldName).push(field) + this._fields.get(fieldName).push(field); } } else { - this._fields.set(fieldName, field) + this._fields.set(fieldName, field); } } @@ -120,12 +137,12 @@ class Serializer { * * @param {(HTMLElement|Serializer|SerializerField)} f Serializer child */ - removeField(f){ - if(this._fields.has(f.name)){ - let fields = this._fields.get(f.name) - if(Array.isArray(fields)){ + removeField(f) { + if (this._fields.has(f.name)) { + let fields = this._fields.get(f.name); + if (Array.isArray(fields)) { let index = fields.indexOf(f); - this._fields.set(f.name, fields.splice(index, 1)) + this._fields.set(f.name, fields.splice(index, 1)); } else { this._fields.delete(); } @@ -137,20 +154,20 @@ class Serializer { * * @returns {Object} */ - serialize(){ + serialize() { let json = {}; - for(let [k, f] of this._fields){ - if(Array.isArray(f)){ - if(k != ""){ + for (let [k, f] of this._fields) { + if (Array.isArray(f)) { + if (k != "") { json[k] = []; } else { json = []; } - for(let key in f){ - if(f[key]){ + for (let key in f) { + if (f[key]) { let d = f[key].serialize(); - if(d !== null){ - if(k == ""){ + if (d !== null) { + if (k == "") { json[key] = d; continue; } @@ -160,14 +177,14 @@ class Serializer { } } else { let d = f.serialize(); - if(f !== null){ - if(k == ""){ - json = d + if (f !== null) { + if (k == "") { + json = d; continue; } - json[k] = d + json[k] = d; } - } + } } return json; } @@ -181,18 +198,18 @@ class Validator { * @param {(erializer|SerializerField)} field * @returns {Object} */ - static validateRequired(field){ + static validateRequired(field) { let e = { valid: true, - errors: {}, - } + errors: {} + }; let v; - if(field instanceof Serializer){ + if (field instanceof Serializer) { v = Validator.validateRequiredSerializer(field); } else { - v = Validator.validateRequiredSerialzerField(field) + v = Validator.validateRequiredSerialzerField(field); } - if(!v.valid){ + if (!v.valid) { e.valid = false; e.errors = v.errors; } @@ -206,43 +223,43 @@ class Validator { * @param {Serializer} field * @returns {Object} */ - static validateRequiredSerializer(field){ + static validateRequiredSerializer(field) { let e = { valid: true, - errors: {}, - } - + errors: {} + }; + let min = field.min; let validFieldsCount = 0; - for(let [k, f] of field._fields){ - if(Array.isArray(f)){ + for (let [k, f] of field._fields) { + if (Array.isArray(f)) { e.errors = { - message: null, + message: null }; let validCount = 0; - for(let sf of f){ - if(!(sf.name in e.errors)){ + 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); + let v = Validator.validateRequired(sf); + if (!v.valid) { + console.log(e.errors); + e.errors[sf.name].push(v.errors); continue; } - validCount++ + validCount++; } - - e.valid = min <= validCount - if(e.valid){ - e.errors = {} + + e.valid = min <= validCount; + if (e.valid) { + e.errors = {}; } else { - e.errors.message = `Should contain atleast ${min} value(s)` + e.errors.message = `Should contain atleast ${min} value(s)`; } } else { let v = Validator.validateRequired(f); - if(!v.valid){ + if (!v.valid) { e.valid = false; e.errors[f.name] = v.errors; } @@ -259,19 +276,19 @@ class Validator { * @param {SerializerField} field * @returns {Object} */ - static validateRequiredSerialzerField(field){ + static validateRequiredSerialzerField(field) { let e = { valid: true, - errors: {}, - } + errors: {} + }; - if(field.required || (field.parent && field.parent.required)){ - if(field.type != "checkbox"){ - e.valid = field.field.validity.valueMissing !== true - e.errors = "Is required" + 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" + e.valid = field.field.checked; + e.errors = "Not checked"; } } return e; diff --git a/tests/main.go b/tests/main.go index 4074621..a54198d 100644 --- a/tests/main.go +++ b/tests/main.go @@ -24,6 +24,10 @@ var testData = []*Person{ Surname: "Bar", Age: 57, BirthDate: time.Date(1960, 1, 1, 0, 0, 0, 0, time.UTC), + Animal: "Dog", + Checklist: []string{ + "Milk", + }, }, nil, &Person{ @@ -32,22 +36,26 @@ var testData = []*Person{ Age: 22, BirthDate: time.Date(1995, 1, 5, 0, 0, 0, 0, time.UTC), Languages: []Language{ - Language{ + { Language: "Dutch", SkillLevel: 9.99, Native: true, }, - Language{ + { Language: "English", SkillLevel: 8.4, Native: false, }, - Language{ + { Language: "Japanese", SkillLevel: -9000.9, Native: false, }, }, + Animal: "Dog", + Checklist: []string{ + "Milk", + }, }, } @@ -84,9 +92,11 @@ type Person struct { Age int `json:"age"` BirthDate time.Time `json:"birth_date"` Languages []Language `json:"languages"` + Checklist []string `json:"checklist"` + Animal string `json:"animal"` } -// Languages ... +// Language ... type Language struct { Language string `json:"language"` SkillLevel float64 `json:"skill_level"` @@ -129,14 +139,21 @@ func isEq(p1, p2 Person) { assert(p1.Surname, p2.Surname, "Surname") assert(p1.Age, p2.Age, "Age") assert(p1.BirthDate, p2.BirthDate, "BirthDate") + assert(p1.Animal, p2.Animal, "Animal") if !assert(len(p2.Languages), len(p1.Languages), "Languages length") { return } + if !assert(len(p2.Checklist), len(p1.Checklist), "Checklist length") { + return + } for k := range p2.Languages { assert(p1.Languages[k].Language, p2.Languages[k].Language, "Languages.Language") assert(p1.Languages[k].SkillLevel, p2.Languages[k].SkillLevel, "Languages.SkillLevel") assert(p1.Languages[k].Native, p2.Languages[k].Native, "Languages.Native") } + for k := range p2.Checklist { + assert(p1.Checklist[k], p2.Checklist[k], "Checklist") + } } func assert(v, v2 interface{}, ident string) bool { diff --git a/tests/templates/test.gohtml b/tests/templates/test.gohtml index 5947be9..b75098a 100644 --- a/tests/templates/test.gohtml +++ b/tests/templates/test.gohtml @@ -32,6 +32,14 @@ {{ end }} + + {{ end }} {{ end }}