@vidispine/vdt-videojs 23.1.0 → 23.2.0-pre.2

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.
@@ -1,274 +0,0 @@
1
- /* eslint-disable no-restricted-globals */
2
- /* eslint-disable class-methods-use-this */
3
- /* eslint-disable no-plusplus */
4
- /* eslint-disable no-unused-expressions */
5
-
6
- const timeCodeNodeNames = ['hours', 'minutes', 'seconds', 'frame'];
7
-
8
- export default class TimeCodeDisplay {
9
- // displays and renders smpte timecodes
10
- constructor(props) {
11
- this.props = props;
12
-
13
- this.state = {
14
- selectedNode: null, // avoid updating values in a selected node
15
- };
16
-
17
- const classNames = [
18
- 'vdt-timecode',
19
- 'vjs-time-control', // will apply default videojs style to the whole container, centers things vertically
20
- !this.props.onInput ? 'duration' : '', // if no input capability, assume it's a duration timecode
21
- ];
22
- this.container = document.createElement('div');
23
- this.container.className = classNames.join(' ');
24
-
25
- this.nodeNames = [].concat(timeCodeNodeNames); // used internally
26
- this.nodes = {}; // store sub-element nodes for mapped access here
27
-
28
- this.nodeNames.forEach((nodeName, index) => {
29
- const node = document.createElement('input');
30
- node.className = nodeName;
31
- node.tabIndex = -1; // prevent default Tab behaviour for cycling inputs
32
-
33
- if (this.props.onInput) {
34
- // optional input capabilities
35
- node.maxLength = 2;
36
-
37
- node.onfocus = (e) => {
38
- this.handleInputFocus(e, nodeName);
39
- };
40
-
41
- node.onblur = (e) => {
42
- this.handleInputBlur(e, nodeName);
43
- };
44
-
45
- node.onmouseup = (e) => {
46
- e.preventDefault();
47
- e.currentTarget.select();
48
- };
49
-
50
- node.onkeydown = (e) => {
51
- this.handleTimeCodeInput(e, nodeName);
52
- };
53
-
54
- node.onkeyup = (e) => {
55
- this.handleTimeCodeInputOnKeyUp(e, nodeName);
56
- };
57
- } else {
58
- node.readOnly = true; // display-only timecode
59
- }
60
-
61
- this.nodes[nodeName] = node;
62
-
63
- const colon = document.createElement('span');
64
- colon.innerHTML = ':';
65
-
66
- this.container.appendChild(node);
67
- index !== this.nodeNames.length - 1 && this.container.appendChild(colon);
68
- });
69
-
70
- if (this.props.target) {
71
- if (this.props.appendAfter) {
72
- // so it's possible to append after volume control, for example
73
- this.props.target.parentNode.insertBefore(this.container, this.props.target.nextSibling);
74
- } else {
75
- this.props.target.appendChild(this.container);
76
- }
77
-
78
- // start at 0 values for now, if player will "remember" playback position, revisit this
79
- this.reset();
80
- } else {
81
- // eslint-disable-next-line no-console
82
- console.error(`Unable to instantiate a new ${this.constructor.name} without target DOM node`); // no joy
83
- }
84
- }
85
-
86
- update(valuesObj) {
87
- // Object.keys and array.forEach are too slow, classic for is faster
88
- const startCount = this.nodeNames.length - 1;
89
- let i;
90
- for (i = startCount; i > -1; i--) {
91
- // updates follow frame -> seconds -> minutes -> hours order
92
- const key = this.nodeNames[i];
93
-
94
- if (
95
- typeof valuesObj[key] !== 'undefined' &&
96
- valuesObj[key] !== parseInt(this.nodes[key].value, 10) &&
97
- key !== this.state.selectedNode
98
- ) {
99
- // re-render node if value is defineed and is different from current value
100
- const str = valuesObj[key].toString();
101
- this.nodes[key].value = this.toDigitPairStr(str);
102
- }
103
- }
104
- }
105
-
106
- reset() {
107
- this.update({
108
- hours: 0,
109
- minutes: 0,
110
- seconds: 0,
111
- frame: 0,
112
- });
113
- }
114
-
115
- handleInputFocus(e, nodeName) {
116
- this.state.selectedNode = nodeName; // prevent updates on this input
117
- this.nodes[nodeName].select();
118
- this.props.onInputFocus && this.props.onInputFocus(nodeName);
119
- }
120
-
121
- handleInputBlur(e, nodeName) {
122
- this.state.selectedNode = null; // allow updates on this input
123
- this.props.onInputBlur && this.props.onInputBlur(nodeName);
124
- }
125
-
126
- sanitize(input) {
127
- const output = input.replace(/[^0-9]/g, '');
128
- return output;
129
- }
130
-
131
- toDigitPairStr(strValue) {
132
- return strValue.length < 2 ? `0${strValue}` : strValue;
133
- }
134
-
135
- handleTimeCodeInput(e, nodeName) {
136
- const nodeIndex = this.nodeNames.indexOf(nodeName);
137
-
138
- switch (e.code) {
139
- case 'Enter': // do work before submitting input
140
- this.checkAndNormalizeAllInputs();
141
-
142
- this.props.onInput &&
143
- this.props.onInput(e, nodeName, {
144
- hours: this.hours,
145
- minutes: this.minutes,
146
- seconds: this.seconds,
147
- frame: this.frame,
148
- });
149
-
150
- this[nodeName] = e.currentTarget.value;
151
- e.currentTarget.blur(); // done
152
- break;
153
- case 'Tab': // custom tab behaviour
154
- e.preventDefault();
155
-
156
- // tab trough inputs in a loop fashion
157
- if (!e.shiftKey) {
158
- if (nodeIndex + 1 <= this.nodeNames.length - 1) {
159
- this.nodes[this.nodeNames[nodeIndex + 1]].focus(); // focus next
160
- } else {
161
- this.nodes[this.nodeNames[0]].focus(); // focus first
162
- }
163
- } else if (nodeIndex - 1 >= 0) {
164
- this.nodes[this.nodeNames[nodeIndex - 1]].focus(); // focus previous
165
- } else {
166
- this.nodes[this.nodeNames[this.nodeNames.length - 1]].focus(); // focus last
167
- }
168
- break;
169
- default:
170
- break;
171
- }
172
- }
173
-
174
- handleTimeCodeInputOnKeyUp(e, nodeName) {
175
- /*
176
- cycle to next input if this one is done being populated,
177
- has to happen onkeyup, since the timecode is already populated
178
- with valid values most of the time, keydown would always trigger
179
- false positive length check.
180
-
181
- Also check if the input is a number (!isNaN),
182
- to prevent double-triggering Tab key or other logic
183
- */
184
- if (this.nodes[nodeName].value.length === 2 && !isNaN(e.key)) {
185
- const nodeIndex = this.nodeNames.indexOf(nodeName); // determine position in timecode
186
-
187
- if (nodeIndex + 1 <= this.nodeNames.length - 1) {
188
- // check bounds
189
- this.nodes[this.nodeNames[nodeIndex + 1]].focus(); // focus next
190
- }
191
- }
192
- }
193
-
194
- checkAndNormalizeAllInputs() {
195
- this.nodeNames.forEach((nodeName) => {
196
- if (this.nodes[nodeName].value.length < 1) {
197
- // somebody left the input blank
198
- this.nodes[nodeName].value = '00';
199
- }
200
-
201
- // make sure displayed timecode stays consistent after input and before time-based updates
202
- this.nodes[nodeName].value = this.toDigitPairStr(this.sanitize(this.nodes[nodeName].value));
203
- });
204
- }
205
-
206
- // setters and getters
207
-
208
- set frame(val) {
209
- this.nodes.frame.value = this.toDigitPairStr(val);
210
- }
211
-
212
- get frame() {
213
- return parseInt(this.nodes.frame.value, 10);
214
- }
215
-
216
- set seconds(val) {
217
- this.nodes.seconds.value = this.toDigitPairStr(val);
218
- }
219
-
220
- get seconds() {
221
- return parseInt(this.nodes.seconds.value, 10);
222
- }
223
-
224
- set minutes(val) {
225
- this.nodes.minutes.value = this.toDigitPairStr(val);
226
- }
227
-
228
- get minutes() {
229
- return parseInt(this.nodes.minutes.value, 10);
230
- }
231
-
232
- set hours(val) {
233
- this.nodes.hours.value = this.toDigitPairStr(val);
234
- }
235
-
236
- get hours() {
237
- return parseInt(this.nodes.hours.value, 10);
238
- }
239
-
240
- getFormatted(key) {
241
- return this.toDigitPairStr(this[key].toString());
242
- }
243
-
244
- get smpte() {
245
- return {
246
- hours: this.hours,
247
- minutes: this.minutes,
248
- seconds: this.seconds,
249
- frame: this.frame,
250
- };
251
- }
252
-
253
- set smpte(o) {
254
- this.update(o);
255
- }
256
-
257
- get smpteString() {
258
- return `${this.getFormatted('hours')}:${this.getFormatted('minutes')}:${this.getFormatted(
259
- 'seconds',
260
- )}:${this.getFormatted('frame')}`;
261
- }
262
-
263
- set external(bool) {
264
- if (bool) {
265
- this.container.classList.add('external');
266
- } else {
267
- this.container.classList.remove('external');
268
- }
269
- }
270
-
271
- get external() {
272
- return this.container.classList.contains('external');
273
- }
274
- }
package/src/videoTime.js DELETED
@@ -1,66 +0,0 @@
1
- // TODO - move this to @vidispine/vdt-js when finalized and use as dependency
2
-
3
- class VideoTime {
4
- constructor(props) {
5
- if (props.frameRate === undefined) {
6
- delete this;
7
- throw new Error('No "frameRate" option provided, refer to docs.');
8
- } else {
9
- this.props = props;
10
- }
11
- }
12
-
13
- secondsToFramesFromStart(seconds) {
14
- let frame = seconds * this.props.frameRate;
15
- frame = Math.round(frame);
16
- return frame; // we're on this frame, could be for example 23.45
17
- }
18
-
19
- currentTimeToFramesFromStart(currentTime) {
20
- return this.secondsToFramesFromStart(currentTime);
21
- }
22
-
23
- secondsToFrame(seconds) {
24
- let frame = this.secondsToFramesFromStart(seconds) % this.props.frameRate;
25
- frame = Math.round(frame);
26
- return frame;
27
- }
28
-
29
- currentFrame(currentTime) {
30
- return Math.round(this.secondsToFrame(currentTime));
31
- }
32
-
33
- frameToCurrentTimeFromStart(frame) {
34
- return frame / this.props.frameRate; // in seconds from start
35
- }
36
-
37
- smpteToCurrentTimeFromStart(values) {
38
- return (
39
- values.hours * 3600 +
40
- values.minutes * 60 +
41
- values.seconds +
42
- values.frame / this.props.frameRate
43
- );
44
- }
45
-
46
- secondsFromStartToSMPTE(secondsFromStart) {
47
- let secondsFS = secondsFromStart;
48
- const hours = Math.floor(secondsFS / 3600);
49
- const minutesWithoutHours = secondsFS / 60 - 60 * hours;
50
- // eslint-disable-next-line no-param-reassign
51
- secondsFS %= 3600;
52
-
53
- const minutes = Math.floor(minutesWithoutHours);
54
- const seconds = Math.floor(secondsFS % 60);
55
- const frame = this.secondsToFrame(secondsFS);
56
-
57
- return {
58
- hours,
59
- minutes,
60
- seconds,
61
- frame,
62
- };
63
- }
64
- }
65
-
66
- export default VideoTime;