alchemy-form 0.1.2 → 0.1.5

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.
@@ -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,36 @@ 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.4
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
+ if (other_field && other_field.value && other_field.config && other_field.config.options) {
38
+ let values = other_field.config.options.values;
39
+
40
+ if (values) {
41
+
42
+ if (values instanceof Classes.Alchemy.Map.Backed) {
43
+ schema = values.get(other_field.value);
44
+ } else {
45
+ schema = values[other_field.value];
46
+ }
47
+
48
+ if (schema && schema.schema) {
49
+ schema = schema.schema;
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ return schema;
32
56
  }
33
57
  });
34
58
 
@@ -37,12 +61,21 @@ FieldSchema.setProperty(function schema() {
37
61
  *
38
62
  * @author Jelle De Loecker <jelle@elevenways.be>
39
63
  * @since 0.1.0
40
- * @version 0.1.0
64
+ * @version 0.1.3
41
65
  */
42
66
  FieldSchema.setProperty(function sub_fields() {
43
67
 
44
- if (this.schema) {
45
- return this.schema.getSorted();
68
+ let schema = this.schema;
69
+
70
+ if (schema) {
71
+
72
+ if (typeof schema != 'object') {
73
+ throw new Error('Expected a schema object, but found "' + typeof schema + '" instead');
74
+ }
75
+
76
+ if (schema) {
77
+ return schema.getSorted();
78
+ }
46
79
  }
47
80
 
48
81
  return [];
@@ -73,56 +106,87 @@ FieldSchema.setProperty(function value() {
73
106
  throw new Error('Unable to set value of schema field');
74
107
  });
75
108
 
76
- return;
109
+ /**
110
+ * Get the optional field that is supplying the schema
111
+ *
112
+ * @author Jelle De Loecker <jelle@elevenways.be>
113
+ * @since 0.1.3
114
+ * @version 0.1.3
115
+ */
116
+ FieldSchema.setMethod(function getSchemaSupplierField() {
77
117
 
118
+ if (!this.alchemy_field || !this.alchemy_field.config || !this.alchemy_field.config.options) {
119
+ return;
120
+ }
78
121
 
122
+ let schema = this.alchemy_field.config.options.schema;
79
123
 
124
+ if (typeof schema == 'string') {
125
+ let other_field_path = this.resolvePath(schema);
80
126
 
127
+ schema = null;
128
+
129
+ let form = this.alchemy_field.alchemy_form;
81
130
 
131
+ if (form) {
132
+ return form.findFieldByPath(other_field_path);
133
+ }
134
+ }
135
+ });
82
136
 
83
137
  /**
84
138
  * Added to the DOM for the first time
85
139
  *
86
140
  * @author Jelle De Loecker <jelle@elevenways.be>
87
- * @since 0.1.0
88
- * @version 0.1.0
141
+ * @since 0.1.3
142
+ * @version 0.1.3
89
143
  */
90
- FieldArray.setMethod(function introduced() {
91
-
92
- const that = this;
93
-
94
- this.onEventSelector('click', '.remove', function onClick(e) {
95
-
96
- e.preventDefault();
144
+ FieldSchema.setMethod(function introduced() {
97
145
 
98
- let entry = e.target.queryUp('alchemy-field-array-entry');
146
+ let supplier_field = this.getSchemaSupplierField();
99
147
 
100
- entry.remove();
101
- });
148
+ if (supplier_field) {
149
+ supplier_field.addEventListener('change', e => {
150
+ this.rerender();
151
+ });
102
152
 
103
- let add_entry = this.querySelector('.add-entry');
153
+ this.rerender();
154
+ }
155
+ });
104
156
 
105
- if (add_entry) {
106
- add_entry.addEventListener('click', function onClick(e) {
157
+ /**
158
+ * Get the original value
159
+ *
160
+ * @author Jelle De Loecker <jelle@elevenways.be>
161
+ * @since 0.1.4
162
+ * @version 0.1.4
163
+ */
164
+ FieldSchema.setProperty(function original_value() {
107
165
 
108
- let field_context = that.field_context,
109
- alchemy_field = that.alchemy_field;
166
+ let field = this.alchemy_field,
167
+ path = this.field_path_in_record;
110
168
 
111
- e.preventDefault();
169
+ if (field && path) {
170
+ let form = field.alchemy_form || this.alchemy_form || this.field_context.alchemy_form;
112
171
 
113
- let view_files = alchemy_field.view_files;
172
+ if (form) {
173
+ return Object.path(form.document, path);
174
+ }
175
+ }
114
176
 
115
- if (!view_files || !view_files.length) {
116
- throw new Error('Unable to add new entry for ' + alchemy_field.field_title);
117
- }
177
+ let context = this.field_context.alchemy_field_schema,
178
+ data;
118
179
 
119
- let new_entry = that.createElement('alchemy-field-array-entry');
180
+ if (context) {
181
+ data = context.original_value;
182
+ } else {
183
+ context = this.field_context.alchemy_form || this.alchemy_field.alchemy_form;
184
+ data = context.document;
185
+ }
120
186
 
121
- new_entry.alchemy_field_array = that;
187
+ path = this.field_path_in_current_schema;
122
188
 
123
- that.entries_element.append(new_entry);
124
- });
125
- }
189
+ let result = Object.path(data, path);
126
190
 
191
+ return result;
127
192
  });
128
-
@@ -5,18 +5,7 @@
5
5
  * @since 0.1.0
6
6
  * @version 0.1.0
7
7
  */
8
- var Form = Function.inherits('Alchemy.Element.Form.Base', function Form() {
9
- Form.super.call(this);
10
- });
11
-
12
- /**
13
- * The stylesheet to load for this element
14
- *
15
- * @author Jelle De Loecker <jelle@develry.be>
16
- * @since 0.1.0
17
- * @version 0.1.0
18
- */
19
- Form.setStylesheetFile('form/form');
8
+ var Form = Function.inherits('Alchemy.Element.Form.Base', 'Form');
20
9
 
21
10
  /**
22
11
  * The stylesheet to load for this element
@@ -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
  });
@@ -244,12 +244,16 @@ AlchemySelect.setProperty(function loaded_items() {
244
244
  *
245
245
  * @author Jelle De Loecker <jelle@develry.be>
246
246
  * @since 0.1.0
247
- * @version 0.1.0
247
+ * @version 0.1.4
248
248
  *
249
249
  * @type {Number}
250
250
  */
251
251
  AlchemySelect.setProperty(function loaded_item_count() {
252
- return Object.size(this.options.values);
252
+ if (this.options.values) {
253
+ return this.options.values.size;
254
+ } else {
255
+ return 0;
256
+ }
253
257
  });
254
258
 
255
259
  /**
@@ -766,7 +770,7 @@ AlchemySelect.setMethod(function _ensureValueData(value) {
766
770
  *
767
771
  * @author Jelle De Loecker <jelle@develry.be>
768
772
  * @since 0.1.0
769
- * @version 0.1.0
773
+ * @version 0.1.4
770
774
  */
771
775
  AlchemySelect.setMethod(function _processPreloadedValues() {
772
776
 
@@ -784,9 +788,14 @@ AlchemySelect.setMethod(function _processPreloadedValues() {
784
788
  let item,
785
789
  key;
786
790
 
787
- for (key in values) {
791
+ let enum_values = new Classes.Alchemy.Map.Enum(values),
792
+ value;
793
+
794
+ for (let key of enum_values.keys()) {
795
+ value = enum_values.get(key);
796
+
788
797
  response.available++;
789
- item = Object.assign({}, values[key]);
798
+ item = Object.assign({}, value);
790
799
  item.id = key;
791
800
 
792
801
  response.items.push(item);
@@ -915,7 +924,7 @@ AlchemySelect.setMethod(function _loadRemote(config) {
915
924
  *
916
925
  * @author Jelle De Loecker <jelle@develry.be>
917
926
  * @since 0.1.0
918
- * @version 0.1.0
927
+ * @version 0.1.4
919
928
  */
920
929
  AlchemySelect.setMethod(function recreateDropdownElements() {
921
930
 
@@ -925,8 +934,8 @@ AlchemySelect.setMethod(function recreateDropdownElements() {
925
934
 
926
935
  Hawkejs.removeChildren(this.dropdown_content);
927
936
 
928
- for (key in items) {
929
- item = items[key];
937
+ for (let key of items.keys()) {
938
+ item = items.get(key);
930
939
  item = this._makeOption(item.id, item);
931
940
  this.addToDropdown(item);
932
941
  }
@@ -1157,7 +1166,7 @@ AlchemySelect.setMethod(function close(event) {
1157
1166
  *
1158
1167
  * @author Jelle De Loecker <jelle@develry.be>
1159
1168
  * @since 0.1.0
1160
- * @version 0.1.0
1169
+ * @version 0.1.5
1161
1170
  *
1162
1171
  * @param {String} type "value" or "option"
1163
1172
  * @param {Mixed} value The actual value of this item
@@ -1175,6 +1184,9 @@ AlchemySelect.setMethod(function _makeValueItem(type, value, data) {
1175
1184
  // Assign the value
1176
1185
  item.value = value;
1177
1186
 
1187
+ // Add a reference to this element
1188
+ item.alchemy_select = this;
1189
+
1178
1190
  if (!data) {
1179
1191
  data = this.getValueData(value);
1180
1192
  }
@@ -1188,7 +1200,11 @@ AlchemySelect.setMethod(function _makeValueItem(type, value, data) {
1188
1200
  this.options.values = {};
1189
1201
  }
1190
1202
 
1191
- this.options.values[value] = data;
1203
+ if (this.options.values instanceof Classes.Alchemy.Map.Enum) {
1204
+ this.options.values.set(value, data);
1205
+ } else {
1206
+ this.options.values[value] = data;
1207
+ }
1192
1208
  }
1193
1209
 
1194
1210
  // And the associated data
@@ -1207,8 +1223,12 @@ AlchemySelect.setMethod(function _makeValueItem(type, value, data) {
1207
1223
  return
1208
1224
  }
1209
1225
 
1210
- if (that.options.values && that.options.values[value]) {
1211
- data = that.options.values[value];
1226
+ if (that.options.values) {
1227
+ if (that.options.values instanceof Classes.Alchemy.Map.Enum) {
1228
+ data = that.options.values.get(value);
1229
+ } else if (that.options.values[value]) {
1230
+ data = that.options.values[value];
1231
+ }
1212
1232
  }
1213
1233
 
1214
1234
  this.data = data;
@@ -53,4 +53,36 @@ Item.setAssignedProperty('value');
53
53
  * @since 0.1.0
54
54
  * @version 0.1.0
55
55
  */
56
- Item.setAssignedProperty('data');
56
+ Item.setAssignedProperty('data');
57
+
58
+ /**
59
+ * The parent alchemy-select item
60
+ *
61
+ * @author Jelle De Loecker <jelle@elevenways.be>
62
+ * @since 0.1.5
63
+ * @version 0.1.5
64
+ */
65
+ Item.enforceProperty(function alchemy_select(new_value) {
66
+
67
+ if (new_value == null) {
68
+ new_value = this.closest('alchemy-select');
69
+ }
70
+
71
+ return new_value;
72
+ });
73
+
74
+ /**
75
+ * The display item
76
+ *
77
+ * @author Jelle De Loecker <jelle@elevenways.be>
78
+ * @since 0.1.5
79
+ * @version 0.1.5
80
+ */
81
+ Item.setProperty(function display_title() {
82
+
83
+ if (!this.data) {
84
+ return '';
85
+ }
86
+
87
+ return this.data.title || this.data.name || this.data.username || this.data.$pk || this.value;
88
+ });
@@ -126,6 +126,15 @@ Table.setAttribute('page-size', {number: true});
126
126
  */
127
127
  Table.setAttribute('show-filters', {boolean: true});
128
128
 
129
+ /**
130
+ * Keep track of the loadRemote calls
131
+ *
132
+ * @author Jelle De Loecker <jelle@elevenways.be>
133
+ * @since 0.1.3
134
+ * @version 0.1.3
135
+ */
136
+ Table.setProperty('load_remote_counter', 0);
137
+
129
138
  /**
130
139
  * Look for changes to the show-filters attribute
131
140
  *
@@ -834,7 +843,7 @@ Table.setMethod(function selectRow(row) {
834
843
  *
835
844
  * @author Jelle De Loecker <jelle@elevenways.be>
836
845
  * @since 0.1.0
837
- * @version 0.1.0
846
+ * @version 0.1.3
838
847
  */
839
848
  Table.setMethod(function loadRemoteData() {
840
849
 
@@ -859,14 +868,24 @@ Table.setMethod(function loadRemoteData() {
859
868
  body : body
860
869
  };
861
870
 
871
+ let load_remote_id = ++this.load_remote_counter;
872
+
862
873
  this.delayAssemble(async function() {
863
874
 
875
+ if (load_remote_id != that.load_remote_counter) {
876
+ return;
877
+ }
878
+
864
879
  let result = await that.getResource(options);
865
880
 
866
881
  if (!result) {
867
882
  return;
868
883
  }
869
884
 
885
+ if (load_remote_id != that.load_remote_counter) {
886
+ return;
887
+ }
888
+
870
889
  let records = result.records;
871
890
 
872
891
  that.records = records;
@@ -0,0 +1,106 @@
1
+ /**
2
+ * The alchemy-number-input custom element
3
+ *
4
+ * @author Jelle De Loecker <jelle@elevenways.be>
5
+ * @since 0.1.3
6
+ * @version 0.1.3
7
+ */
8
+ var NumberInput = Function.inherits('Alchemy.Element.Form.FeedbackInput', 'NumberInput');
9
+
10
+ /**
11
+ * The hawkejs template to use
12
+ *
13
+ * @author Jelle De Loecker <jelle@elevenways.be>
14
+ * @since 0.1.3
15
+ * @version 0.1.3
16
+ */
17
+ NumberInput.setTemplateFile('form/elements/number_input');
18
+
19
+ /**
20
+ * The value property
21
+ *
22
+ * @author Jelle De Loecker <jelle@elevenways.be>
23
+ * @since 0.1.3
24
+ * @version 0.1.3
25
+ */
26
+ NumberInput.setProperty(function value() {
27
+
28
+ var input = this.input_el,
29
+ value = input.value;
30
+
31
+ if (value === '') {
32
+ return null;
33
+ }
34
+
35
+ return Number(value);
36
+
37
+ }, function setValue(value) {
38
+
39
+ var input = this.input_el;
40
+
41
+ if (value == null || value === '') {
42
+ input.value = '';
43
+ } else {
44
+ input.value = value;
45
+ }
46
+
47
+ });
48
+
49
+ /**
50
+ * The disabled property
51
+ *
52
+ * @author Jelle De Loecker <jelle@elevenways.be>
53
+ * @since 0.1.3
54
+ * @version 0.1.3
55
+ */
56
+ NumberInput.setProperty(function disabled() {
57
+ return this.input_el.disabled;
58
+ }, function setDisabled(value) {
59
+ return this.input_el.disabled = value;
60
+ });
61
+
62
+ /**
63
+ * Added to the DOM for the first time
64
+ *
65
+ * @author Jelle De Loecker <jelle@elevenways.be>
66
+ * @since 0.1.3
67
+ * @version 0.1.3
68
+ */
69
+ NumberInput.setMethod(function introduced() {
70
+
71
+ var that = this,
72
+ minus = this.querySelector('.minus'),
73
+ plus = this.querySelector('.plus'),
74
+ input = this.querySelector('.input');
75
+
76
+ var accommodations_summary_element = this.accommodations_summary;
77
+
78
+ minus.addEventListener('click', function onMinus(e) {
79
+ e.preventDefault();
80
+ adjustValue(-1, that);
81
+ });
82
+
83
+ plus.addEventListener('click', function onPlus(e) {
84
+ e.preventDefault();
85
+ adjustValue(+1, that);
86
+ });
87
+
88
+ function adjustValue(change, obj) {
89
+
90
+ var max = Number(input.getAttribute('max')),
91
+ min = Number(input.getAttribute('min')),
92
+ val = Number(input.value) || 0;
93
+
94
+ val += change;
95
+
96
+ if (val > max) {
97
+ val = max;
98
+ }
99
+
100
+ if (val < min) {
101
+ val = min;
102
+ }
103
+
104
+ input.value = val;
105
+ }
106
+ });