Serializer.js/serializer.js

259 lines
4.8 KiB
JavaScript
Raw Normal View History

2017-08-29 12:58:02 +02:00
HTMLElement.prototype.isChildOf = function(parent){
var node = this.parentNode;
while (node != null) {
if (node == parent) {
return true;
}
node = node.parentNode;
}
return false;
}
2017-08-26 23:44:47 +02:00
class SerializerField {
/**
* constructor
*
* @param {HTMLElement} f Input field (input|select|textarea)
* @returns {SerializerField}
*/
constructor(f){
2017-08-31 12:21:39 +02:00
this.name;
this.parent;
2017-08-26 23:44:47 +02:00
this.field = f;
2017-08-31 12:21:39 +02:00
this.required = f.required
this.type = this.field.getAttribute("type");
2017-08-26 23:44:47 +02:00
}
/**
* serialize
*
2017-08-31 12:21:39 +02:00
* @returns {(String|Number|Boolean|Date)}
2017-08-26 23:44:47 +02:00
*/
serialize(){
2017-08-31 12:21:39 +02:00
if(this.type == "number" || this.type == "range"){
2017-08-26 23:44:47 +02:00
return Number(this.field.value);
2017-08-31 12:21:39 +02:00
} else if(this.type == "date" || this.type == "datetime-local" || this.type == "month" || this.type == "week") {
2017-08-26 23:44:47 +02:00
return new Date(this.field.value);
2017-08-31 12:21:39 +02:00
} 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;
2017-08-26 23:44:47 +02:00
} else {
return this.field.value;
}
}
}
class Serializer {
/**
* constructor
*
* @param {HTMLElement} element
* @returns {Serializer}
*/
constructor(element){
2017-08-29 12:58:02 +02:00
let fields = element.querySelectorAll(`:scope input:not([type="submit"]), :scope select, :scope textarea, :scope group`);
let groups = [].slice.call(element.querySelectorAll(`:scope group`));
2017-08-26 23:44:47 +02:00
2017-08-31 12:21:39 +02:00
this.name = ":root";
this.parent;
2017-08-26 23:44:47 +02:00
this._fields = new Map();
2017-08-31 12:21:39 +02:00
this.min = Number(element.getAttribute("min") || -1);
this.required = element.getAttribute("required") !== null || this.min != -1;
2017-08-26 23:44:47 +02:00
for(let f of fields){
2017-08-29 12:58:02 +02:00
if(f.isChildOf(element) && groups.every(g => !f.isChildOf(g))){
this.addField(f);
}
2017-08-26 23:44:47 +02:00
}
}
/**
* addField
*
* @param {HTMLElement} f
*/
addField(f){
let fieldName = f.getAttribute("name");
let isArray = fieldName.match(/^\[(\d*)\]/)
2017-08-31 12:21:39 +02:00
fieldName = fieldName.replace(/^\[\d*\]/, '');
2017-08-26 23:44:47 +02:00
let field;
if(f.tagName == "GROUP"){
field = new Serializer(f)
} else {
2017-08-31 12:21:39 +02:00
field = new SerializerField(f);
2017-08-26 23:44:47 +02:00
}
2017-08-31 12:21:39 +02:00
field.name = fieldName;
field.parent = this;
f.serializer = field
2017-08-26 23:44:47 +02:00
if(isArray){
if(!this._fields.has(fieldName)){
this._fields.set(fieldName, [])
}
if(isArray[1] != ""){
this._fields.get(fieldName)[isArray[1]] = field
} else {
this._fields.get(fieldName).push(field)
}
} else {
this._fields.set(fieldName, field)
}
}
/**
* serialize
*
* @returns {Object}
*/
serialize(){
let json = {};
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]){
2017-08-31 12:21:39 +02:00
let d = f[key].serialize();
if(d !== null){
if(k == ""){
json[key] = d;
continue;
}
json[k][key] = d;
2017-08-26 23:44:47 +02:00
}
}
}
} else {
2017-08-31 12:21:39 +02:00
let d = f.serialize();
if(f !== null){
if(k == ""){
json = d
continue;
}
json[k] = d
2017-08-26 23:44:47 +02:00
}
}
}
return json;
}
}
2017-08-31 12:21:39 +02:00
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;
}
}