alchemy-form 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,9 +7,7 @@ const VALUE = Symbol('value');
7
7
  * @since 0.1.0
8
8
  * @version 0.1.0
9
9
  */
10
- var FeedbackInput = Function.inherits('Alchemy.Element.Form', function FeedbackInput() {
11
- FeedbackInput.super.call(this);
12
- });
10
+ var FeedbackInput = Function.inherits('Alchemy.Element.Form.Base', 'FeedbackInput');
13
11
 
14
12
  /**
15
13
  * Don't register this as a custom element
@@ -20,6 +18,99 @@ var FeedbackInput = Function.inherits('Alchemy.Element.Form', function FeedbackI
20
18
  */
21
19
  FeedbackInput.setStatic('is_abstract_class', true, false);
22
20
 
21
+ /**
22
+ * The stylesheet to load for this element
23
+ *
24
+ * @author Jelle De Loecker <jelle@elevenways.be>
25
+ * @since 0.1.3
26
+ * @version 0.1.3
27
+ */
28
+ FeedbackInput.setStylesheetFile('form/alchemy_feedback_input');
29
+
30
+ /**
31
+ * The readonly attribute
32
+ *
33
+ * @author Jelle De Loecker <jelle@elevenways.be>
34
+ * @since 0.1.3
35
+ * @version 0.1.3
36
+ */
37
+ FeedbackInput.setAttribute('readonly', {boolean: true});
38
+
39
+ /**
40
+ * Reference to the errors element
41
+ *
42
+ * @author Jelle De Loecker <jelle@elevenways.be>
43
+ * @since 0.1.3
44
+ * @version 0.1.3
45
+ */
46
+ FeedbackInput.addElementGetter('errors_el', '.errors');
47
+
48
+ /**
49
+ * Reference to the success element
50
+ *
51
+ * @author Jelle De Loecker <jelle@elevenways.be>
52
+ * @since 0.1.3
53
+ * @version 0.1.3
54
+ */
55
+ FeedbackInput.addElementGetter('success_el', '.success');
56
+
57
+ /**
58
+ * Reference to the inputbox element
59
+ *
60
+ * @author Jelle De Loecker <jelle@elevenways.be>
61
+ * @since 0.1.3
62
+ * @version 0.1.3
63
+ */
64
+ FeedbackInput.addElementGetter('inputbox_el', '.inputbox');
65
+
66
+ /**
67
+ * Reference to the input element
68
+ *
69
+ * @author Jelle De Loecker <jelle@elevenways.be>
70
+ * @since 0.1.3
71
+ * @version 0.1.3
72
+ */
73
+ FeedbackInput.addElementGetter('input_el', '.input');
74
+
75
+ /**
76
+ * The last validated value
77
+ *
78
+ * @author Jelle De Loecker <jelle@elevenways.be>
79
+ * @since 0.1.3
80
+ * @version 0.1.3
81
+ */
82
+ FeedbackInput.setProperty('last_validated_value', null);
83
+
84
+ /**
85
+ * The validation counter
86
+ *
87
+ * @author Jelle De Loecker <jelle@elevenways.be>
88
+ * @since 0.1.3
89
+ * @version 0.1.3
90
+ */
91
+ FeedbackInput.setProperty('validation_counter', 0);
92
+
93
+ /**
94
+ * Was this input valid after the last revalidation?
95
+ *
96
+ * @author Jelle De Loecker <jelle@elevenways.be>
97
+ * @since 0.1.3
98
+ * @version 0.1.3
99
+ */
100
+ FeedbackInput.setProperty(function is_valid() {
101
+
102
+ if (this.classList.contains('error')) {
103
+ return false;
104
+ }
105
+
106
+ if (this.classList.contains('valid')) {
107
+ return true;
108
+ }
109
+
110
+ // Default to true
111
+ return true;
112
+ });
113
+
23
114
  /**
24
115
  * The value property
25
116
  *
@@ -57,3 +148,171 @@ FeedbackInput.setProperty(function value() {
57
148
 
58
149
  this[VALUE] = value;
59
150
  });
151
+
152
+ /**
153
+ * Remove all errors
154
+ *
155
+ * @author Jelle De Loecker <jelle@elevenways.be>
156
+ * @since 0.1.3
157
+ * @version 0.1.3
158
+ */
159
+ FeedbackInput.setMethod(function removeErrors() {
160
+ this.classList.remove('valid');
161
+ this.classList.remove('error');
162
+ this.inputbox_el.classList.remove('valid');
163
+ this.inputbox_el.classList.remove('error');
164
+ Hawkejs.removeChildren(this.errors_el);
165
+ Hawkejs.removeChildren(this.success_el);
166
+ });
167
+
168
+ /**
169
+ * Get a message stirng or a microcopy object
170
+ *
171
+ * @author Jelle De Loecker <jelle@elevenways.be>
172
+ * @since 0.1.3
173
+ * @version 0.1.3
174
+ *
175
+ * @return {<micro-copy>|String}
176
+ */
177
+ FeedbackInput.setMethod(function convertMessage(message, parameters) {
178
+
179
+ if (!message) {
180
+ return '';
181
+ }
182
+
183
+ let microcopy;
184
+
185
+ if (typeof message == 'string') {
186
+ if (!message.startsWith('microcopy:')) {
187
+ return message;
188
+ }
189
+
190
+ microcopy = this.createElement('micro-copy');
191
+ microcopy.key = message.after('microcopy:');
192
+
193
+ if (!parameters) {
194
+ parameters = {};
195
+ }
196
+
197
+ microcopy.parameters = parameters;
198
+ } else if (typeof message == 'object') {
199
+
200
+ if (message instanceof Classes.Alchemy.Microcopy) {
201
+ microcopy = message.toElement();
202
+ } else {
203
+ microcopy = message;
204
+ }
205
+
206
+ if (parameters) {
207
+ microcopy.parameters = parameters;
208
+ } else {
209
+ parameters = microcopy.parameters;
210
+ }
211
+
212
+ if (!parameters) {
213
+ microcopy.parameters = parameters = {};
214
+ }
215
+ }
216
+
217
+ if (!parameters.field) {
218
+ parameters.field = this.getAttribute('input-name');
219
+ }
220
+
221
+ let friendly = this.dataset.friendly;
222
+
223
+ if (!friendly) {
224
+ let label = this.querySelector('[slot="label"]');
225
+
226
+ if (label) {
227
+ friendly = label.textContent;
228
+ }
229
+ }
230
+
231
+ if (friendly) {
232
+ parameters.field = friendly;
233
+ }
234
+
235
+ return microcopy;
236
+ });
237
+
238
+ /**
239
+ * Add an error
240
+ *
241
+ * @author Jelle De Loecker <jelle@elevenways.be>
242
+ * @since 0.1.3
243
+ * @version 0.1.3
244
+ */
245
+ FeedbackInput.setMethod(function addError(message, parameters, clear_first, add_friendly) {
246
+
247
+ var p = this.createElement('p'),
248
+ i = this.createElement('i'),
249
+ span = this.createElement('span'),
250
+ friendly = this.dataset.friendly,
251
+ strong = this.createElement('strong');
252
+
253
+ if (typeof parameters == 'boolean') {
254
+ add_friendly = clear_first;
255
+ clear_first = parameters;
256
+ parameters = null;
257
+ }
258
+
259
+ if (clear_first) {
260
+ this.removeErrors();
261
+ }
262
+
263
+ p.classList.add('errorlabel');
264
+ i.classList.add('erroricon');
265
+ span.classList.add('text');
266
+
267
+ p.append(i);
268
+ p.append(span);
269
+
270
+ // Try getting a microcopy
271
+ message = this.convertMessage(message, parameters);
272
+
273
+ strong.append(message);
274
+ span.append(strong);
275
+
276
+ this.errors_el.append(p);
277
+
278
+ if (this.external_element) {
279
+ this.external_element.disabled = true;
280
+ }
281
+
282
+ if (this.show_element) {
283
+ this.show_element.hidden = true;
284
+ }
285
+
286
+ this.classList.add('error');
287
+ this.inputbox_el.classList.add('error');
288
+
289
+ if (this.activate_el) {
290
+ this.activate_el.classList.remove(this.activate_class);
291
+ }
292
+ });
293
+
294
+ /**
295
+ * Add a success message
296
+ *
297
+ * @author Jelle De Loecker <jelle@elevenways.be>
298
+ * @since 0.1.3
299
+ * @version 0.1.3
300
+ */
301
+ FeedbackInput.setMethod(function addSuccess(message, parameters, clear_first, add_friendly) {
302
+
303
+ var p = this.createElement('p');
304
+
305
+ message = this.convertMessage(message, parameters);
306
+
307
+ p.classList.add('successlabel');
308
+ p.append(message);
309
+
310
+ this.success_el.append(p);
311
+
312
+ this.classList.add('valid');
313
+ this.inputbox_el.classList.add('valid');
314
+
315
+ if (this.activate_el) {
316
+ this.activate_el.classList.add(this.activate_class);
317
+ }
318
+ });
@@ -187,6 +187,24 @@ Field.setProperty(function is_array() {
187
187
  return false;
188
188
  });
189
189
 
190
+ /**
191
+ * Is this a schema field?
192
+ *
193
+ * @author Jelle De Loecker <jelle@elevenways.be>
194
+ * @since 0.1.3
195
+ * @version 0.1.3
196
+ */
197
+ Field.setProperty(function contains_schema() {
198
+
199
+ let config = this.config;
200
+
201
+ if (config) {
202
+ return config instanceof Classes.Alchemy.Field.Schema;
203
+ }
204
+
205
+ return false;
206
+ });
207
+
190
208
  /**
191
209
  * Is this a translatable field?
192
210
  *
@@ -247,6 +265,35 @@ Field.setProperty(function field_description() {
247
265
  return result;
248
266
  });
249
267
 
268
+ /**
269
+ * Get the path of this field in the schema
270
+ *
271
+ * @author Jelle De Loecker <jelle@elevenways.be>
272
+ * @since 0.1.3
273
+ * @version 0.1.3
274
+ */
275
+ Field.setProperty(function field_path_in_schema() {
276
+ return this.config && this.config.getPath();
277
+ });
278
+
279
+ /**
280
+ * Get the name of this entry for use in a record path
281
+ *
282
+ * @author Jelle De Loecker <jelle@elevenways.be>
283
+ * @since 0.1.3
284
+ * @version 0.1.3
285
+ *
286
+ * @return {String}
287
+ */
288
+ Field.setMethod(function getPathEntryName() {
289
+
290
+ if (this.config && this.config.name) {
291
+ return this.config.name;
292
+ }
293
+
294
+ return '';
295
+ });
296
+
250
297
  /**
251
298
  * Get the name of the model this field belongs to
252
299
  *
@@ -439,7 +486,6 @@ Field.setProperty(function original_value() {
439
486
  if (form && form.document) {
440
487
  return form.document[this.field_name];
441
488
  }
442
-
443
489
  });
444
490
 
445
491
  /**
@@ -447,7 +493,7 @@ Field.setProperty(function original_value() {
447
493
  *
448
494
  * @author Jelle De Loecker <jelle@elevenways.be>
449
495
  * @since 0.1.0
450
- * @version 0.1.0
496
+ * @version 0.1.3
451
497
  */
452
498
  Field.setProperty(function value_element() {
453
499
 
@@ -458,6 +504,8 @@ Field.setProperty(function value_element() {
458
504
  input = this.querySelector('alchemy-field-translatable');
459
505
  } else if (this.is_array) {
460
506
  input = this.querySelector('alchemy-field-array');
507
+ } else if (this.contains_schema) {
508
+ input = this.querySelector('alchemy-field-schema');
461
509
  } else {
462
510
  input = this.querySelector('.alchemy-field-value');
463
511
  }
@@ -470,7 +518,7 @@ Field.setProperty(function value_element() {
470
518
  *
471
519
  * @author Jelle De Loecker <jelle@elevenways.be>
472
520
  * @since 0.1.0
473
- * @version 0.1.0
521
+ * @version 0.1.3
474
522
  */
475
523
  Field.setProperty(function value() {
476
524
 
@@ -478,6 +526,8 @@ Field.setProperty(function value() {
478
526
 
479
527
  if (element) {
480
528
  return element.value;
529
+ } else {
530
+ return this.original_value;
481
531
  }
482
532
 
483
533
  }, function setValue(value) {
@@ -593,7 +643,7 @@ Field.setMethod(function removeErrors() {
593
643
  *
594
644
  * @author Jelle De Loecker <jelle@elevenways.be>
595
645
  * @since 0.1.0
596
- * @version 0.1.0
646
+ * @version 0.1.3
597
647
  */
598
648
  Field.setMethod(function retained() {
599
649
 
@@ -607,15 +657,15 @@ Field.setMethod(function retained() {
607
657
  id += this.field_name.slug();
608
658
 
609
659
  this.id = id;
660
+ }
610
661
 
611
- let label = this.querySelector('.form-field-info alchemy-label');
662
+ let label = this.querySelector('.form-field-info alchemy-label');
612
663
 
613
- if (label && this.value_element) {
614
- let v_id = id + '_fv';
664
+ if (label && this.value_element) {
665
+ let v_id = this.id + '_fv';
615
666
 
616
- label.setAttribute('for', v_id);
617
- this.value_element.setAttribute('id', v_id);
618
- }
667
+ label.setAttribute('for', v_id);
668
+ this.value_element.setAttribute('id', v_id);
619
669
  }
620
670
 
621
671
  });
@@ -18,15 +18,6 @@ var FieldArrayEntry = Function.inherits('Alchemy.Element.Form.FieldEntry', funct
18
18
  */
19
19
  FieldArrayEntry.setTemplateFile('form/elements/alchemy_field_array_entry');
20
20
 
21
- /**
22
- * The prefix of this translation
23
- *
24
- * @author Jelle De Loecker <jelle@elevenways.be>
25
- * @since 0.1.0
26
- * @version 0.1.0
27
- */
28
- FieldArrayEntry.setAttribute('index');
29
-
30
21
  /**
31
22
  * Get a reference to the alchemy-field-array parent
32
23
  *
@@ -43,6 +34,46 @@ FieldArrayEntry.enforceProperty(function alchemy_field_array(new_value, old_valu
43
34
  return new_value;
44
35
  });
45
36
 
37
+ /**
38
+ * Get the index of this entry
39
+ *
40
+ * @author Jelle De Loecker <jelle@elevenways.be>
41
+ * @since 0.1.3
42
+ * @version 0.1.3
43
+ */
44
+ FieldArrayEntry.setProperty(function index() {
45
+
46
+ let defined_index = this.getAttribute('index'),
47
+ index;
48
+
49
+ let container = this.alchemy_field_array;
50
+
51
+ if (!container || !container.entries_element) {
52
+ if (defined_index) {
53
+ index = +defined_index;
54
+ }
55
+ } else {
56
+ let counter = -1,
57
+ child;
58
+
59
+ for (let i = 0; i < container.entries_element.children.length; i++) {
60
+ child = container.entries_element.children[i];
61
+
62
+ if (child.tagName == 'ALCHEMY-FIELD-ARRAY-ENTRY') {
63
+ counter++;
64
+ }
65
+
66
+ if (child == this) {
67
+ break;
68
+ }
69
+ }
70
+
71
+ index = counter;
72
+ }
73
+
74
+ return index;
75
+ });
76
+
46
77
  /**
47
78
  * Get the original value
48
79
  *
@@ -58,3 +89,16 @@ FieldArrayEntry.setProperty(function original_value() {
58
89
  return context_value[this.index];
59
90
  }
60
91
  });
92
+
93
+ /**
94
+ * Get the name of this entry for use in a record path
95
+ *
96
+ * @author Jelle De Loecker <jelle@elevenways.be>
97
+ * @since 0.1.3
98
+ * @version 0.1.3
99
+ *
100
+ * @return {String}
101
+ */
102
+ FieldArrayEntry.setMethod(function getPathEntryName() {
103
+ return '' + this.index;
104
+ });
@@ -23,12 +23,33 @@ FieldSchema.setTemplateFile('form/elements/alchemy_field_schema');
23
23
  *
24
24
  * @author Jelle De Loecker <jelle@elevenways.be>
25
25
  * @since 0.1.0
26
- * @version 0.1.0
26
+ * @version 0.1.3
27
27
  */
28
28
  FieldSchema.setProperty(function schema() {
29
29
 
30
30
  if (this.alchemy_field && this.alchemy_field.config.options) {
31
- return this.alchemy_field.config.options.schema;
31
+ let schema = this.alchemy_field.config.options.schema;
32
+
33
+ if (typeof schema == 'string') {
34
+ let other_field = this.getSchemaSupplierField();
35
+ schema = null;
36
+
37
+ console.log('Other field:', other_field, 'of', this)
38
+
39
+ if (other_field && other_field.value && other_field.config && other_field.config.options) {
40
+ let values = other_field.config.options.values;
41
+
42
+ if (values) {
43
+ schema = values[other_field.value];
44
+
45
+ if (schema && schema.schema) {
46
+ schema = schema.schema;
47
+ }
48
+ }
49
+ }
50
+ }
51
+
52
+ return schema;
32
53
  }
33
54
  });
34
55
 
@@ -37,12 +58,21 @@ FieldSchema.setProperty(function schema() {
37
58
  *
38
59
  * @author Jelle De Loecker <jelle@elevenways.be>
39
60
  * @since 0.1.0
40
- * @version 0.1.0
61
+ * @version 0.1.3
41
62
  */
42
63
  FieldSchema.setProperty(function sub_fields() {
43
64
 
44
- if (this.schema) {
45
- return this.schema.getSorted();
65
+ let schema = this.schema;
66
+
67
+ if (schema) {
68
+
69
+ if (typeof schema != 'object') {
70
+ throw new Error('Expected a schema object, but found "' + typeof schema + '" instead');
71
+ }
72
+
73
+ if (schema) {
74
+ return schema.getSorted();
75
+ }
46
76
  }
47
77
 
48
78
  return [];
@@ -73,56 +103,56 @@ FieldSchema.setProperty(function value() {
73
103
  throw new Error('Unable to set value of schema field');
74
104
  });
75
105
 
76
- return;
77
-
78
-
79
-
80
-
81
-
82
-
83
106
  /**
84
- * Added to the DOM for the first time
107
+ * Get the optional field that is supplying the schema
85
108
  *
86
109
  * @author Jelle De Loecker <jelle@elevenways.be>
87
- * @since 0.1.0
88
- * @version 0.1.0
110
+ * @since 0.1.3
111
+ * @version 0.1.3
89
112
  */
90
- FieldArray.setMethod(function introduced() {
91
-
92
- const that = this;
93
-
94
- this.onEventSelector('click', '.remove', function onClick(e) {
95
-
96
- e.preventDefault();
113
+ FieldSchema.setMethod(function getSchemaSupplierField() {
97
114
 
98
- let entry = e.target.queryUp('alchemy-field-array-entry');
99
-
100
- entry.remove();
101
- });
115
+ if (!this.alchemy_field || !this.alchemy_field.config || !this.alchemy_field.config.options) {
116
+ console.log('--no config found?')
117
+ return;
118
+ }
102
119
 
103
- let add_entry = this.querySelector('.add-entry');
120
+ let schema = this.alchemy_field.config.options.schema;
104
121
 
105
- if (add_entry) {
106
- add_entry.addEventListener('click', function onClick(e) {
122
+ console.log('Schema is...', schema);
107
123
 
108
- let field_context = that.field_context,
109
- alchemy_field = that.alchemy_field;
124
+ if (typeof schema == 'string') {
125
+ let other_field_path = this.resolvePath(schema);
110
126
 
111
- e.preventDefault();
127
+ schema = null;
128
+
129
+ let form = this.alchemy_field.alchemy_form;
112
130
 
113
- let view_files = alchemy_field.view_files;
131
+ console.log(' -- Got form:', form);
114
132
 
115
- if (!view_files || !view_files.length) {
116
- throw new Error('Unable to add new entry for ' + alchemy_field.field_title);
117
- }
133
+ if (form) {
134
+ console.log(' -- Looking for path:', other_field_path)
135
+ return form.findFieldByPath(other_field_path);
136
+ }
137
+ }
138
+ });
118
139
 
119
- let new_entry = that.createElement('alchemy-field-array-entry');
140
+ /**
141
+ * Added to the DOM for the first time
142
+ *
143
+ * @author Jelle De Loecker <jelle@elevenways.be>
144
+ * @since 0.1.3
145
+ * @version 0.1.3
146
+ */
147
+ FieldSchema.setMethod(function introduced() {
120
148
 
121
- new_entry.alchemy_field_array = that;
149
+ let supplier_field = this.getSchemaSupplierField();
122
150
 
123
- that.entries_element.append(new_entry);
151
+ if (supplier_field) {
152
+ supplier_field.addEventListener('change', e => {
153
+ this.rerender();
124
154
  });
125
- }
126
-
127
- });
128
155
 
156
+ this.rerender();
157
+ }
158
+ });
@@ -30,7 +30,7 @@ AlchemyLabel.setAttribute('for');
30
30
  *
31
31
  * @author Jelle De Loecker <jelle@elevenways.be>
32
32
  * @since 0.1.0
33
- * @version 0.1.0
33
+ * @version 0.1.3
34
34
  */
35
35
  AlchemyLabel.setMethod(function introduced() {
36
36
 
@@ -46,8 +46,14 @@ AlchemyLabel.setMethod(function introduced() {
46
46
  return;
47
47
  }
48
48
 
49
- element.click();
49
+ try {
50
+ // Trigger a click (for buttons & checkboxes)
51
+ element.click();
50
52
 
53
+ // Focus on the element (for inputs)
54
+ element.focus();
55
+ } catch (err) {
56
+ console.error('Failed to focus element:', err);
57
+ }
51
58
  });
52
-
53
59
  });