-
Notifications
You must be signed in to change notification settings - Fork 0
/
addInputEventListeners.js
72 lines (66 loc) · 2.45 KB
/
addInputEventListeners.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import evaluatePostfixExpression from "./evaluatePostfixExpression.js";
export default function addInputEventListeners(form, schema, getValidationMessageElement) {
const handleInput = createInputHandler(form, schema, getValidationMessageElement);
Object.keys(schema.properties).forEach(property => {
const inputElement = form[property];
inputElement.addEventListener("input", handleInput);
});
}
function createInputHandler(form, schema, getValidationMessageElement) {
return () => {
const variables = extractVariables(form, schema);
for (const interpropertyExpression of schema.interpropertyExpressions) {
const {expression, type, message, properties} = interpropertyExpression;
const [isValid, error] = evaluateExpression(type, expression, variables);
if (error) throw error;
properties.forEach(property => {
const inputElement = form[property];
const validationMessageElement = getValidationMessageElement(inputElement);
if (!isValid) {
inputElement.setCustomValidity(message);
validationMessageElement.innerText = message;
} else {
inputElement.setCustomValidity("");
validationMessageElement.innerText = "";
}
});
}
};
}
function evaluateExpression(type, expression, variables) {
switch(type) {
case "postfix":
return evaluatePostfixExpression(expression, variables);
default:
throw new TypeError(`"${type}" expressions are not supported.`);
}
}
function extractVariables(form, schema) {
const variables = {};
for (const element of form.elements) {
const {name, value} = element;
const {type} = schema.properties[name];
variables[name] = cast(value, type);
}
return variables;
}
/**
* Casts a string to a JavaScript type based on the JSON Schema type.
*
* @see https://json-schema.org/understanding-json-schema/reference/type.html
*
* @param {string} value A string value.
* @param {string} type JSON Schema type.
* @returns {string|number|boolean} Potentially casted string value.
*/
function cast(value, type) {
switch(type) {
case "number":
case "integer":
return Number(value);
case "boolean":
return Boolean(value);
default:
return value;
}
}