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.
- package/CHANGELOG.md +26 -0
- package/assets/stylesheets/form/alchemy_feedback_input.scss +336 -0
- package/assets/stylesheets/form/general/_colors.scss +114 -0
- package/assets/stylesheets/form/general/_textsizes.scss +55 -0
- package/assets/stylesheets/form/general/index.scss +2 -0
- package/controller/form_api_controller.js +19 -2
- package/element/00_form_base.js +170 -0
- package/element/05_feedback_input.js +262 -3
- package/element/alchemy_field.js +105 -22
- package/element/alchemy_field_array_entry.js +53 -9
- package/element/alchemy_field_schema.js +98 -34
- package/element/alchemy_form.js +1 -12
- package/element/alchemy_label.js +9 -3
- package/element/alchemy_select.js +32 -12
- package/element/alchemy_select_item.js +33 -1
- package/element/alchemy_table.js +20 -1
- package/element/number_input.js +106 -0
- package/element/string_input.js +333 -5
- package/helper/widgets/alchemy_field_widget.js +48 -1
- package/helper/widgets/alchemy_form_widget.js +23 -2
- package/package.json +2 -2
- package/view/form/elements/alchemy_field_schema.hwk +2 -4
- package/view/form/elements/alchemy_select_item.hwk +1 -1
- package/view/form/elements/number_input.hwk +36 -0
- package/view/form/inputs/edit/datetime.hwk +8 -1
package/element/string_input.js
CHANGED
|
@@ -3,11 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
5
5
|
* @since 0.1.0
|
|
6
|
-
* @version 0.1.
|
|
6
|
+
* @version 0.1.3
|
|
7
7
|
*/
|
|
8
|
-
|
|
9
|
-
StringInput.super.call(this);
|
|
10
|
-
});
|
|
8
|
+
const StringInput = Function.inherits('Alchemy.Element.Form.FeedbackInput', 'StringInput');
|
|
11
9
|
|
|
12
10
|
/**
|
|
13
11
|
* The template to use for the content of this element
|
|
@@ -16,4 +14,334 @@ var StringInput = Function.inherits('Alchemy.Element.Form.FeedbackInput', functi
|
|
|
16
14
|
* @since 0.1.0
|
|
17
15
|
* @version 0.1.0
|
|
18
16
|
*/
|
|
19
|
-
StringInput.setTemplateFile('form/elements/string_input');
|
|
17
|
+
StringInput.setTemplateFile('form/elements/string_input');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The required attribute
|
|
21
|
+
*
|
|
22
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
23
|
+
* @since 0.1.3
|
|
24
|
+
* @version 0.1.3
|
|
25
|
+
*/
|
|
26
|
+
StringInput.setAttribute('required', {boolean: true});
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The required attribute
|
|
30
|
+
*
|
|
31
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
32
|
+
* @since 0.1.3
|
|
33
|
+
* @version 0.1.3
|
|
34
|
+
*/
|
|
35
|
+
StringInput.setAssignedProperty('validate');
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Revalidate the value
|
|
39
|
+
*
|
|
40
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
41
|
+
* @since 0.1.3
|
|
42
|
+
* @version 0.1.3
|
|
43
|
+
*
|
|
44
|
+
* @return {Object[]}
|
|
45
|
+
*/
|
|
46
|
+
StringInput.setMethod(function getValidationConfig() {
|
|
47
|
+
|
|
48
|
+
let result = [],
|
|
49
|
+
config = this.validate,
|
|
50
|
+
types;
|
|
51
|
+
|
|
52
|
+
if (config && typeof config == 'string') {
|
|
53
|
+
types = config;
|
|
54
|
+
config = null;
|
|
55
|
+
} else if (config && typeof config == 'object') {
|
|
56
|
+
config = Array.cast(config);
|
|
57
|
+
} else {
|
|
58
|
+
types = this.getAttribute('validate');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (types) {
|
|
62
|
+
types = types.split(',');
|
|
63
|
+
} else {
|
|
64
|
+
types = [];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Required always comes first if defined as an attribute
|
|
68
|
+
if (this.required) {
|
|
69
|
+
types.unshift('required');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
for (let type of types) {
|
|
73
|
+
if (type == 'email') {
|
|
74
|
+
result.push({
|
|
75
|
+
type : 'regex',
|
|
76
|
+
regex : /[a-zA-Z0-9_\.-]+@[a-zA-Z0-9_\.-]+\.[a-zA-Z]{2,}/,
|
|
77
|
+
message : 'microcopy:invalid-email',
|
|
78
|
+
when : 'onblur',
|
|
79
|
+
});
|
|
80
|
+
} else if (type == 'regex') {
|
|
81
|
+
result.push({
|
|
82
|
+
type : 'regex',
|
|
83
|
+
regex : RegExp.interpret(this.getAttribute('validate-regex')),
|
|
84
|
+
message : 'microcopy:invalid-pattern-match',
|
|
85
|
+
when : 'onblur',
|
|
86
|
+
});
|
|
87
|
+
} else if (type == 'remote') {
|
|
88
|
+
let route = this.getAttribute('validate-route'),
|
|
89
|
+
url = this.getAttribute('validate-url');
|
|
90
|
+
|
|
91
|
+
result.push({
|
|
92
|
+
type : 'remote',
|
|
93
|
+
route : route,
|
|
94
|
+
url : url,
|
|
95
|
+
message : 'microcopy:invalid-remote',
|
|
96
|
+
when : 'onblur',
|
|
97
|
+
});
|
|
98
|
+
} else if (type == 'required') {
|
|
99
|
+
result.push({
|
|
100
|
+
type : 'required',
|
|
101
|
+
message : 'microcopy:cannot-be-empty'
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
let min_length = Number(this.getAttribute('min-length')) || 0;
|
|
107
|
+
|
|
108
|
+
if (min_length > 0) {
|
|
109
|
+
// Checking the minimum length only has to happen on blur
|
|
110
|
+
result.push({
|
|
111
|
+
type : 'min_length',
|
|
112
|
+
length : min_length,
|
|
113
|
+
message : 'microcopy:is-too-short',
|
|
114
|
+
when : 'onblur',
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
let max_length = Number(this.getAttribute('max-length')) || 0;
|
|
119
|
+
|
|
120
|
+
if (max_length > 0) {
|
|
121
|
+
// Checking maximum length has to happen immediately
|
|
122
|
+
result.push({
|
|
123
|
+
type : 'max_length',
|
|
124
|
+
length : max_length,
|
|
125
|
+
message : 'microcopy:is-too-long',
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (config) {
|
|
130
|
+
for (let entry of config) {
|
|
131
|
+
|
|
132
|
+
if (!entry.when) {
|
|
133
|
+
entry.when = 'onblur';
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
result.push(entry);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return result;
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Revalidate the value
|
|
145
|
+
*
|
|
146
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
147
|
+
* @since 0.1.3
|
|
148
|
+
* @version 0.1.3
|
|
149
|
+
*
|
|
150
|
+
* @param {Object} trigger The revalidation trigger
|
|
151
|
+
*/
|
|
152
|
+
StringInput.setMethod(async function revalidate(trigger, force) {
|
|
153
|
+
|
|
154
|
+
// Get the current value
|
|
155
|
+
let value = this.value;
|
|
156
|
+
|
|
157
|
+
if (value) {
|
|
158
|
+
value = value.trim();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Don't revalidate the same value twice
|
|
162
|
+
if (this.last_validated_value == value) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (this.success_el) {
|
|
167
|
+
this.success_el.innerHTML = '';
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Get the validation counter (important for async validations)
|
|
171
|
+
let validation_counter = ++this.validation_counter;
|
|
172
|
+
|
|
173
|
+
let config = this.getValidationConfig(),
|
|
174
|
+
error_params,
|
|
175
|
+
check_count = 0,
|
|
176
|
+
skip_count = 0,
|
|
177
|
+
required;
|
|
178
|
+
|
|
179
|
+
if (config && config.length) {
|
|
180
|
+
|
|
181
|
+
required = config.findByPath('type', 'required');
|
|
182
|
+
|
|
183
|
+
for (let entry of config) {
|
|
184
|
+
|
|
185
|
+
if (!value.length && !required) {
|
|
186
|
+
skip_count++;
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (entry.when) {
|
|
191
|
+
|
|
192
|
+
// Always check when it's being submitted
|
|
193
|
+
if (trigger != 'submit') {
|
|
194
|
+
if (entry.when == 'onblur' && (!trigger || trigger.type != 'blur')) {
|
|
195
|
+
skip_count++;
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
check_count++;
|
|
202
|
+
|
|
203
|
+
if (entry.type == 'regex') {
|
|
204
|
+
if (!entry.regex.test(value)) {
|
|
205
|
+
error_params = [entry.message, null, true];
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
} else if (entry.type == 'min_length') {
|
|
209
|
+
if (value.length < entry.length) {
|
|
210
|
+
error_params = [entry.message, {
|
|
211
|
+
value_length: value.length,
|
|
212
|
+
min_length : entry.length,
|
|
213
|
+
}, true];
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
} else if (entry.type == 'max_length') {
|
|
217
|
+
if (value.length > entry.length) {
|
|
218
|
+
error_params = [entry.message, {
|
|
219
|
+
value_length : value.length,
|
|
220
|
+
max_length : entry.length,
|
|
221
|
+
}, true];
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
} else if (entry.type == 'remote') {
|
|
225
|
+
|
|
226
|
+
let url;
|
|
227
|
+
|
|
228
|
+
if (entry.url) {
|
|
229
|
+
url = Classes.RURL.parse(entry.url);
|
|
230
|
+
} else if (entry.route) {
|
|
231
|
+
url = hawkejs.scene.helpers.Router.routeUrl(entry.route);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if(!url) {
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
url.param('value', value);
|
|
239
|
+
|
|
240
|
+
try {
|
|
241
|
+
|
|
242
|
+
let result = await Blast.fetch(url);
|
|
243
|
+
|
|
244
|
+
if (result) {
|
|
245
|
+
if (!result.allowed) {
|
|
246
|
+
error_params = [result.message || entry.message, null, true];
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
} catch (err) {
|
|
251
|
+
error_params = [entry.message || err.message, null, true];
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Remove errors if not required and empty
|
|
259
|
+
if (!required && !value.length) {
|
|
260
|
+
this.removeErrors();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Make sure something was checked, otherwise exit early
|
|
264
|
+
if (!check_count) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (validation_counter != this.validation_counter) {
|
|
269
|
+
// Another validation happened while we were waiting for the result
|
|
270
|
+
if (!force) {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (!skip_count) {
|
|
276
|
+
// Remember we validated this value (if all the checks were done)
|
|
277
|
+
this.last_validated_value = value;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (error_params) {
|
|
281
|
+
this.addError(...error_params);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Remove all errors when we got this far
|
|
286
|
+
this.removeErrors();
|
|
287
|
+
|
|
288
|
+
// Mark it as valid, but only if we checked all the checks
|
|
289
|
+
if (!skip_count) {
|
|
290
|
+
this.classList.add('valid');
|
|
291
|
+
this.inputbox_el.classList.add('valid');
|
|
292
|
+
|
|
293
|
+
let message = this.getAttribute('success-message');
|
|
294
|
+
|
|
295
|
+
if (message) {
|
|
296
|
+
this.addSuccess(message);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Actions to perform when this element
|
|
303
|
+
* has been added to the DOM for the first time
|
|
304
|
+
*
|
|
305
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
306
|
+
* @since 0.1.3
|
|
307
|
+
* @version 0.1.3
|
|
308
|
+
*/
|
|
309
|
+
StringInput.setMethod(function introduced() {
|
|
310
|
+
|
|
311
|
+
const that = this,
|
|
312
|
+
input = this.input_el;
|
|
313
|
+
|
|
314
|
+
if (this.readonly) {
|
|
315
|
+
input.disabled = true;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
let doRevalidate = Fn.throttle((e, force) => {
|
|
319
|
+
this.revalidate(e, force);
|
|
320
|
+
}, {
|
|
321
|
+
minimum_wait : 300,
|
|
322
|
+
immediate : false,
|
|
323
|
+
reset_on_call : true
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
input.addEventListener('focus', e => {
|
|
327
|
+
this.inputbox_el.classList.add('focus');
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
input.addEventListener('blur', e => {
|
|
331
|
+
this.inputbox_el.classList.remove('focus');
|
|
332
|
+
doRevalidate(e, true);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
input.addEventListener('keyup', function onKeyup(e) {
|
|
336
|
+
doRevalidate(e);
|
|
337
|
+
that.emit('changing');
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
input.addEventListener('input',function onInput(e) {
|
|
341
|
+
doRevalidate(e);
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
if (this.value) {
|
|
345
|
+
this.revalidate();
|
|
346
|
+
}
|
|
347
|
+
});
|
|
@@ -28,18 +28,65 @@ AlchemyField.constitute(function prepareSchema() {
|
|
|
28
28
|
// this.schema.addField('widgets', widgets, {array: true});
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Find the alchemy-form parent
|
|
33
|
+
*
|
|
34
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
35
|
+
* @since 0.1.4
|
|
36
|
+
* @version 0.1.4
|
|
37
|
+
*/
|
|
38
|
+
AlchemyField.enforceProperty(function alchemy_form(new_value) {
|
|
39
|
+
|
|
40
|
+
if (!new_value && this.config && this.config.alchemy_form) {
|
|
41
|
+
new_value = this.config.alchemy_form;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!new_value) {
|
|
45
|
+
|
|
46
|
+
let parent = this.parent_instance;
|
|
47
|
+
|
|
48
|
+
while (parent) {
|
|
49
|
+
|
|
50
|
+
new_value = parent.alchemy_form;
|
|
51
|
+
|
|
52
|
+
if (new_value) {
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (parent.element) {
|
|
57
|
+
new_value = parent.element.querySelector('alchemy-form');
|
|
58
|
+
|
|
59
|
+
if (new_value) {
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
parent = parent.parent_instance;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return new_value;
|
|
69
|
+
});
|
|
70
|
+
|
|
31
71
|
/**
|
|
32
72
|
* Populate the widget
|
|
33
73
|
*
|
|
34
74
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
35
75
|
* @since 0.1.0
|
|
36
|
-
* @version 0.1.
|
|
76
|
+
* @version 0.1.4
|
|
37
77
|
*/
|
|
38
78
|
AlchemyField.setMethod(function populateWidget() {
|
|
39
79
|
|
|
40
80
|
let config = this.config;
|
|
41
81
|
|
|
82
|
+
let alchemy_form = this.alchemy_form;
|
|
83
|
+
|
|
42
84
|
let field_el = this.createElement('alchemy-field');
|
|
85
|
+
|
|
86
|
+
if (alchemy_form) {
|
|
87
|
+
field_el.alchemy_form = alchemy_form;
|
|
88
|
+
}
|
|
89
|
+
|
|
43
90
|
field_el.field_name = config.field;
|
|
44
91
|
|
|
45
92
|
if (config.view) {
|
|
@@ -16,7 +16,7 @@ const AlchemyForm = Function.inherits('Alchemy.Widget', 'AlchemyForm');
|
|
|
16
16
|
*
|
|
17
17
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
18
18
|
* @since 0.1.0
|
|
19
|
-
* @version 0.1.
|
|
19
|
+
* @version 0.1.4
|
|
20
20
|
*/
|
|
21
21
|
AlchemyForm.setMethod(function populateWidget() {
|
|
22
22
|
|
|
@@ -31,7 +31,22 @@ AlchemyForm.setMethod(function populateWidget() {
|
|
|
31
31
|
form.classList.add('alchemy-widgets-container');
|
|
32
32
|
|
|
33
33
|
if (this.config && this.config.widgets) {
|
|
34
|
-
|
|
34
|
+
let widgets = this.config.widgets.slice(0),
|
|
35
|
+
widget,
|
|
36
|
+
i;
|
|
37
|
+
|
|
38
|
+
for (i = 0; i < widgets.length; i++) {
|
|
39
|
+
widget = widgets[i];
|
|
40
|
+
|
|
41
|
+
if (widget.type == 'alchemy_field') {
|
|
42
|
+
widget = Object.assign({}, widget);
|
|
43
|
+
widget.config = Object.assign({}, widget.config);
|
|
44
|
+
widget.config.alchemy_form = form;
|
|
45
|
+
widgets[i] = widget;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
col.widget.value = widgets;
|
|
35
50
|
}
|
|
36
51
|
|
|
37
52
|
let record = this.element.getContextVariable('record');
|
|
@@ -49,6 +64,12 @@ AlchemyForm.setMethod(function populateWidget() {
|
|
|
49
64
|
form.append(col.widget);
|
|
50
65
|
|
|
51
66
|
this.element.append(form);
|
|
67
|
+
|
|
68
|
+
let violations = this.element.getContextVariable('form_violations');
|
|
69
|
+
|
|
70
|
+
if (violations) {
|
|
71
|
+
form.showError(violations);
|
|
72
|
+
}
|
|
52
73
|
});
|
|
53
74
|
|
|
54
75
|
/**
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "alchemy-form",
|
|
3
3
|
"description": "Form plugin for Alchemy",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.5",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type" : "git",
|
|
7
7
|
"url" : "https://github.com/11ways/alchemy-form.git"
|
|
8
8
|
},
|
|
9
9
|
"peerDependencies": {
|
|
10
|
-
"alchemymvc" : "~1.
|
|
10
|
+
"alchemymvc" : "~1.2.0"
|
|
11
11
|
},
|
|
12
12
|
"license": "MIT",
|
|
13
13
|
"engines": {
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
{%
|
|
2
|
-
{% each %}
|
|
1
|
+
{% each self.sub_fields as sub_field %}
|
|
3
2
|
<alchemy-field
|
|
4
3
|
#alchemy_field_schema=<% self %>
|
|
5
4
|
#schema=<% self.schema %>
|
|
6
5
|
field-name=<% sub_field.name %>
|
|
7
6
|
></alchemy-field>
|
|
8
|
-
{% /each %}
|
|
9
|
-
{% /with %}
|
|
7
|
+
{% /each %}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
<% data = self.data %>
|
|
2
|
-
{
|
|
2
|
+
{{ data.title or data.name or data.$pk or self.value }}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<label
|
|
2
|
+
for="nr_input_<% self.getAttribute('input-name') || '' %>"
|
|
3
|
+
>
|
|
4
|
+
<div class="inputlabel">
|
|
5
|
+
<span class="label" data-he-slot="label"></span>
|
|
6
|
+
<span class="description" data-he-slot="description"></span>
|
|
7
|
+
<hr class="spacer">
|
|
8
|
+
</div>
|
|
9
|
+
</label>
|
|
10
|
+
|
|
11
|
+
<div class="row">
|
|
12
|
+
|
|
13
|
+
<button
|
|
14
|
+
class="control minus"
|
|
15
|
+
tabindex="-1"
|
|
16
|
+
aria-hidden="true"
|
|
17
|
+
></button>
|
|
18
|
+
|
|
19
|
+
<input
|
|
20
|
+
class="input"
|
|
21
|
+
value="<% self.getAttribute('start') %>"
|
|
22
|
+
min="<% self.getAttribute('min') %>"
|
|
23
|
+
max="<% self.getAttribute('max') %>"
|
|
24
|
+
type="number"
|
|
25
|
+
id="nr_input_<% self.getAttribute('input-name') || '' %>"
|
|
26
|
+
name=<% self.getAttribute('input-name') || '' %>
|
|
27
|
+
|
|
28
|
+
<% if (self.hasAttribute('disabled')) print('disabled="disabled"'); %>
|
|
29
|
+
>
|
|
30
|
+
|
|
31
|
+
<button
|
|
32
|
+
class="control plus"
|
|
33
|
+
tabindex="-1"
|
|
34
|
+
aria-hidden="true"
|
|
35
|
+
></button>
|
|
36
|
+
</div>
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
<%
|
|
2
|
+
|
|
2
3
|
if (value) {
|
|
3
|
-
|
|
4
|
+
|
|
5
|
+
// Make sure it's a date
|
|
6
|
+
value = Date.create(value);
|
|
7
|
+
|
|
8
|
+
// According to MDN `toISOString()` should work,
|
|
9
|
+
// but neither Chrome or Firefox allow that format (it still contains timezone info)
|
|
10
|
+
value = value.format('Y-m-d\\TH:i:s');
|
|
4
11
|
}
|
|
5
12
|
%>
|
|
6
13
|
<input
|