-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathenforcer.js
120 lines (83 loc) · 3.1 KB
/
enforcer.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
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
/*
Author: Robert F. Popeleski <[email protected]>
License: MIT
This JavaScript library uses event monitoring to make form field
elements immutable and defend against constraint manipulations.
*/
"use strict";
function enforcer_assert(condition, message) {
if ( !condition ) {
throw message || "Assertion failed";
}
}
/*
watch: element id to enforce with desired attributes separated by periods
onManip: callback function to be called after change to detected
persist: reinsert element if deleted from the DOM
activate(): start Enforcer on new object
[PRIVATE] #_watch(): parser and validator for watch property
[PRIVATE] #_onManip(): on change event listener instantiator
[PRIVATE] #_persist(): on delete event listener instantiator
if an element id is passed to watch with no accompanying attributes, then all watchable attributes are enforced
i.e. ElementID => all attributes supported
i.e. ElementID.maxlength => enforce maxlength attribute
i.e. ElementID.maxlength.type => enforce maxlength and type attributes
*/
class Enforcer {
static #ERR_WATCH_STR = "Watched object must be passed as a string";
static #ERR_WATCH_ID = "Element with passed id does not exist";
constructor (watch, onManip, persist) {
this.watch = watch;
this.onManip = onManip;
this.persist = persist;
}
static #_onManip ( onManip, parent_ele, watch_list ) {
let i = 0;
let watch_list_l = watch_list.length;
for ( i; i < watch_list_l; i++ ) {
switch (watch_list[ i ]) {
case "maxlength":
let m = parent_ele.getAttribute("maxlength");
if(m) {
parent_ele.addEventListener('focusout', (e) => {
if(parent_ele.value.length > m) {
parent_ele.setAttribute("maxlength", m);
parent_ele.value = parent_ele.value.substring(0,m);
onManip();
}
});
}
break;
}
}
}
static #_persist ( onManip, parent_ele, watch_list ) {
let backup = parent_ele.cloneNode(true);
const observer = new MutationObserver(function(mutations_list) {
mutations_list.forEach(function(mutation) {
mutation.removedNodes.forEach(function(removed_node) {
if(removed_node.id == parent_ele.id) {
console.log(backup);
document.body.appendChild(backup);
Enforcer.#_onManip( onManip, backup, watch_list );
}
});
});
});
observer.observe(document.getElementsByTagName('body')[0], { subtree: false, childList: true });
}
static #_watch ( watch, onManip, persist ) {
enforcer_assert ( typeof watch === "string", Enforcer.#ERR_WATCH_STR+" ("+watch+")" );
let watch_list = watch.split( "." );
let parent_ele = null;
enforcer_assert ( typeof watch_list[ 0 ] === "string" && document.getElementById( watch_list[ 0 ] ) !== null, Enforcer.#ERR_WATCH_ID+" ("+watch_list[ 0 ]+")" );
parent_ele = document.getElementById(watch_list[0]);
watch_list.shift();
Enforcer.#_onManip( onManip, parent_ele, watch_list );
persist ? Enforcer.#_persist( onManip, parent_ele, watch_list ) : null;
}
activate () {
Enforcer.#_watch( this.watch, this.onManip, this.persist );
//Enforcer.#_persist( this.persist );
}
}