input-duration 2.0.12 → 2.1.0
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/README.md +8 -8
- package/docs/InputDuration.html +1249 -0
- package/docs/index.html +3 -4
- package/docs/index.js.html +660 -0
- package/index.js +396 -496
- package/package.json +14 -3
package/index.js
CHANGED
|
@@ -1,186 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Class for the Input-Duration webcomponent
|
|
3
|
+
* @class InputDuration
|
|
4
|
+
* @extends HTMLElement
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
class InputDuration extends HTMLElement {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
8
|
+
constructor() {
|
|
9
|
+
|
|
10
|
+
super();
|
|
11
|
+
|
|
12
|
+
this.myElement = this.attachShadow({ mode: 'open' });
|
|
13
|
+
|
|
14
|
+
// needed for setting inputs when value attribute is added to chronlyHMS
|
|
15
|
+
// <chronly-hms id="bobPrepop" value="99:09:09.999"></chronly-hms>
|
|
16
|
+
|
|
17
|
+
this.value = this.getAttribute('value');
|
|
18
|
+
|
|
19
|
+
this.boot();
|
|
20
|
+
|
|
21
|
+
} // end constructor
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* get the input-duration value, pulls values from each input
|
|
26
|
+
* so in js use var x = document.querySelector("#bobPrepop").value;
|
|
27
|
+
* @return {duration}
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
get value() {
|
|
5
31
|
|
|
6
|
-
|
|
32
|
+
// return this.getAttribute('value');
|
|
7
33
|
|
|
34
|
+
if (this.myElement.querySelector('input[name="startHours"]') !== null) {
|
|
8
35
|
|
|
9
|
-
|
|
10
|
-
|
|
36
|
+
return this.myElement.querySelector('input[name="startHours"]').value +
|
|
37
|
+
':' + this.myElement.querySelector('input[name="startMinutes"]').value +
|
|
38
|
+
':' + this.myElement.querySelector('input[name="startSeconds"]').value +
|
|
39
|
+
'.' + this.myElement.querySelector('input[name="startMilliSecs"]').value;
|
|
11
40
|
|
|
12
|
-
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
13
43
|
|
|
44
|
+
return null;
|
|
14
45
|
|
|
15
|
-
|
|
46
|
+
}
|
|
47
|
+
}
|
|
16
48
|
|
|
17
49
|
|
|
18
|
-
|
|
50
|
+
/**
|
|
51
|
+
* set the input-duration value
|
|
52
|
+
* so in js use document.querySelector("#bobPrepop").value = "05:05:05.005"
|
|
53
|
+
* @return {duration}
|
|
54
|
+
* @param {duration} can be html attribute or set in js
|
|
55
|
+
*/
|
|
19
56
|
|
|
20
|
-
|
|
57
|
+
set value(val) {
|
|
21
58
|
|
|
22
|
-
|
|
59
|
+
// for setting the value in js (like document.querySelector("#bobPrepop").value = "05:05:05.005")
|
|
60
|
+
if (val) {
|
|
23
61
|
|
|
24
|
-
if (this.myElement.querySelector('input[name="startHours"]') !== null) {
|
|
25
62
|
|
|
26
|
-
|
|
27
|
-
':' + this.myElement.querySelector('input[name="startMinutes"]').value +
|
|
28
|
-
':' + this.myElement.querySelector('input[name="startSeconds"]').value +
|
|
29
|
-
'.' + this.myElement.querySelector('input[name="startMilliSecs"]').value;
|
|
63
|
+
console.log(val);
|
|
30
64
|
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
65
|
|
|
34
|
-
|
|
66
|
+
if (/(^[0-9][0-9]):([0-5][0-9]):([0-5][0-9])\.([0-9][0-9][0-9]$)/.exec(val)) {
|
|
35
67
|
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
68
|
|
|
39
|
-
|
|
69
|
+
// split val
|
|
40
70
|
|
|
41
|
-
|
|
42
|
-
if (val) {
|
|
71
|
+
var timeArray = val.split(/[.:]+/);
|
|
43
72
|
|
|
73
|
+
console.log('time array is ' + timeArray[0] + ':' + timeArray[1] + ':' + timeArray[2] + ':' + timeArray[3]);
|
|
44
74
|
|
|
45
|
-
|
|
75
|
+
console.log('this.id = ' + this.id);
|
|
46
76
|
|
|
77
|
+
setTimeout(() => {
|
|
47
78
|
|
|
48
|
-
|
|
79
|
+
this.myElement.querySelector('input[name="startHours"]').value = timeArray[0];
|
|
80
|
+
this.myElement.querySelector('input[name="startMinutes"]').value = timeArray[1];
|
|
81
|
+
this.myElement.querySelector('input[name="startSeconds"]').value = timeArray[2];
|
|
82
|
+
this.myElement.querySelector('input[name="startMilliSecs"]').value = timeArray[3];
|
|
49
83
|
|
|
84
|
+
}, 0);
|
|
50
85
|
|
|
51
|
-
// split val
|
|
52
86
|
|
|
53
|
-
|
|
87
|
+
this.setAttribute('value', val);
|
|
54
88
|
|
|
55
|
-
|
|
89
|
+
}
|
|
56
90
|
|
|
57
|
-
|
|
91
|
+
else {
|
|
58
92
|
|
|
59
|
-
|
|
93
|
+
console.warn(`The specified value ${val} does not conform to the required format. The format is "HH:mm:ss.SSS" where HH is 00-99, mm is 00-59, ss is 00-59, and SSS is 000-999.`);
|
|
60
94
|
|
|
61
|
-
|
|
62
|
-
this.myElement.querySelector('input[name="startMinutes"]').value = timeArray[1];
|
|
63
|
-
this.myElement.querySelector('input[name="startSeconds"]').value = timeArray[2];
|
|
64
|
-
this.myElement.querySelector('input[name="startMilliSecs"]').value = timeArray[3];
|
|
65
|
-
}, 0);
|
|
95
|
+
}
|
|
66
96
|
|
|
97
|
+
// I think this is for empty string to clear value
|
|
98
|
+
// gives a False bool and removes value from Webcomponent chronlyHMS
|
|
67
99
|
|
|
100
|
+
} else {
|
|
68
101
|
|
|
69
|
-
|
|
102
|
+
setTimeout(() => {
|
|
70
103
|
|
|
71
|
-
|
|
72
|
-
|
|
104
|
+
this.myElement.querySelector('input[name="startHours"]').value = '00';
|
|
105
|
+
this.myElement.querySelector('input[name="startMinutes"]').value = '00';
|
|
106
|
+
this.myElement.querySelector('input[name="startSeconds"]').value = '00';
|
|
107
|
+
this.myElement.querySelector('input[name="startMilliSecs"]').value = '000';
|
|
73
108
|
|
|
74
|
-
|
|
109
|
+
}, 0);
|
|
75
110
|
|
|
76
|
-
|
|
111
|
+
this.removeAttribute('value');
|
|
77
112
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
} else {
|
|
113
|
+
}
|
|
114
|
+
}
|
|
81
115
|
|
|
82
116
|
|
|
83
|
-
|
|
117
|
+
/**
|
|
118
|
+
* Called from constructor, sets up the html and event listeners
|
|
119
|
+
* @method
|
|
120
|
+
*/
|
|
84
121
|
|
|
85
|
-
|
|
86
|
-
this.myElement.querySelector('input[name="startMinutes"]').value = '00';
|
|
87
|
-
this.myElement.querySelector('input[name="startSeconds"]').value = '00';
|
|
88
|
-
this.myElement.querySelector('input[name="startMilliSecs"]').value = '000';
|
|
122
|
+
boot() {
|
|
89
123
|
|
|
90
|
-
|
|
124
|
+
this.addHTML();
|
|
91
125
|
|
|
126
|
+
// // set up event listeners
|
|
127
|
+
this.add0s();
|
|
128
|
+
this.addNumberLooping();
|
|
129
|
+
this.addArrowKeyInput();
|
|
130
|
+
this.addNumericInput();
|
|
131
|
+
this.addClicksToActivate();
|
|
132
|
+
this.nonNumericBugInHTML();
|
|
92
133
|
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
}
|
|
134
|
+
}
|
|
96
135
|
|
|
97
|
-
/**
|
|
98
|
-
* eventlistener that adds arrow key input of values (up/down) and place toggling (left/right) triggered by
|
|
99
|
-
* the change event of the input
|
|
100
|
-
* @method
|
|
101
|
-
* @see boot()
|
|
102
|
-
*/
|
|
103
136
|
|
|
104
|
-
|
|
137
|
+
/**
|
|
138
|
+
* eventlistener that adds arrow key input of values (up/down) and place toggling (left/right) triggered by
|
|
139
|
+
* the change event of the input
|
|
140
|
+
* @method
|
|
141
|
+
* @see boot()
|
|
142
|
+
*/
|
|
105
143
|
|
|
144
|
+
addArrowKeyInput() {
|
|
106
145
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
146
|
+
console.log('1 this: ' + this);
|
|
147
|
+
console.log('1 this.myElement: ' + this.myElement);
|
|
148
|
+
console.log('1 this.myElement active: ' + this.myElement);
|
|
110
149
|
|
|
111
|
-
|
|
150
|
+
var mE = this.myElement;
|
|
112
151
|
|
|
113
|
-
|
|
114
|
-
|
|
152
|
+
// Left and Right arrow key toggle between HMSmS
|
|
153
|
+
// this depends on data-attributes ex. data-tp="1" in HTML
|
|
115
154
|
|
|
116
|
-
|
|
117
|
-
|
|
155
|
+
this.myElement.querySelector("div.timeCase")
|
|
156
|
+
.addEventListener('keydown', function (event) {
|
|
118
157
|
|
|
119
|
-
|
|
120
|
-
|
|
158
|
+
var et = event.target;
|
|
159
|
+
var tp_active = mE.activeElement.dataset.tp;
|
|
121
160
|
|
|
122
|
-
|
|
161
|
+
switch (true) {
|
|
123
162
|
|
|
124
|
-
|
|
163
|
+
case event.key == "ArrowLeft":
|
|
125
164
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
165
|
+
if (tp_active >= 2) {
|
|
166
|
+
tp_active--;
|
|
167
|
+
}
|
|
129
168
|
|
|
130
|
-
|
|
131
|
-
|
|
169
|
+
et.parentElement.querySelector("[data-tp='" + tp_active + "']").focus();
|
|
170
|
+
setTimeout(function () { et.parentElement.querySelector("[data-tp='" + tp_active + "']").select(); }, 5);
|
|
132
171
|
|
|
133
|
-
|
|
172
|
+
break;
|
|
134
173
|
|
|
135
|
-
|
|
136
|
-
|
|
174
|
+
case event.key == "ArrowRight":
|
|
175
|
+
// tp_active = this.myElement.shadowRoot.activeElement.dataset.tp;
|
|
137
176
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
177
|
+
if (tp_active <= 3) {
|
|
178
|
+
tp_active++;
|
|
179
|
+
}
|
|
141
180
|
|
|
142
|
-
|
|
143
|
-
|
|
181
|
+
et.parentElement.querySelector("[data-tp='" + tp_active + "']").focus();
|
|
182
|
+
setTimeout(function () { et.parentElement.querySelector("[data-tp='" + tp_active + "']").select(); }, 5);
|
|
144
183
|
|
|
145
|
-
|
|
184
|
+
break;
|
|
146
185
|
|
|
147
|
-
|
|
148
|
-
|
|
186
|
+
// these keep the input selected
|
|
187
|
+
case event.key == "ArrowUp":
|
|
149
188
|
|
|
150
|
-
|
|
189
|
+
setTimeout(function () { mE.activeElement.select(); }, 5);
|
|
151
190
|
|
|
152
|
-
|
|
191
|
+
break;
|
|
153
192
|
|
|
154
|
-
|
|
193
|
+
case event.key == "ArrowDown":
|
|
155
194
|
|
|
156
|
-
|
|
195
|
+
setTimeout(function () { mE.activeElement.select(); }, 5);
|
|
157
196
|
|
|
158
|
-
|
|
197
|
+
break;
|
|
159
198
|
|
|
160
|
-
|
|
161
|
-
|
|
199
|
+
// this is good for testing, to determine whether a key press is detected
|
|
200
|
+
case /^([0-9]?)$/.test(event.key):
|
|
162
201
|
|
|
163
|
-
|
|
202
|
+
break;
|
|
164
203
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
168
207
|
|
|
169
|
-
/**
|
|
170
|
-
* used by boot() to update inputs marked with data-univHMS
|
|
171
|
-
* @method
|
|
172
|
-
* @see boot()
|
|
173
|
-
*/
|
|
174
208
|
|
|
175
|
-
|
|
209
|
+
/**
|
|
210
|
+
* updates inputs-duration marked with shadow html and css
|
|
211
|
+
* @method
|
|
212
|
+
* @see boot()
|
|
213
|
+
*/
|
|
176
214
|
|
|
177
|
-
|
|
215
|
+
addHTML() {
|
|
178
216
|
|
|
179
|
-
|
|
217
|
+
var spanIn = document.createElement("div");
|
|
180
218
|
|
|
181
|
-
|
|
219
|
+
spanIn.classList.add('timeCase');
|
|
182
220
|
|
|
183
|
-
|
|
221
|
+
var template = document.createElement('template');
|
|
222
|
+
|
|
223
|
+
template.innerHTML = `
|
|
184
224
|
<input id="inShadow" type="number" class="sH D2 ts_digit" name="startHours" data-tp="1" min="-1" max="100" value="00" >
|
|
185
225
|
<span class="bds-h">:</span>
|
|
186
226
|
<input type="number" class="sM D2 ts_digit" name="startMinutes" data-tp="2" min="-1" max="60" value="00">
|
|
@@ -196,515 +236,375 @@ class InputDuration extends HTMLElement {
|
|
|
196
236
|
</svg>
|
|
197
237
|
</div>
|
|
198
238
|
<style>
|
|
199
|
-
*:focus {
|
|
200
|
-
outline: none;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
div.timeCase{
|
|
205
|
-
display: inline-flex;
|
|
206
|
-
flex-direction: row;
|
|
207
|
-
max-width: 300px;
|
|
208
|
-
padding: 3px;
|
|
209
|
-
border-style: solid;
|
|
210
|
-
border-width: 1px;
|
|
211
|
-
border-radius: 2px;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
/* Each input width set and blinking cursor 'caret' removed */
|
|
216
|
-
div.timeCase input{
|
|
217
|
-
caret-color: transparent;
|
|
218
|
-
width: 15px;
|
|
219
|
-
padding-top:1px;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
div.timeCase .D3{
|
|
224
|
-
width: 25px;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
/* Hiding the up and down arrow */
|
|
229
|
-
/*https://www.w3schools.com/howto/howto_css_hide_arrow_number.asp*/
|
|
230
|
-
/* Chrome, Safari, Edge, Opera */
|
|
231
|
-
|
|
232
|
-
input::-webkit-outer-spin-button,
|
|
233
|
-
input::-webkit-inner-spin-button {
|
|
234
|
-
-webkit-appearance: none;
|
|
235
|
-
margin: 0;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
/* Firefox */
|
|
240
|
-
|
|
241
|
-
input[type=number] {
|
|
242
|
-
/* -moz-appearance: textfield; */
|
|
243
|
-
-moz-appearance: textarea;
|
|
244
|
-
-webkit-appearance: textarea;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
div.timeCase:focus-within {
|
|
249
|
-
border: 2px solid black;
|
|
250
|
-
padding: 2px;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
.ts_digit {
|
|
255
|
-
border: none;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/* between digit span */
|
|
259
|
-
.bds{
|
|
260
|
-
padding-bottom: 1px;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
#svgContainer {
|
|
264
|
-
width: 12px;
|
|
265
|
-
height: 12px;
|
|
266
|
-
padding-top: 1px;
|
|
267
|
-
padding-right: 2px;
|
|
268
|
-
color: black;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
*:disabled {
|
|
272
|
-
background-color: grey;
|
|
273
|
-
color: lightgrey;
|
|
274
|
-
opacity: .6;
|
|
275
|
-
}
|
|
276
|
-
</style> `
|
|
277
|
-
|
|
278
|
-
spanIn.appendChild(template.content);
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
// const chronlyCssLink = document.createElement('link');
|
|
282
|
-
// let link = document.createElement('link');
|
|
283
|
-
// chronlyCssLink.setAttribute('rel', 'stylesheet');
|
|
284
|
-
// chronlyCssLink.setAttribute('href', 'chronlyWebComponent.css');
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
this.myElement.appendChild(spanIn);
|
|
239
|
+
*:focus {
|
|
240
|
+
outline: none;
|
|
241
|
+
}
|
|
292
242
|
|
|
293
|
-
// this.myElement.appendChild(chronlyCssLink);
|
|
294
243
|
|
|
295
|
-
|
|
244
|
+
div.timeCase{
|
|
245
|
+
display: inline-flex;
|
|
246
|
+
flex-direction: row;
|
|
247
|
+
max-width: 300px;
|
|
248
|
+
padding: 3px;
|
|
249
|
+
border-style: solid;
|
|
250
|
+
border-width: 1px;
|
|
251
|
+
border-radius: 2px;
|
|
252
|
+
}
|
|
296
253
|
|
|
297
254
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
255
|
+
/* Each input width set and blinking cursor 'caret' removed */
|
|
256
|
+
div.timeCase input{
|
|
257
|
+
caret-color: transparent;
|
|
258
|
+
width: 15px;
|
|
259
|
+
padding-top:1px;
|
|
260
|
+
}
|
|
304
261
|
|
|
305
|
-
addNumberLooping() {
|
|
306
262
|
|
|
307
|
-
|
|
308
|
-
|
|
263
|
+
div.timeCase .D3{
|
|
264
|
+
width: 25px;
|
|
265
|
+
}
|
|
309
266
|
|
|
310
|
-
const sH = this.myElement.querySelector("input.sH");
|
|
311
|
-
sH.addEventListener('change', function (event) {
|
|
312
267
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
if (sH.value == -1) {
|
|
317
|
-
sH.value = 99;
|
|
318
|
-
}
|
|
268
|
+
/* Hiding the up and down arrow */
|
|
269
|
+
/*https://www.w3schools.com/howto/howto_css_hide_arrow_number.asp*/
|
|
270
|
+
/* Chrome, Safari, Edge, Opera */
|
|
319
271
|
|
|
320
|
-
|
|
272
|
+
input::-webkit-outer-spin-button,
|
|
273
|
+
input::-webkit-inner-spin-button {
|
|
274
|
+
-webkit-appearance: none;
|
|
275
|
+
margin: 0;
|
|
276
|
+
}
|
|
321
277
|
|
|
322
|
-
const sM = this.myElement.querySelector("input.sM");
|
|
323
|
-
sM.addEventListener('change', function (event) {
|
|
324
278
|
|
|
325
|
-
|
|
326
|
-
sM.value = '00';
|
|
327
|
-
}
|
|
328
|
-
if (sM.value == -1) {
|
|
329
|
-
sM.value = 59;
|
|
330
|
-
}
|
|
279
|
+
/* Firefox */
|
|
331
280
|
|
|
332
|
-
|
|
281
|
+
input[type=number] {
|
|
282
|
+
/* -moz-appearance: textfield; */
|
|
283
|
+
-moz-appearance: textarea;
|
|
284
|
+
-webkit-appearance: textarea;
|
|
285
|
+
}
|
|
333
286
|
|
|
334
|
-
const sS = this.myElement.querySelector("input.sS");
|
|
335
|
-
sS.addEventListener('change', function (event) {
|
|
336
287
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
288
|
+
div.timeCase:focus-within {
|
|
289
|
+
border: 2px solid black;
|
|
290
|
+
padding: 2px;
|
|
291
|
+
}
|
|
340
292
|
|
|
341
|
-
if (sS.value == -1) {
|
|
342
|
-
sS.value = 59;
|
|
343
|
-
}
|
|
344
293
|
|
|
345
|
-
|
|
294
|
+
.ts_digit {
|
|
295
|
+
border: none;
|
|
296
|
+
}
|
|
346
297
|
|
|
298
|
+
/* between digit span */
|
|
299
|
+
.bds{
|
|
300
|
+
padding-bottom: 1px;
|
|
301
|
+
}
|
|
347
302
|
|
|
348
|
-
|
|
349
|
-
|
|
303
|
+
#svgContainer {
|
|
304
|
+
width: 12px;
|
|
305
|
+
height: 12px;
|
|
306
|
+
padding-top: 1px;
|
|
307
|
+
padding-right: 2px;
|
|
308
|
+
color: black;
|
|
309
|
+
}
|
|
350
310
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
311
|
+
*:disabled {
|
|
312
|
+
background-color: grey;
|
|
313
|
+
color: lightgrey;
|
|
314
|
+
opacity: .6;
|
|
315
|
+
}
|
|
316
|
+
</style> `
|
|
354
317
|
|
|
355
|
-
|
|
356
|
-
sMS.value = 990;
|
|
357
|
-
}
|
|
318
|
+
spanIn.appendChild(template.content);
|
|
358
319
|
|
|
359
|
-
|
|
360
|
-
}
|
|
320
|
+
this.myElement.appendChild(spanIn);
|
|
361
321
|
|
|
362
|
-
|
|
363
|
-
}
|
|
322
|
+
}
|
|
364
323
|
|
|
365
|
-
addNumericInput() {
|
|
366
324
|
|
|
367
|
-
|
|
325
|
+
/**
|
|
326
|
+
* eventlistener that adds number looping for up and down keys triggered by
|
|
327
|
+
* the change event of the input
|
|
328
|
+
* @method
|
|
329
|
+
* @see boot()
|
|
330
|
+
*/
|
|
368
331
|
|
|
369
|
-
|
|
370
|
-
// Digit input 0-9 (typed in by user)
|
|
332
|
+
addNumberLooping() {
|
|
371
333
|
|
|
372
|
-
|
|
373
|
-
|
|
334
|
+
// Numeric Value looping (eventually this can be 'parameterised' refactored)
|
|
335
|
+
// ex. 99 uparrow to 0 hours, 59 uparrow to 0 minutes and seconds, 990 uparrow to 010, downarrow 000 milliseconds
|
|
374
336
|
|
|
375
|
-
|
|
376
|
-
|
|
337
|
+
const sH = this.myElement.querySelector("input.sH");
|
|
338
|
+
sH.addEventListener('change', function (event) {
|
|
377
339
|
|
|
378
|
-
|
|
340
|
+
if (sH.value == 100) {
|
|
341
|
+
sH.value = '00';
|
|
342
|
+
}
|
|
343
|
+
if (sH.value == -1) {
|
|
344
|
+
sH.value = 99;
|
|
345
|
+
}
|
|
379
346
|
|
|
380
|
-
|
|
347
|
+
});
|
|
381
348
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
this.oldValue = this.value;
|
|
385
|
-
this.oldSelectionStart = this.selectionStart;
|
|
386
|
-
this.oldSelectionEnd = this.selectionEnd;
|
|
387
|
-
} else if (this.hasOwnProperty("oldValue")) {
|
|
388
|
-
this.value = this.oldValue;
|
|
389
|
-
// this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
|
|
390
|
-
} else {
|
|
391
|
-
this.value = "";
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
});
|
|
395
|
-
}
|
|
349
|
+
const sM = this.myElement.querySelector("input.sM");
|
|
350
|
+
sM.addEventListener('change', function (event) {
|
|
396
351
|
|
|
352
|
+
if (sM.value == 60) {
|
|
353
|
+
sM.value = '00';
|
|
354
|
+
}
|
|
355
|
+
if (sM.value == -1) {
|
|
356
|
+
sM.value = 59;
|
|
357
|
+
}
|
|
397
358
|
|
|
398
|
-
|
|
359
|
+
});
|
|
399
360
|
|
|
400
|
-
|
|
401
|
-
|
|
361
|
+
const sS = this.myElement.querySelector("input.sS");
|
|
362
|
+
sS.addEventListener('change', function (event) {
|
|
402
363
|
|
|
403
|
-
|
|
364
|
+
if (sS.value == 60) {
|
|
365
|
+
sS.value = '00';
|
|
366
|
+
}
|
|
404
367
|
|
|
405
|
-
|
|
368
|
+
if (sS.value == -1) {
|
|
369
|
+
sS.value = 59;
|
|
370
|
+
}
|
|
406
371
|
|
|
372
|
+
});
|
|
407
373
|
|
|
408
|
-
|
|
374
|
+
const sMS = this.myElement.querySelector("input.sMS");
|
|
375
|
+
sMS.addEventListener('change', function (event) {
|
|
409
376
|
|
|
410
|
-
|
|
411
|
-
|
|
377
|
+
if (sMS.value == 1000) {
|
|
378
|
+
sMS.value = "010";
|
|
379
|
+
}
|
|
412
380
|
|
|
413
|
-
|
|
381
|
+
if (sMS.value == -10) {
|
|
382
|
+
sMS.value = 990;
|
|
383
|
+
}
|
|
414
384
|
|
|
415
|
-
|
|
385
|
+
if (sMS.value == 0) {
|
|
386
|
+
}
|
|
416
387
|
|
|
417
|
-
|
|
388
|
+
});
|
|
389
|
+
}
|
|
418
390
|
|
|
419
|
-
var sM = this.myElement.querySelector('input.sM');
|
|
420
|
-
setInputFilter(sM, function (value) {
|
|
421
391
|
|
|
392
|
+
/**
|
|
393
|
+
* eventlistener that adds number input for keyed values triggered by the keyup event
|
|
394
|
+
* @method
|
|
395
|
+
* @see boot()
|
|
396
|
+
*/
|
|
422
397
|
|
|
423
|
-
|
|
398
|
+
addNumericInput() {
|
|
424
399
|
|
|
425
|
-
|
|
400
|
+
const mE = this.myElement;
|
|
426
401
|
|
|
427
|
-
|
|
428
|
-
|
|
402
|
+
// https://stackoverflow.com/questions/469357/html-text-input-allow-only-numeric-input
|
|
403
|
+
// Digit input 0-9 (typed in by user)
|
|
429
404
|
|
|
430
|
-
|
|
405
|
+
function setInputFilter(inputElement, inputFilter) {
|
|
406
|
+
// this sets a listener and immediately updates the value of the input number (note: can update this from input text, like by removing setSelectionRange )
|
|
431
407
|
|
|
432
|
-
|
|
408
|
+
console.log('inputElement: ' + inputElement);
|
|
409
|
+
window.inputElement = inputElement;
|
|
433
410
|
|
|
434
|
-
|
|
411
|
+
inputElement.addEventListener('keyup', function (event) {
|
|
435
412
|
|
|
436
|
-
|
|
437
|
-
setInputFilter(sS, function (value) {
|
|
413
|
+
window.kue = event;
|
|
438
414
|
|
|
439
|
-
|
|
415
|
+
if (/^([0-9]?)$/.test(event.key)) {
|
|
416
|
+
if (inputFilter(this.value)) {
|
|
417
|
+
this.oldValue = this.value;
|
|
418
|
+
this.oldSelectionStart = this.selectionStart;
|
|
419
|
+
this.oldSelectionEnd = this.selectionEnd;
|
|
420
|
+
} else if (this.hasOwnProperty("oldValue")) {
|
|
421
|
+
this.value = this.oldValue;
|
|
422
|
+
// this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
|
|
423
|
+
} else {
|
|
424
|
+
this.value = "";
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
}
|
|
440
429
|
|
|
441
|
-
|
|
430
|
+
// three filters, hours or minutes and seconds (are the same) but milliseconds is different
|
|
442
431
|
|
|
443
|
-
|
|
444
|
-
mE.querySelector('input.sMS').select();
|
|
432
|
+
var sH = this.myElement.querySelector('input.sH');
|
|
445
433
|
|
|
446
|
-
|
|
434
|
+
setInputFilter(sH, function (value) {
|
|
447
435
|
|
|
448
|
-
|
|
436
|
+
var newV = /^([0-9]?|[0-9][0-9]?)$/.test(value);
|
|
449
437
|
|
|
450
|
-
});
|
|
451
438
|
|
|
439
|
+
if (value.length === 2) {
|
|
452
440
|
|
|
453
|
-
|
|
454
|
-
|
|
441
|
+
mE.querySelector('input.sM').focus();
|
|
442
|
+
mE.querySelector('input.sM').select();
|
|
455
443
|
|
|
456
|
-
|
|
444
|
+
}
|
|
457
445
|
|
|
446
|
+
return newV;
|
|
458
447
|
|
|
459
|
-
|
|
448
|
+
});
|
|
460
449
|
|
|
461
|
-
|
|
450
|
+
var sM = this.myElement.querySelector('input.sM');
|
|
451
|
+
setInputFilter(sM, function (value) {
|
|
462
452
|
|
|
463
|
-
}
|
|
464
453
|
|
|
465
|
-
|
|
454
|
+
var newV = /^([0-9]?|[0-5][0-9]?)$/.test(value);
|
|
466
455
|
|
|
467
|
-
|
|
456
|
+
if (value > 5 || value.length === 2) {
|
|
468
457
|
|
|
469
|
-
|
|
458
|
+
mE.querySelector('input.sS').focus();
|
|
459
|
+
mE.querySelector('input.sS').select();
|
|
470
460
|
|
|
461
|
+
}
|
|
471
462
|
|
|
472
|
-
|
|
473
|
-
* each time Chronly is newed up, the constructor uses checkBoot() to
|
|
474
|
-
* 1) check for an existing window.ChronlyFlag if there is one
|
|
475
|
-
* 2) clear events a) named events, b) remove
|
|
476
|
-
* 3) add events
|
|
477
|
-
* @method
|
|
478
|
-
*/
|
|
463
|
+
return newV;
|
|
479
464
|
|
|
480
|
-
|
|
465
|
+
});
|
|
481
466
|
|
|
482
|
-
|
|
467
|
+
var sS = this.myElement.querySelector('input.sS');
|
|
468
|
+
setInputFilter(sS, function (value) {
|
|
483
469
|
|
|
470
|
+
var newV = /^([0-9]?|[0-5][0-9]?)$/.test(value);
|
|
484
471
|
|
|
485
|
-
|
|
486
|
-
// this.reboot();
|
|
487
|
-
// }
|
|
488
|
-
// else {
|
|
489
|
-
// this.boot();
|
|
490
|
-
// }
|
|
491
|
-
}
|
|
472
|
+
if (value > 5 || value.length === 2) {
|
|
492
473
|
|
|
474
|
+
mE.querySelector('input.sMS').focus();
|
|
475
|
+
mE.querySelector('input.sMS').select();
|
|
493
476
|
|
|
477
|
+
}
|
|
494
478
|
|
|
495
|
-
|
|
496
|
-
* used by checkBoot() and externally exposed for user
|
|
497
|
-
* @method
|
|
498
|
-
*
|
|
499
|
-
*/
|
|
479
|
+
return newV;
|
|
500
480
|
|
|
501
|
-
|
|
481
|
+
});
|
|
502
482
|
|
|
503
|
-
this.addHTML();
|
|
504
|
-
// this.addCSS();
|
|
505
|
-
this.blockNonNumberInput();
|
|
506
483
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
this.addNumberLooping();
|
|
510
|
-
this.addArrowKeyInput();
|
|
511
|
-
this.addNumericInput();
|
|
512
|
-
this.addClicksToActivate();
|
|
513
|
-
this.nonNumericBugInHTML();
|
|
514
|
-
// this.updatePrototype();
|
|
484
|
+
var sMS = this.myElement.querySelector('input.sMS');
|
|
485
|
+
setInputFilter(sMS, function (value) {
|
|
515
486
|
|
|
487
|
+
var newV = /^([0-9]?|[0-9][0-9]?|[0-9][0-9][0-9]?)$/.test(value);
|
|
516
488
|
|
|
517
|
-
/**
|
|
518
|
-
* window.ChronlyFlag declared here
|
|
519
|
-
* @global
|
|
520
|
-
*/
|
|
521
|
-
// this.ChronlyFlag = true;
|
|
522
|
-
}
|
|
523
489
|
|
|
490
|
+
if (value.length === 3) {
|
|
524
491
|
|
|
492
|
+
mE.querySelector('input.sMS').blur();
|
|
525
493
|
|
|
526
|
-
|
|
494
|
+
}
|
|
527
495
|
|
|
496
|
+
return newV;
|
|
528
497
|
|
|
529
|
-
|
|
498
|
+
});
|
|
499
|
+
}
|
|
530
500
|
|
|
531
501
|
|
|
532
|
-
|
|
502
|
+
/**
|
|
503
|
+
* eventlistener that adds 0s to preface numbers less than 10 triggered by
|
|
504
|
+
* the change event of the input
|
|
505
|
+
* @method
|
|
506
|
+
* @see boot()
|
|
507
|
+
*/
|
|
533
508
|
|
|
534
|
-
|
|
509
|
+
add0s() {
|
|
535
510
|
|
|
511
|
+
// input for hours, minutes, seconds
|
|
512
|
+
this.myElement.querySelectorAll('input').forEach(i => i.addEventListener('change', function () {
|
|
513
|
+
if (!isNaN(this.value) && this.value.length === 1) {
|
|
514
|
+
this.value = '0' + this.value;
|
|
515
|
+
}
|
|
516
|
+
}));
|
|
536
517
|
|
|
537
|
-
|
|
518
|
+
// milliseconds
|
|
519
|
+
this.myElement.querySelectorAll("input.sMS").forEach(i => i.addEventListener('change', function () {
|
|
538
520
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
* @see boot()
|
|
543
|
-
* /
|
|
544
|
-
|
|
545
|
-
addCSS(){
|
|
521
|
+
if (!isNaN(this.value) && this.value.length === 2) {
|
|
522
|
+
this.value = '0' + this.value;
|
|
523
|
+
}
|
|
546
524
|
|
|
547
|
-
|
|
525
|
+
}));
|
|
548
526
|
|
|
527
|
+
}
|
|
528
|
+
|
|
549
529
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
530
|
+
/**
|
|
531
|
+
* eventlistener that adds click to activate input of values by the keyboard triggered by
|
|
532
|
+
* the click event of the input
|
|
533
|
+
* @method
|
|
534
|
+
* @see boot()
|
|
535
|
+
*/
|
|
556
536
|
|
|
557
|
-
|
|
537
|
+
addClicksToActivate() {
|
|
558
538
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
if (!isNaN(this.value) && this.value.length === 1) {
|
|
562
|
-
this.value = '0' + this.value;
|
|
563
|
-
}
|
|
564
|
-
}));
|
|
539
|
+
this.myElement.querySelectorAll('input').forEach(i => i.addEventListener("click", function () { this.select(); }))
|
|
540
|
+
}
|
|
565
541
|
|
|
566
|
-
// milliseconds
|
|
567
|
-
this.myElement.querySelectorAll("input.sMS").forEach(i => i.addEventListener('change', function () {
|
|
568
542
|
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
543
|
+
/**
|
|
544
|
+
* eventlistener that adds key filtering to stop letters (or other non-numerics) from being input triggered by
|
|
545
|
+
* the keypress event of the input
|
|
546
|
+
* @method
|
|
547
|
+
* @see boot()
|
|
548
|
+
*/
|
|
572
549
|
|
|
573
|
-
|
|
550
|
+
nonNumericBugInHTML() {
|
|
574
551
|
|
|
575
|
-
|
|
552
|
+
this.myElement.querySelectorAll(".timeCase input").forEach(item =>
|
|
576
553
|
|
|
554
|
+
item.addEventListener('keypress', function (e) {
|
|
577
555
|
|
|
578
|
-
|
|
556
|
+
e = e || window.event;
|
|
557
|
+
var charCode = (typeof e.which == "undefined") ? e.keyCode : e.which;
|
|
558
|
+
var charStr = String.fromCharCode(charCode);
|
|
579
559
|
|
|
580
|
-
|
|
560
|
+
if (!charStr.match(/^[0-9]+$/))
|
|
561
|
+
e.preventDefault();
|
|
581
562
|
|
|
582
|
-
|
|
563
|
+
}));
|
|
564
|
+
}
|
|
583
565
|
|
|
584
|
-
item.addEventListener('keypress', function (e) {
|
|
585
566
|
|
|
586
|
-
|
|
587
|
-
var charCode = (typeof e.which == "undefined") ? e.keyCode : e.which;
|
|
588
|
-
var charStr = String.fromCharCode(charCode);
|
|
567
|
+
// formatting and behaviour options
|
|
589
568
|
|
|
590
|
-
|
|
591
|
-
|
|
569
|
+
/**
|
|
570
|
+
* disables entire control => read-only
|
|
571
|
+
* @method
|
|
572
|
+
*/
|
|
592
573
|
|
|
593
|
-
|
|
594
|
-
}
|
|
574
|
+
disable() {
|
|
595
575
|
|
|
576
|
+
var closure = this;
|
|
596
577
|
|
|
597
|
-
|
|
578
|
+
// disable chronly inputs on page
|
|
598
579
|
|
|
599
|
-
|
|
580
|
+
closure.shadowRoot.querySelectorAll(".timeCase input").forEach(el => el.disabled = 'true')
|
|
600
581
|
|
|
582
|
+
}
|
|
601
583
|
|
|
602
|
-
ChronlyHMSElement.prototype.__defineGetter__('value', function () {
|
|
603
584
|
|
|
604
|
-
|
|
585
|
+
/**
|
|
586
|
+
* removes the hours, so the display is mm:ss.uuu
|
|
587
|
+
* @method
|
|
588
|
+
*/
|
|
605
589
|
|
|
606
|
-
|
|
607
|
-
':' + this.myElement.querySelector('input[name="startMinutes"]').value +
|
|
608
|
-
':' + this.myElement.querySelector('input[name="startSeconds"]').value +
|
|
609
|
-
'.' + this.myElement.querySelector('input[name="startMilliSecs"]').value;
|
|
590
|
+
noHours() {
|
|
610
591
|
|
|
611
|
-
|
|
612
|
-
else {
|
|
592
|
+
var closure = this;
|
|
613
593
|
|
|
614
|
-
|
|
594
|
+
// hide chronly hours inputs on page
|
|
615
595
|
|
|
616
|
-
|
|
617
|
-
});
|
|
596
|
+
closure.shadowRoot.querySelectorAll(".timeCase input.sH").forEach(el => el.style.display = 'none');
|
|
618
597
|
|
|
619
598
|
|
|
599
|
+
// hide the hours colon on page
|
|
620
600
|
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
// will need warning about timeString format (like input type='time')
|
|
624
|
-
|
|
625
|
-
if (/(^[0-9][0-9]):([0-5][0-9]):([0-5][0-9])\.([0-9][0-9][0-9]$)/.exec(timeString)) {
|
|
626
|
-
|
|
627
|
-
// split val
|
|
628
|
-
|
|
629
|
-
var timeArray = timeString.split(/[.:]+/);
|
|
630
|
-
|
|
631
|
-
this.myElement.querySelector('input[name="startHours"]').value = timeArray[0];
|
|
632
|
-
this.myElement.querySelector('input[name="startMinutes"]').value = timeArray[1];
|
|
633
|
-
this.myElement.querySelector('input[name="startSeconds"]').value = timeArray[2];
|
|
634
|
-
this.myElement.querySelector('input[name="startMilliSecs"]').value = timeArray[3];
|
|
635
|
-
|
|
636
|
-
}
|
|
637
|
-
else {
|
|
638
|
-
|
|
639
|
-
console.warn(`The specified value ${timeString} does not conform to the required format. The format is "HH:mm:ss.SSS" where HH is 00-99, mm is 00-59, ss is 00-59, and SSS is 000-999.`);
|
|
640
|
-
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
});
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
/**
|
|
647
|
-
* eventlistener that adds click to activate input of values by the keyboard triggered by
|
|
648
|
-
* the click event of the input
|
|
649
|
-
* @method
|
|
650
|
-
* @see boot()
|
|
651
|
-
*/
|
|
652
|
-
|
|
653
|
-
addClicksToActivate() {
|
|
654
|
-
|
|
655
|
-
this.myElement.querySelectorAll('input').forEach(i => i.addEventListener("click", function () { this.select(); }))
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
noHours() {
|
|
660
|
-
|
|
661
|
-
var closure = this;
|
|
662
|
-
|
|
663
|
-
// hide chronly hours inputs on page
|
|
664
|
-
|
|
665
|
-
closure.shadowRoot.querySelectorAll(".timeCase input.sH").forEach(el => el.style.display = 'none');
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
// hide the hours colon on page
|
|
669
|
-
|
|
670
|
-
closure.shadowRoot.querySelectorAll(".timeCase span.bds-h").forEach(el => el.style.display = 'none');
|
|
671
|
-
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
/**
|
|
681
|
-
* eventlistener that adds key filtering to stop letters (or other non-numerics) from being input triggered by
|
|
682
|
-
* the keypress event of the input
|
|
683
|
-
* @method
|
|
684
|
-
* @see boot()
|
|
685
|
-
*/
|
|
686
|
-
|
|
687
|
-
nonNumericBugInHTML() {
|
|
688
|
-
|
|
689
|
-
this.myElement.querySelectorAll(".timeCase input").forEach(item =>
|
|
690
|
-
|
|
691
|
-
item.addEventListener('keypress', function (e) {
|
|
692
|
-
|
|
693
|
-
e = e || window.event;
|
|
694
|
-
var charCode = (typeof e.which == "undefined") ? e.keyCode : e.which;
|
|
695
|
-
var charStr = String.fromCharCode(charCode);
|
|
696
|
-
|
|
697
|
-
if (!charStr.match(/^[0-9]+$/))
|
|
698
|
-
e.preventDefault();
|
|
699
|
-
|
|
700
|
-
}));
|
|
701
|
-
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
} // end class
|
|
601
|
+
closure.shadowRoot.querySelectorAll(".timeCase span.bds-h").forEach(el => el.style.display = 'none');
|
|
706
602
|
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
// end class
|
|
707
606
|
|
|
708
|
-
// page script (try making this auto instantiate in module like PM does)
|
|
709
607
|
|
|
710
608
|
export default customElements.define('input-duration', InputDuration);
|
|
609
|
+
|
|
610
|
+
// an option is to make all above an IIFE
|