1
1
class EditorGenerator {
2
- constructor ( object , schema , formContainerId ) {
2
+ constructor ( object , schema , formContainer ) {
3
3
this . object = object ;
4
4
this . schema = schema ;
5
- this . formContainer = $ ( '#' + formContainerId ) ;
5
+ this . formContainer = formContainer ;
6
6
}
7
7
8
- generateEditor ( ignoreFields ) {
8
+ generateEditor ( ignoreFields = [ ] ) {
9
9
this . formContainer . empty ( ) ;
10
10
11
11
for ( const [ key , property ] of Object . entries ( this . schema ) ) {
12
12
if ( ignoreFields . includes ( key ) ) {
13
13
continue ;
14
14
}
15
15
16
- const label = $ ( '<label>' ) . text ( key ) . addClass ( 'property-editor-label' ) ;
16
+ const label = $ ( '<label>' )
17
+ . text ( key )
18
+ . addClass ( 'property-editor-label' ) ;
17
19
let input ;
18
-
19
- let propertyType = property . type ;
20
- if ( Array . isArray ( property . type ) ) {
21
- propertyType = property . type [ 0 ] ;
22
- if ( propertyType === 'array' ) {
23
- propertyType = 'arrayOf ' + property . items . type ;
24
- }
25
- }
20
+ const propertyType = Array . isArray ( property . type ) ? property . type [ 0 ] : property . type ;
26
21
27
22
switch ( propertyType ) {
28
23
case 'string' :
@@ -32,17 +27,14 @@ class EditorGenerator {
32
27
. val ( this . object [ key ] || '' )
33
28
. on ( 'change' , ( ) => {
34
29
this . object [ key ] = input . val ( ) ;
35
- } ) ; ;
36
-
37
- // Use jQuery UI datepicker
30
+ } ) ;
38
31
input . datepicker ( ) ;
39
32
} else if ( property . enum ) {
40
33
input = $ ( '<select>' )
41
34
. addClass ( 'property-editor-input' )
42
35
. on ( 'change' , ( ) => {
43
36
this . object [ key ] = input . val ( ) ;
44
37
} ) ;
45
-
46
38
property . enum . forEach ( ( option ) => {
47
39
input . append ( $ ( '<option>' ) . val ( option ) . text ( option ) ) ;
48
40
} ) ;
@@ -52,7 +44,7 @@ class EditorGenerator {
52
44
. val ( this . object [ key ] || '' )
53
45
. on ( 'change' , ( ) => {
54
46
this . object [ key ] = input . val ( ) ;
55
- } ) ; ;
47
+ } ) ;
56
48
}
57
49
break ;
58
50
@@ -77,8 +69,113 @@ class EditorGenerator {
77
69
} ) ;
78
70
break ;
79
71
72
+ case 'object' : {
73
+ const subContainer = $ ( '<div>' ) . addClass ( 'property-editor-object' ) . hide ( ) ;
74
+ const toggleButton = $ ( '<span>' )
75
+ . text ( '>' )
76
+ . addClass ( 'property-editor-toggle' )
77
+ . on ( 'click' , ( ) => {
78
+ subContainer . toggle ( ) ;
79
+ toggleButton . text ( toggleButton . text ( ) === '>' ? 'v' : '>' ) ;
80
+ } ) ;
81
+
82
+ const subObject = this . object [ key ] || { } ;
83
+ const subSchema = property . properties || { } ;
84
+
85
+ const subEditor = new EditorGenerator ( subObject , subSchema , '' ) ;
86
+ subEditor . formContainer = subContainer ; // Set the container manually
87
+ subEditor . generateEditor ( ) ;
88
+
89
+ this . object [ key ] = subObject ;
90
+
91
+ input = $ ( '<div>' )
92
+ . append ( toggleButton , label , subContainer ) ;
93
+ break ;
94
+ }
95
+
96
+ case 'array' : {
97
+ const arrayContainer = $ ( '<div>' ) . addClass ( 'property-editor-array' ) ;
98
+ const arrayItems = this . object [ key ] || [ ] ;
99
+ const itemSchema = property . items || { } ;
100
+
101
+ const renderArrayItems = ( ) => {
102
+ arrayContainer . empty ( ) ;
103
+
104
+ arrayItems . forEach ( ( item , index ) => {
105
+ const itemContainer = $ ( '<div>' ) . addClass ( 'array-item' ) ;
106
+ const deleteButton = $ ( '<button>' )
107
+ . text ( 'x' )
108
+ . addClass ( 'array-item-delete' )
109
+ . on ( 'click' , ( ) => {
110
+ arrayItems . splice ( index , 1 ) ;
111
+ renderArrayItems ( ) ;
112
+ } ) ;
113
+
114
+ if ( itemSchema . type === 'object' || itemSchema . properties ) {
115
+ // Handle array of objects
116
+ const subEditor = new EditorGenerator ( arrayItems [ index ] , itemSchema . properties , '' ) ;
117
+ subEditor . formContainer = itemContainer ; // Set the container manually
118
+ subEditor . generateEditor ( ) ;
119
+ } else if ( itemSchema . type === 'string' ) {
120
+ // Handle array of strings
121
+ const input = $ ( '<input type="text">' )
122
+ . addClass ( 'property-editor-input' )
123
+ . val ( item || '' )
124
+ . on ( 'change' , ( ) => {
125
+ arrayItems [ index ] = input . val ( ) ;
126
+ } ) ;
127
+ itemContainer . append ( input ) ;
128
+ } else if ( itemSchema . type === 'number' || itemSchema . type === 'integer' ) {
129
+ // Handle array of numbers
130
+ const input = $ ( '<input type="number">' )
131
+ . addClass ( 'property-editor-input' )
132
+ . val ( item !== undefined ? item : '' )
133
+ . on ( 'input' , ( ) => {
134
+ arrayItems [ index ] = parseFloat ( input . val ( ) ) ;
135
+ } ) ;
136
+ itemContainer . append ( input ) ;
137
+ } else {
138
+ // Fallback for unsupported item types
139
+ itemContainer . append (
140
+ $ ( '<label>' )
141
+ . text ( 'Unsupported item type: ' + ( itemSchema . type || 'unknown' ) )
142
+ . addClass ( 'property-editor-label' )
143
+ ) ;
144
+ }
145
+
146
+ itemContainer . append ( deleteButton ) ;
147
+ arrayContainer . append ( itemContainer ) ;
148
+ } ) ;
149
+ } ;
150
+
151
+ const addButton = $ ( '<button>' )
152
+ . text ( 'Add' )
153
+ . on ( 'click' , ( ) => {
154
+ if ( itemSchema . type === 'object' ) {
155
+ arrayItems . push ( { } ) ;
156
+ } else if ( itemSchema . type === 'string' ) {
157
+ arrayItems . push ( '' ) ;
158
+ } else if ( itemSchema . type === 'number' || itemSchema . type === 'integer' ) {
159
+ arrayItems . push ( 0 ) ; // Default value for numbers
160
+ } else {
161
+ console . warn ( 'Unsupported item type for addition:' , itemSchema . type ) ;
162
+ return ;
163
+ }
164
+ renderArrayItems ( ) ;
165
+ } ) ;
166
+
167
+ renderArrayItems ( ) ;
168
+ input = $ ( '<div>' )
169
+ . append ( arrayContainer , addButton ) ;
170
+
171
+ this . object [ key ] = arrayItems ;
172
+ break ;
173
+ }
174
+
80
175
default :
81
- input = $ ( '<label>' ) . text ( 'Unsupported type ' + propertyType ) . addClass ( 'property-editor-label' ) ;
176
+ input = $ ( '<label>' )
177
+ . text ( 'Unsupported type ' + propertyType )
178
+ . addClass ( 'property-editor-label' ) ;
82
179
}
83
180
84
181
const fieldContainer = $ ( '<div>' ) . addClass ( 'property-editor-field' ) ;
0 commit comments