1
1
import '../sass/tbxforms.scss' ;
2
2
3
3
/**
4
- * CustomEvent polyfill for IE11.
5
- * https://stackoverflow.com/a/26596324/1798491
4
+ * Updates the visibility of a form element based on conditional field values
5
+ * @param {HTMLElement } container - The container element to show/hide
6
+ * @param {NodeList } drivingFieldNodeList - List of form fields that control visibility
7
+ * @param {Array } conditionalValuesForElement - Values that should trigger showing the container
6
8
*/
7
- ( function ( ) {
8
- if ( typeof window . CustomEvent === 'function' ) return false ; //If not IE
9
-
10
- function CustomEvent ( event , params ) {
11
- params = params || { bubbles : false , cancelable : false , detail : undefined } ;
12
- var evt = document . createEvent ( 'CustomEvent' ) ;
13
- evt . initCustomEvent (
14
- event ,
15
- params . bubbles ,
16
- params . cancelable ,
17
- params . detail
18
- ) ;
19
- return evt ;
9
+ function updateVisibility (
10
+ container ,
11
+ drivingFieldNodeList ,
12
+ conditionalValuesForElement
13
+ ) {
14
+ let shouldShow = false ;
15
+
16
+ if ( drivingFieldNodeList . length > 1 ) {
17
+ // For checkboxes/radios, check if any are checked with matching values
18
+ drivingFieldNodeList . forEach ( function ( field ) {
19
+ if ( field . checked && conditionalValuesForElement . includes ( field . value ) ) {
20
+ shouldShow = true ;
21
+ }
22
+ } ) ;
23
+ } else {
24
+ // For single fields, check the value directly
25
+ const field = drivingFieldNodeList . item ( 0 ) ;
26
+ shouldShow =
27
+ conditionalValuesForElement . includes ( field . value ) ||
28
+ conditionalValuesForElement . includes ( Number ( field . value ) ) ;
20
29
}
21
30
22
- CustomEvent . prototype = window . Event . prototype ;
23
-
24
- window . CustomEvent = CustomEvent ;
25
- } ) ( ) ;
31
+ // Update visibility and aria states
32
+ container . hidden = ! shouldShow ;
33
+ drivingFieldNodeList . forEach ( ( field ) =>
34
+ field . setAttribute ( 'aria-expanded' , shouldShow . toString ( ) )
35
+ ) ;
36
+ }
26
37
38
+ /**
39
+ * Initializes form functionality with conditional field visibility
40
+ * @param {HTMLFormElement } form - The form element to initialize
41
+ * @constructor
42
+ */
27
43
function TbxForms ( form ) {
28
- this . form = form ;
44
+ this . form = form ; // Stash the TbxForms DOM element.
45
+ const self = this ; // Stash the TbxForms instance.
29
46
30
47
// Loop through all elements within the given form (e.g. inputs, divs, fieldsets).
31
48
form . querySelectorAll ( '*' ) . forEach ( function ( formElement ) {
@@ -42,7 +59,6 @@ function TbxForms(form) {
42
59
) ;
43
60
let conditionalValuesForElement ;
44
61
45
- // Try to parse the JSON containing required field mapping.
46
62
try {
47
63
conditionalValuesForElement = JSON . parse (
48
64
formElement . dataset . conditionalFieldValues
@@ -53,55 +69,31 @@ function TbxForms(form) {
53
69
54
70
container . classList . add ( 'tbxforms-conditional' ) ;
55
71
56
- if ( drivingFieldNodeList . length > 1 ) {
57
- // We're dealing with radios or checkboxes.
58
-
59
- drivingFieldNodeList . forEach ( function ( option_node ) {
60
- option_node . addEventListener ( 'change' , function ( ) {
61
- if (
62
- option_node . checked &&
63
- conditionalValuesForElement . includes ( option_node . value )
64
- ) {
65
- option_node . setAttribute ( 'aria-expanded' , 'true' ) ;
66
- container . hidden = false ;
67
- } else {
68
- option_node . setAttribute ( 'aria-expanded' , 'false' ) ;
69
- container . hidden = true ;
70
- }
71
- } ) ;
72
-
73
- // Trigger above event listener to correct presentation.
74
- option_node . dispatchEvent ( new CustomEvent ( 'change' ) ) ;
75
- } ) ;
76
- } else {
77
- // We're dealing with a single field.
78
-
79
- const drivingField = drivingFieldNodeList . item ( 0 ) ;
80
-
81
- drivingField . addEventListener ( 'change' , function ( ) {
82
- if (
83
- conditionalValuesForElement . includes ( drivingField . value ) ||
84
- conditionalValuesForElement . includes ( Number ( drivingField . value ) )
85
- ) {
86
- drivingField . setAttribute ( 'aria-expanded' , 'true' ) ;
87
- container . hidden = false ;
88
- } else {
89
- drivingField . setAttribute ( 'aria-expanded' , 'false' ) ;
90
- container . hidden = true ;
91
- }
72
+ // Set up change listeners
73
+ drivingFieldNodeList . forEach ( function ( field ) {
74
+ field . addEventListener ( 'change' , function ( ) {
75
+ updateVisibility (
76
+ container ,
77
+ drivingFieldNodeList ,
78
+ conditionalValuesForElement
79
+ ) ;
92
80
} ) ;
81
+ } ) ;
93
82
94
- // Trigger above event listener to correct presentation.
95
- drivingField . dispatchEvent ( new CustomEvent ( 'change' ) ) ;
96
- }
83
+ // Check initial state
84
+ updateVisibility (
85
+ container ,
86
+ drivingFieldNodeList ,
87
+ conditionalValuesForElement
88
+ ) ;
97
89
}
98
90
} ) ;
99
91
100
92
// Clear any values for fields that are conditionally hidden.
101
93
// NB. We don't use `form.elements.('[hidden]')` to include divs.
102
94
form . addEventListener ( 'submit' , function ( ) {
103
95
form . querySelectorAll ( '[hidden]' ) . forEach ( function ( hiddenFormElement ) {
104
- form . clearInput ( hiddenFormElement ) ;
96
+ self . clearInput ( hiddenFormElement ) ;
105
97
} ) ;
106
98
} ) ;
107
99
}
@@ -144,10 +136,8 @@ TbxForms.prototype.clearInput = function (node) {
144
136
break ;
145
137
146
138
default :
147
- console . error (
148
- "Unexpected node.type '" +
149
- node . type +
150
- "' found while trying to clearInput."
139
+ console . debug (
140
+ `Skipping unsupported node.type '${ node . type } ' while trying to clearInput().`
151
141
) ;
152
142
}
153
143
break ;
@@ -160,8 +150,7 @@ TbxForms.prototype.clearInput = function (node) {
160
150
node . selectedIndex = - 1 ;
161
151
break ;
162
152
163
- // If this is a container element run again for child elements.
164
- // NB. maybe a `default` case would be better here.
153
+ // If this is a container element, run again for child elements.
165
154
case 'DIV' :
166
155
case 'FIELDSET' :
167
156
node . querySelectorAll ( '*' ) . forEach ( function ( formElement ) {
@@ -170,10 +159,8 @@ TbxForms.prototype.clearInput = function (node) {
170
159
break ;
171
160
172
161
default :
173
- console . error (
174
- "Unexpected node.tagName '" +
175
- node . tagName +
176
- "' found while trying to clearInput."
162
+ console . debug (
163
+ `Skipping unsupported node.tagName '${ node . tagName } ' while trying to clearInput().`
177
164
) ;
178
165
}
179
166
} ;
0 commit comments