-
Notifications
You must be signed in to change notification settings - Fork 0
/
be-formidable.ts
123 lines (110 loc) · 4.14 KB
/
be-formidable.ts
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import {BE, propDefaults, propInfo} from 'be-enhanced/BE.js';
import {BEConfig, EnhancementInfo} from 'be-enhanced/types';
import {XE} from 'xtal-element/XE.js';
import {Actions, AllProps, AP, PAP, ProPAP, POA} from './types';
export class BeFormidable extends BE<AP, Actions, HTMLFormElement> implements Actions{
static override get beConfig(){
return {
parse: true,
} as BEConfig
}
#originalCheckValidity!: () => boolean;
override async attach(enhancedElement: HTMLFormElement, enhancementInfo: EnhancementInfo) {
const checkValidity = enhancedElement.checkValidity;
this.#originalCheckValidity = checkValidity.bind(enhancedElement);
await super.attach(enhancedElement, enhancementInfo);
}
async onInvalidIf(self: this) {
const {invalidIf, enhancedElement} = self;
const {evalInvalidIf} = await import('./evalInvalidIf.js');
enhancedElement.checkValidity = () => {
if(!this.#originalCheckValidity()){
self.objections = ['']; //TODO: Gather all the invalid messages
self.isValid = false;
return false;
}
const messages = evalInvalidIf(self, enhancedElement);
const valid = messages.length === 0;
this.markStatus(enhancedElement, valid);
self.objections = messages;
self.isValid = valid;
return valid;
}
enhancedElement.classList.add('be-formidable')
self.checkValidityAttached = true;
self.resolved = true;
}
markStatus(target:HTMLFormElement, valid: boolean){
if(valid){
target.classList.remove('invalid');
target.classList.add('valid');
}else{
target.classList.remove('valid');
target.classList.add('invalid');
}
}
onCheckValidityOn(self: this): void {
const {checkValidityOn, enhancedElement} = self;
this.disconnect();
this.#abortControllers = [];
if(typeof checkValidityOn === 'string'){
const abortController = new AbortController();
this.#abortControllers.push(abortController);
enhancedElement.addEventListener(checkValidityOn, e => {
enhancedElement.checkValidity();
}, {signal: abortController.signal});
}else{
for(const checkOn of checkValidityOn!){
const abortController = new AbortController();
this.#abortControllers.push(abortController);
if(typeof checkOn === 'string'){
enhancedElement.addEventListener(checkOn, e => {
enhancedElement.checkValidity();
}, {signal: abortController.signal});
}else{
const options = {...checkOn.options || {}, signal: abortController.signal}
enhancedElement.addEventListener(checkOn.type, e => {
enhancedElement.checkValidity();
}, options);
}
}
}
}
onCheckValidityOnInit(self: this): void {
const {enhancedElement} = self;
enhancedElement.checkValidity();
}
#abortControllers: AbortController[] | undefined;
disconnect(){
if(this.#abortControllers !== undefined){
for(const abortController of this.#abortControllers){
abortController.abort();
}
}
}
override detach(detachedElement: HTMLFormElement): void {
this.disconnect();
}
}
export interface BeFormidable extends AllProps{}
export const tagName = 'be-formidable';
const xe = new XE<AP, Actions>({
config:{
tagName,
propDefaults: {
...propDefaults,
checkValidityOnInit: true,
},
propInfo: {
...propInfo
},
actions: {
onInvalidIf: 'invalidIf',
onCheckValidityOn: 'checkValidityOn',
onCheckValidityOnInit: {
ifAllOf: ['checkValidityOnInit', 'checkValidityAttached']
}
}
},
superclass: BeFormidable
});