input-duration 3.1.0 → 3.2.1
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 +18 -2
- package/docs/InputDuration.html +3506 -528
- package/docs/index.js.html +466 -181
- package/index.js +276 -14
- package/package.json +2 -2
package/index.js
CHANGED
|
@@ -17,28 +17,72 @@
|
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Class for the Input-Duration webcomponent
|
|
20
|
+
*
|
|
21
|
+
* Boolean attributes `no-hours`, `no-minutes`, `no-seconds`, and
|
|
22
|
+
* `no-microseconds` hide their respective fields. String attributes
|
|
23
|
+
* `hours-divider`, `minutes-divider`, `seconds-divider`, and
|
|
24
|
+
* `microseconds-divider` customize the separators; the last adds a suffix
|
|
25
|
+
* after milliseconds. Divider values are rendered as text.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* <input-duration no-microseconds hours-divider="h " microseconds-divider="ms"></input-duration>
|
|
29
|
+
*
|
|
20
30
|
* @class InputDuration
|
|
21
31
|
* @extends HTMLElement
|
|
22
32
|
*/
|
|
23
33
|
|
|
24
34
|
class InputDuration extends HTMLElement {
|
|
35
|
+
/**
|
|
36
|
+
* HTML attributes that update the component when changed.
|
|
37
|
+
*
|
|
38
|
+
* @static
|
|
39
|
+
* @returns {string[]} Observed value, visibility, and divider attributes.
|
|
40
|
+
*/
|
|
25
41
|
static get observedAttributes() {
|
|
26
|
-
return [
|
|
42
|
+
return [
|
|
43
|
+
'value',
|
|
44
|
+
'no-hours',
|
|
45
|
+
'no-minutes',
|
|
46
|
+
'no-seconds',
|
|
47
|
+
'no-microseconds',
|
|
48
|
+
'hours-divider',
|
|
49
|
+
'minutes-divider',
|
|
50
|
+
'seconds-divider',
|
|
51
|
+
'microseconds-divider'
|
|
52
|
+
];
|
|
27
53
|
}
|
|
28
54
|
|
|
29
55
|
constructor() {
|
|
30
56
|
|
|
31
57
|
super();
|
|
32
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Shadow root containing this component's controls.
|
|
61
|
+
* @type {ShadowRoot}
|
|
62
|
+
*/
|
|
33
63
|
this.myElement = this.attachShadow({ mode: 'open' });
|
|
34
64
|
|
|
35
65
|
this.boot();
|
|
36
66
|
|
|
37
67
|
} // end constructor
|
|
38
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Updates the rendered control when an observed attribute changes.
|
|
71
|
+
*
|
|
72
|
+
* @param {string} name - Changed attribute name.
|
|
73
|
+
* @param {?string} oldValue - Previous attribute value.
|
|
74
|
+
* @param {?string} newValue - New attribute value, or null when removed.
|
|
75
|
+
* @returns {void}
|
|
76
|
+
*/
|
|
39
77
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
40
78
|
|
|
41
|
-
if (
|
|
79
|
+
if (oldValue === newValue) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (name !== 'value') {
|
|
84
|
+
this.updateVisibleFields();
|
|
85
|
+
this.updateDividers();
|
|
42
86
|
return;
|
|
43
87
|
}
|
|
44
88
|
|
|
@@ -55,7 +99,7 @@ class InputDuration extends HTMLElement {
|
|
|
55
99
|
/**
|
|
56
100
|
* get the input-duration value, pulls values from each input
|
|
57
101
|
* so in js use var x = document.querySelector("#bobPrepop").value;
|
|
58
|
-
* @
|
|
102
|
+
* @returns {?string} Duration in `HH:mm:ss.SSS` format, or null before initialization.
|
|
59
103
|
*/
|
|
60
104
|
|
|
61
105
|
get value() {
|
|
@@ -79,10 +123,10 @@ class InputDuration extends HTMLElement {
|
|
|
79
123
|
|
|
80
124
|
|
|
81
125
|
/**
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* @
|
|
85
|
-
* @
|
|
126
|
+
* Sets the duration using the fixed `HH:mm:ss.SSS` format.
|
|
127
|
+
*
|
|
128
|
+
* @param {string} val - Duration string, such as `05:05:05.005`.
|
|
129
|
+
* @returns {void}
|
|
86
130
|
*/
|
|
87
131
|
|
|
88
132
|
set value(val) {
|
|
@@ -106,11 +150,23 @@ class InputDuration extends HTMLElement {
|
|
|
106
150
|
}
|
|
107
151
|
}
|
|
108
152
|
|
|
153
|
+
/**
|
|
154
|
+
* Checks whether a value follows the supported duration format and ranges.
|
|
155
|
+
*
|
|
156
|
+
* @param {*} val - Candidate value.
|
|
157
|
+
* @returns {boolean} Whether the value is valid `HH:mm:ss.SSS`.
|
|
158
|
+
*/
|
|
109
159
|
isValidValue(val) {
|
|
110
160
|
return typeof val === 'string' &&
|
|
111
161
|
/^[0-9]{2}:[0-5][0-9]:[0-5][0-9]\.[0-9]{3}$/.test(val);
|
|
112
162
|
}
|
|
113
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Copies a validated duration string into the four shadow inputs.
|
|
166
|
+
*
|
|
167
|
+
* @param {string} val - Valid duration in `HH:mm:ss.SSS` format.
|
|
168
|
+
* @returns {void}
|
|
169
|
+
*/
|
|
114
170
|
setInputValues(val) {
|
|
115
171
|
const timeArray = val.split(/[.:]+/);
|
|
116
172
|
const inputNames = ['startHours', 'startMinutes', 'startSeconds', 'startMilliSecs'];
|
|
@@ -122,6 +178,11 @@ class InputDuration extends HTMLElement {
|
|
|
122
178
|
});
|
|
123
179
|
}
|
|
124
180
|
|
|
181
|
+
/**
|
|
182
|
+
* Resets all duration fields to zero.
|
|
183
|
+
*
|
|
184
|
+
* @returns {void}
|
|
185
|
+
*/
|
|
125
186
|
resetInputs() {
|
|
126
187
|
const defaults = ['00', '00', '00', '000'];
|
|
127
188
|
const inputs = this.myElement.querySelectorAll('.timeCase input');
|
|
@@ -132,6 +193,12 @@ class InputDuration extends HTMLElement {
|
|
|
132
193
|
});
|
|
133
194
|
}
|
|
134
195
|
|
|
196
|
+
/**
|
|
197
|
+
* Reports a value that does not match the supported duration format.
|
|
198
|
+
*
|
|
199
|
+
* @param {*} val - Rejected value.
|
|
200
|
+
* @returns {void}
|
|
201
|
+
*/
|
|
135
202
|
warnInvalidValue(val) {
|
|
136
203
|
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.`);
|
|
137
204
|
}
|
|
@@ -249,6 +316,7 @@ class InputDuration extends HTMLElement {
|
|
|
249
316
|
<input type="number" class="sS D2 ts_digit" part="field field-seconds" name="startSeconds" data-tp="3" min="-1" max="60" value="00">
|
|
250
317
|
<span class="bds-s" part="divider divider-seconds-milliseconds">.</span>
|
|
251
318
|
<input type="number" class="sMS D3 ts_digit" part="field field-milliseconds" name="startMilliSecs" data-tp="4" min="-10" max="1010" step="10" value="000">
|
|
319
|
+
<span class="bds-ms" part="divider divider-milliseconds-suffix" style="display: none"></span>
|
|
252
320
|
<div id="svgContainer" part="icon">
|
|
253
321
|
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true"
|
|
254
322
|
focusable="false" data-prefix="fal" data-icon="stopwatch" class="svg-inline--fa fa-stopwatch fa-w-14"
|
|
@@ -631,23 +699,217 @@ class InputDuration extends HTMLElement {
|
|
|
631
699
|
|
|
632
700
|
|
|
633
701
|
/**
|
|
634
|
-
*
|
|
635
|
-
*
|
|
702
|
+
* Hides the hours field and its adjacent divider.
|
|
703
|
+
* Sets the `no-hours` attribute.
|
|
704
|
+
*
|
|
705
|
+
* @returns {void}
|
|
636
706
|
*/
|
|
707
|
+
hideHours() {
|
|
708
|
+
this.setAttribute('no-hours', '');
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* Shows the hours field and its adjacent divider.
|
|
713
|
+
* Removes the `no-hours` attribute.
|
|
714
|
+
*
|
|
715
|
+
* @returns {void}
|
|
716
|
+
*/
|
|
717
|
+
showHours() {
|
|
718
|
+
this.removeAttribute('no-hours');
|
|
719
|
+
}
|
|
637
720
|
|
|
721
|
+
/**
|
|
722
|
+
* Backward-compatible alias for {@link InputDuration#hideHours}.
|
|
723
|
+
*
|
|
724
|
+
* @returns {void}
|
|
725
|
+
*/
|
|
638
726
|
noHours() {
|
|
727
|
+
this.hideHours();
|
|
728
|
+
}
|
|
639
729
|
|
|
640
|
-
|
|
730
|
+
/**
|
|
731
|
+
* Hides the minutes field and its adjacent divider.
|
|
732
|
+
* Sets the `no-minutes` attribute.
|
|
733
|
+
*
|
|
734
|
+
* @returns {void}
|
|
735
|
+
*/
|
|
736
|
+
hideMinutes() {
|
|
737
|
+
this.setAttribute('no-minutes', '');
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
/**
|
|
741
|
+
* Shows the minutes field and its adjacent divider.
|
|
742
|
+
* Removes the `no-minutes` attribute.
|
|
743
|
+
*
|
|
744
|
+
* @returns {void}
|
|
745
|
+
*/
|
|
746
|
+
showMinutes() {
|
|
747
|
+
this.removeAttribute('no-minutes');
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* Backward-compatible alias for {@link InputDuration#hideMinutes}.
|
|
752
|
+
*
|
|
753
|
+
* @returns {void}
|
|
754
|
+
*/
|
|
755
|
+
noMinutes() {
|
|
756
|
+
this.hideMinutes();
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Hides the seconds field and its adjacent divider.
|
|
761
|
+
* Sets the `no-seconds` attribute.
|
|
762
|
+
*
|
|
763
|
+
* @returns {void}
|
|
764
|
+
*/
|
|
765
|
+
hideSeconds() {
|
|
766
|
+
this.setAttribute('no-seconds', '');
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
/**
|
|
770
|
+
* Shows the seconds field and its adjacent divider.
|
|
771
|
+
* Removes the `no-seconds` attribute.
|
|
772
|
+
*
|
|
773
|
+
* @returns {void}
|
|
774
|
+
*/
|
|
775
|
+
showSeconds() {
|
|
776
|
+
this.removeAttribute('no-seconds');
|
|
777
|
+
}
|
|
641
778
|
|
|
642
|
-
|
|
779
|
+
/**
|
|
780
|
+
* Backward-compatible alias for {@link InputDuration#hideSeconds}.
|
|
781
|
+
*
|
|
782
|
+
* @returns {void}
|
|
783
|
+
*/
|
|
784
|
+
noSeconds() {
|
|
785
|
+
this.hideSeconds();
|
|
786
|
+
}
|
|
643
787
|
|
|
644
|
-
|
|
788
|
+
/**
|
|
789
|
+
* Hides the milliseconds field and its adjacent divider or suffix.
|
|
790
|
+
* Sets the `no-microseconds` attribute.
|
|
791
|
+
*
|
|
792
|
+
* @returns {void}
|
|
793
|
+
*/
|
|
794
|
+
hideMicroSeconds() {
|
|
795
|
+
this.setAttribute('no-microseconds', '');
|
|
796
|
+
}
|
|
645
797
|
|
|
798
|
+
/**
|
|
799
|
+
* Shows the milliseconds field and its adjacent divider or suffix.
|
|
800
|
+
* Removes the `no-microseconds` attribute.
|
|
801
|
+
*
|
|
802
|
+
* @returns {void}
|
|
803
|
+
*/
|
|
804
|
+
showMicroSeconds() {
|
|
805
|
+
this.removeAttribute('no-microseconds');
|
|
806
|
+
}
|
|
646
807
|
|
|
647
|
-
|
|
808
|
+
/**
|
|
809
|
+
* Backward-compatible alias for {@link InputDuration#hideMicroSeconds}.
|
|
810
|
+
*
|
|
811
|
+
* @returns {void}
|
|
812
|
+
*/
|
|
813
|
+
noMicroSeconds() {
|
|
814
|
+
this.hideMicroSeconds();
|
|
815
|
+
}
|
|
648
816
|
|
|
649
|
-
|
|
817
|
+
/**
|
|
818
|
+
* Replaces the hours/minutes separator.
|
|
819
|
+
* Also available through the `hours-divider` attribute.
|
|
820
|
+
*
|
|
821
|
+
* @param {string} text - Divider text to display.
|
|
822
|
+
* @returns {void}
|
|
823
|
+
*/
|
|
824
|
+
setHoursDivider(text) {
|
|
825
|
+
this.setAttribute('hours-divider', text);
|
|
826
|
+
}
|
|
650
827
|
|
|
828
|
+
/**
|
|
829
|
+
* Replaces the minutes/seconds separator.
|
|
830
|
+
* Also available through the `minutes-divider` attribute.
|
|
831
|
+
*
|
|
832
|
+
* @param {string} text - Divider text to display.
|
|
833
|
+
* @returns {void}
|
|
834
|
+
*/
|
|
835
|
+
setMinutesDivider(text) {
|
|
836
|
+
this.setAttribute('minutes-divider', text);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
/**
|
|
840
|
+
* Replaces the seconds/milliseconds separator.
|
|
841
|
+
* Also available through the `seconds-divider` attribute.
|
|
842
|
+
*
|
|
843
|
+
* @param {string} text - Divider text to display.
|
|
844
|
+
* @returns {void}
|
|
845
|
+
*/
|
|
846
|
+
setSecondsDivider(text) {
|
|
847
|
+
this.setAttribute('seconds-divider', text);
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
/**
|
|
851
|
+
* Sets a suffix to display after milliseconds.
|
|
852
|
+
* Also available through the `microseconds-divider` attribute.
|
|
853
|
+
*
|
|
854
|
+
* @param {string} text - Suffix text to display.
|
|
855
|
+
* @returns {void}
|
|
856
|
+
*/
|
|
857
|
+
setMicroSecondsDivider(text) {
|
|
858
|
+
this.setAttribute('microseconds-divider', text);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* Synchronizes field and divider visibility with the `no-*` attributes.
|
|
863
|
+
*
|
|
864
|
+
* @returns {void}
|
|
865
|
+
*/
|
|
866
|
+
updateVisibleFields() {
|
|
867
|
+
const hiddenFields = {
|
|
868
|
+
'no-hours': '.sH',
|
|
869
|
+
'no-minutes': '.sM',
|
|
870
|
+
'no-seconds': '.sS',
|
|
871
|
+
'no-microseconds': '.sMS'
|
|
872
|
+
};
|
|
873
|
+
const hiddenDividers = {
|
|
874
|
+
'.bds-h': ['no-hours', 'no-minutes'],
|
|
875
|
+
'.bds-m': ['no-seconds'],
|
|
876
|
+
'.bds-s': ['no-microseconds'],
|
|
877
|
+
'.bds-ms': ['no-microseconds']
|
|
878
|
+
};
|
|
879
|
+
|
|
880
|
+
for (const [attribute, selector] of Object.entries(hiddenFields)) {
|
|
881
|
+
const field = this.myElement.querySelector(selector);
|
|
882
|
+
field.style.display = this.hasAttribute(attribute) ? 'none' : '';
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
for (const [selector, attributes] of Object.entries(hiddenDividers)) {
|
|
886
|
+
const divider = this.myElement.querySelector(selector);
|
|
887
|
+
const shouldHide = attributes.some(attribute => this.hasAttribute(attribute));
|
|
888
|
+
divider.style.display = shouldHide ? 'none' : '';
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
/**
|
|
893
|
+
* Synchronizes divider text with the corresponding divider attributes.
|
|
894
|
+
*
|
|
895
|
+
* @returns {void}
|
|
896
|
+
*/
|
|
897
|
+
updateDividers() {
|
|
898
|
+
const dividers = {
|
|
899
|
+
'hours-divider': ['.bds-h', ':'],
|
|
900
|
+
'minutes-divider': ['.bds-m', ':'],
|
|
901
|
+
'seconds-divider': ['.bds-s', '.'],
|
|
902
|
+
'microseconds-divider': ['.bds-ms', '']
|
|
903
|
+
};
|
|
904
|
+
|
|
905
|
+
for (const [attribute, [selector, defaultText]] of Object.entries(dividers)) {
|
|
906
|
+
const divider = this.myElement.querySelector(selector);
|
|
907
|
+
const text = this.getAttribute(attribute) ?? defaultText;
|
|
908
|
+
divider.textContent = text;
|
|
909
|
+
if (selector === '.bds-ms') {
|
|
910
|
+
divider.style.display = text && !this.hasAttribute('no-microseconds') ? '' : 'none';
|
|
911
|
+
}
|
|
912
|
+
}
|
|
651
913
|
}
|
|
652
914
|
}
|
|
653
915
|
// end class
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "input-duration",
|
|
3
|
-
"version": "3.1
|
|
3
|
+
"version": "3.2.1",
|
|
4
4
|
"author": "Stephan Luis <stephan@learnsense.org>",
|
|
5
5
|
"description": "A JavaScript web component for entering durations up to 99 hours in a fixed HH:mm:ss.SSS format, with millisecond precision for countdown timers and elapsed time.",
|
|
6
6
|
"browser": "./index.js",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"type": "git",
|
|
18
18
|
"url": "git+https://github.com/StephanLuis/input-duration.git"
|
|
19
19
|
},
|
|
20
|
-
"license": "
|
|
20
|
+
"license": "MIT",
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"jsdom": "^26.1.0"
|
|
23
23
|
},
|