wavesurfer.js 6.5.0 → 7.0.0-alpha.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.
Files changed (132) hide show
  1. package/.eslintrc.json +24 -0
  2. package/.prettierrc +8 -0
  3. package/README.md +26 -117
  4. package/dist/base-plugin.d.ts +10 -0
  5. package/dist/base-plugin.js +13 -0
  6. package/dist/decoder.d.ts +10 -0
  7. package/dist/decoder.js +43 -0
  8. package/dist/event-emitter.d.ts +11 -0
  9. package/dist/event-emitter.js +21 -0
  10. package/dist/fetcher.d.ts +4 -0
  11. package/dist/fetcher.js +17 -0
  12. package/dist/index.d.ts +92 -0
  13. package/dist/index.js +166 -0
  14. package/dist/player-webaudio.d.ts +8 -0
  15. package/dist/player-webaudio.js +31 -0
  16. package/dist/player.d.ts +16 -0
  17. package/dist/player.js +40 -0
  18. package/dist/plugins/regions.d.ts +48 -0
  19. package/dist/plugins/regions.js +183 -0
  20. package/dist/renderer.d.ts +34 -0
  21. package/dist/renderer.js +193 -0
  22. package/dist/timer.d.ts +10 -0
  23. package/dist/timer.js +17 -0
  24. package/examples/audio.ogg +0 -0
  25. package/examples/bars.js +19 -0
  26. package/examples/basic.js +8 -0
  27. package/examples/gradient.js +28 -0
  28. package/examples/regions.js +63 -0
  29. package/examples/video.js +19 -0
  30. package/examples/webaudio.js +14 -0
  31. package/package.json +19 -99
  32. package/src/base-plugin.ts +20 -0
  33. package/src/decoder.ts +41 -0
  34. package/src/event-emitter.ts +35 -0
  35. package/src/fetcher.ts +7 -0
  36. package/src/index.ts +252 -0
  37. package/src/player-webaudio.ts +34 -0
  38. package/src/player.ts +50 -0
  39. package/src/plugins/regions.ts +240 -0
  40. package/src/renderer.ts +250 -0
  41. package/src/timer.ts +27 -0
  42. package/tsconfig.json +105 -0
  43. package/tutorial/index.html +47 -0
  44. package/tutorial/src/editor.js +70 -0
  45. package/tutorial/src/init.js +66 -0
  46. package/tutorial/src/url.js +25 -0
  47. package/tutorial/style.css +211 -0
  48. package/yarn-error.log +1049 -0
  49. package/LICENSE +0 -29
  50. package/dist/plugin/wavesurfer.cursor.js +0 -418
  51. package/dist/plugin/wavesurfer.cursor.js.map +0 -1
  52. package/dist/plugin/wavesurfer.cursor.min.js +0 -7
  53. package/dist/plugin/wavesurfer.cursor.min.js.map +0 -1
  54. package/dist/plugin/wavesurfer.elan.js +0 -381
  55. package/dist/plugin/wavesurfer.elan.js.map +0 -1
  56. package/dist/plugin/wavesurfer.elan.min.js +0 -7
  57. package/dist/plugin/wavesurfer.elan.min.js.map +0 -1
  58. package/dist/plugin/wavesurfer.markers.js +0 -520
  59. package/dist/plugin/wavesurfer.markers.js.map +0 -1
  60. package/dist/plugin/wavesurfer.markers.min.js +0 -7
  61. package/dist/plugin/wavesurfer.markers.min.js.map +0 -1
  62. package/dist/plugin/wavesurfer.mediasession.js +0 -181
  63. package/dist/plugin/wavesurfer.mediasession.js.map +0 -1
  64. package/dist/plugin/wavesurfer.mediasession.min.js +0 -7
  65. package/dist/plugin/wavesurfer.mediasession.min.js.map +0 -1
  66. package/dist/plugin/wavesurfer.microphone.js +0 -466
  67. package/dist/plugin/wavesurfer.microphone.js.map +0 -1
  68. package/dist/plugin/wavesurfer.microphone.min.js +0 -7
  69. package/dist/plugin/wavesurfer.microphone.min.js.map +0 -1
  70. package/dist/plugin/wavesurfer.minimap.js +0 -440
  71. package/dist/plugin/wavesurfer.minimap.js.map +0 -1
  72. package/dist/plugin/wavesurfer.minimap.min.js +0 -7
  73. package/dist/plugin/wavesurfer.minimap.min.js.map +0 -1
  74. package/dist/plugin/wavesurfer.playhead.js +0 -300
  75. package/dist/plugin/wavesurfer.playhead.js.map +0 -1
  76. package/dist/plugin/wavesurfer.playhead.min.js +0 -7
  77. package/dist/plugin/wavesurfer.playhead.min.js.map +0 -1
  78. package/dist/plugin/wavesurfer.regions.js +0 -1342
  79. package/dist/plugin/wavesurfer.regions.js.map +0 -1
  80. package/dist/plugin/wavesurfer.regions.min.js +0 -7
  81. package/dist/plugin/wavesurfer.regions.min.js.map +0 -1
  82. package/dist/plugin/wavesurfer.spectrogram.js +0 -736
  83. package/dist/plugin/wavesurfer.spectrogram.js.map +0 -1
  84. package/dist/plugin/wavesurfer.spectrogram.min.js +0 -7
  85. package/dist/plugin/wavesurfer.spectrogram.min.js.map +0 -1
  86. package/dist/plugin/wavesurfer.timeline.js +0 -649
  87. package/dist/plugin/wavesurfer.timeline.js.map +0 -1
  88. package/dist/plugin/wavesurfer.timeline.min.js +0 -7
  89. package/dist/plugin/wavesurfer.timeline.min.js.map +0 -1
  90. package/dist/wavesurfer-html-init.js +0 -381
  91. package/dist/wavesurfer-html-init.js.map +0 -1
  92. package/dist/wavesurfer-html-init.min.js +0 -7
  93. package/dist/wavesurfer-html-init.min.js.map +0 -1
  94. package/dist/wavesurfer.js +0 -6145
  95. package/dist/wavesurfer.js.map +0 -1
  96. package/dist/wavesurfer.min.js +0 -7
  97. package/dist/wavesurfer.min.js.map +0 -1
  98. package/src/drawer.canvasentry.js +0 -427
  99. package/src/drawer.js +0 -413
  100. package/src/drawer.multicanvas.js +0 -617
  101. package/src/html-init.js +0 -241
  102. package/src/mediaelement-webaudio.js +0 -77
  103. package/src/mediaelement.js +0 -443
  104. package/src/peakcache.js +0 -127
  105. package/src/plugin/cursor/index.js +0 -350
  106. package/src/plugin/elan/index.js +0 -307
  107. package/src/plugin/markers/index.js +0 -436
  108. package/src/plugin/mediasession/index.js +0 -94
  109. package/src/plugin/microphone/index.js +0 -415
  110. package/src/plugin/minimap/index.js +0 -403
  111. package/src/plugin/playhead/index.js +0 -226
  112. package/src/plugin/regions/index.js +0 -478
  113. package/src/plugin/regions/region.js +0 -883
  114. package/src/plugin/spectrogram/fft.js +0 -222
  115. package/src/plugin/spectrogram/index.js +0 -522
  116. package/src/plugin/timeline/index.js +0 -600
  117. package/src/util/absMax.js +0 -16
  118. package/src/util/clamp.js +0 -11
  119. package/src/util/fetch.js +0 -222
  120. package/src/util/frame.js +0 -13
  121. package/src/util/get-id.js +0 -22
  122. package/src/util/index.js +0 -14
  123. package/src/util/max.js +0 -16
  124. package/src/util/min.js +0 -16
  125. package/src/util/observer.js +0 -144
  126. package/src/util/orientation.js +0 -98
  127. package/src/util/prevent-click.js +0 -19
  128. package/src/util/request-animation-frame.js +0 -15
  129. package/src/util/silence-mode.js +0 -42
  130. package/src/util/style.js +0 -16
  131. package/src/wavesurfer.js +0 -1797
  132. package/src/webaudio.js +0 -779
@@ -1,883 +0,0 @@
1
- /**
2
- * @since 4.0.0
3
- *
4
- * (Single) Region plugin class
5
- *
6
- * Must be turned into an observer before instantiating. This is done in
7
- * `RegionsPlugin` (main plugin class).
8
- *
9
- * @extends {Observer}
10
- */
11
- export class Region {
12
- constructor(params, regionsUtils, ws) {
13
- this.wavesurfer = ws;
14
- this.wrapper = ws.drawer.wrapper;
15
- this.util = ws.util;
16
- this.style = this.util.style;
17
- this.regionsUtil = regionsUtils;
18
- this.vertical = ws.drawer.params.vertical;
19
-
20
- this.id = params.id == null ? ws.util.getId() : params.id;
21
- this.start = Number(params.start) || 0;
22
- this.end =
23
- params.end == null
24
- ? // small marker-like region
25
- this.start +
26
- (4 / this.wrapper.scrollWidth) * this.wavesurfer.getDuration()
27
- : Number(params.end);
28
- this.resize =
29
- params.resize === undefined ? true : Boolean(params.resize);
30
- this.drag = params.drag === undefined ? true : Boolean(params.drag);
31
- this.contentEditable = Boolean(params.contentEditable);
32
- this.removeButton = Boolean(params.removeButton);
33
- // reflect resize and drag state of region for region-updated listener
34
- this.isResizing = false;
35
- this.isDragging = false;
36
- this.loop = Boolean(params.loop);
37
- this.color = params.color || 'rgba(0, 0, 0, 0.1)';
38
- // The left and right handleStyle properties can be set to 'none' for
39
- // no styling or can be assigned an object containing CSS properties.
40
- this.handleStyle = params.handleStyle || {
41
- left: {},
42
- right: {}
43
- };
44
- this.handleLeftEl = null;
45
- this.handleRightEl = null;
46
- this.data = params.data || {};
47
- this.attributes = params.attributes || {};
48
- this.showTooltip = params.showTooltip ?? true;
49
-
50
- this.maxLength = params.maxLength;
51
- // It assumes the minLength parameter value, or the regionsMinLength parameter value, if the first one not provided
52
- this.minLength = params.minLength;
53
- this._onRedraw = () => this.updateRender();
54
-
55
- this.scroll = params.scroll !== false && ws.params.scrollParent;
56
- this.scrollSpeed = params.scrollSpeed || 1;
57
- this.scrollThreshold = params.scrollThreshold || 10;
58
- // Determines whether the context menu is prevented from being opened.
59
- this.preventContextMenu =
60
- params.preventContextMenu === undefined
61
- ? false
62
- : Boolean(params.preventContextMenu);
63
-
64
- // select channel ID to set region
65
- let channelIdx =
66
- params.channelIdx == null ? -1 : parseInt(params.channelIdx);
67
- this.channelIdx = channelIdx;
68
- this.regionHeight = '100%';
69
- this.marginTop = '0px';
70
-
71
- if (channelIdx !== -1) {
72
- let channelCount =
73
- this.wavesurfer.backend.buffer != null
74
- ? this.wavesurfer.backend.buffer.numberOfChannels
75
- : -1;
76
- if (channelCount >= 0 && channelIdx < channelCount) {
77
- this.regionHeight = Math.floor((1 / channelCount) * 100) + '%';
78
- this.marginTop =
79
- this.wavesurfer.getHeight() * channelIdx + 'px';
80
- }
81
- }
82
-
83
- this.formatTimeCallback = params.formatTimeCallback;
84
- this.edgeScrollWidth = params.edgeScrollWidth;
85
- this.bindInOut();
86
- this.render();
87
- this.wavesurfer.on('zoom', this._onRedraw);
88
- this.wavesurfer.on('redraw', this._onRedraw);
89
- this.wavesurfer.fireEvent('region-created', this);
90
- }
91
-
92
- /* Update region params. */
93
- update(params, eventParams) {
94
- if (params.start != null) {
95
- this.start = Number(params.start);
96
- }
97
- if (params.end != null) {
98
- this.end = Number(params.end);
99
- }
100
- if (params.loop != null) {
101
- this.loop = Boolean(params.loop);
102
- }
103
- if (params.color != null) {
104
- this.color = params.color;
105
- }
106
- if (params.handleStyle != null) {
107
- this.handleStyle = params.handleStyle;
108
- }
109
- if (params.data != null) {
110
- this.data = params.data;
111
- }
112
- if (params.resize != null) {
113
- this.resize = Boolean(params.resize);
114
- this.updateHandlesResize(this.resize);
115
- }
116
- if (params.drag != null) {
117
- this.drag = Boolean(params.drag);
118
- }
119
- if (params.maxLength != null) {
120
- this.maxLength = Number(params.maxLength);
121
- }
122
- if (params.minLength != null) {
123
- this.minLength = Number(params.minLength);
124
- }
125
- if (params.attributes != null) {
126
- this.attributes = params.attributes;
127
- }
128
-
129
- this.updateRender();
130
- this.fireEvent('update');
131
- this.wavesurfer.fireEvent('region-updated', this, eventParams);
132
- }
133
-
134
- /* Remove a single region. */
135
- remove() {
136
- if (this.element) {
137
- this.wrapper.removeChild(this.element.domElement);
138
- this.element = null;
139
- this.fireEvent('remove');
140
- this.wavesurfer.un('zoom', this._onRedraw);
141
- this.wavesurfer.un('redraw', this._onRedraw);
142
- this.wavesurfer.fireEvent('region-removed', this);
143
- }
144
- }
145
-
146
- /**
147
- * Play the audio region.
148
- * @param {number} start Optional offset to start playing at
149
- */
150
- play(start) {
151
- const s = start || this.start;
152
- this.wavesurfer.play(s, this.end);
153
- this.fireEvent('play');
154
- this.wavesurfer.fireEvent('region-play', this);
155
- }
156
-
157
- /**
158
- * Play the audio region in a loop.
159
- * @param {number} start Optional offset to start playing at
160
- * */
161
- playLoop(start) {
162
- this.loop = true;
163
- this.play(start);
164
- }
165
-
166
- /**
167
- * Set looping on/off.
168
- * @param {boolean} loop True if should play in loop
169
- */
170
- setLoop(loop) {
171
- this.loop = loop;
172
- }
173
-
174
- /* Render a region as a DOM element. */
175
- render() {
176
- this.element = this.util.withOrientation(
177
- this.wrapper.appendChild(document.createElement('region')),
178
- this.vertical
179
- );
180
-
181
- this.element.className = 'wavesurfer-region';
182
- if (this.showTooltip) {
183
- this.element.title = this.formatTime(this.start, this.end);
184
- }
185
- this.element.setAttribute('data-id', this.id);
186
-
187
- for (const attrname in this.attributes) {
188
- this.element.setAttribute(
189
- 'data-region-' + attrname,
190
- this.attributes[attrname]
191
- );
192
- }
193
-
194
- this.style(this.element, {
195
- position: 'absolute',
196
- zIndex: 3,
197
- height: this.regionHeight,
198
- top: this.marginTop
199
- });
200
-
201
- /* Button Remove Region */
202
- if (this.removeButton){
203
- const removeButtonEl = document.createElement('div');
204
- removeButtonEl.className = 'remove-region-button';
205
- removeButtonEl.innerText = 'x';
206
- this.removeButtonEl = this.element.appendChild(removeButtonEl);
207
- const css = {
208
- zIndex: 4,
209
- position: 'absolute',
210
- bottom: 0,
211
- right: 0,
212
- cursor:'pointer',
213
- marginRight: '3px',
214
- fontSize: '80%',
215
- color: 'grey',
216
- height: '14px'
217
- };
218
- this.style(this.removeButtonEl, css);
219
- }
220
-
221
- /* Edit content */
222
- if (this.contentEditable){
223
- const contentEl = document.createElement('div');
224
- contentEl.className = 'region-content';
225
- contentEl.contentEditable = true;
226
- contentEl.innerText = this.data.text || '';
227
- this.contentEl = this.element.appendChild(contentEl);
228
- const css = {
229
- zIndex: 4,
230
- padding: '2px 5px',
231
- cursor:'text'};
232
- this.style(this.contentEl, css);
233
- }
234
-
235
- /* Resize handles */
236
- if (this.resize) {
237
- this.handleLeftEl = this.util.withOrientation(
238
- this.element.appendChild(document.createElement('handle')),
239
- this.vertical
240
- );
241
- this.handleRightEl = this.util.withOrientation(
242
- this.element.appendChild(document.createElement('handle')),
243
- this.vertical
244
- );
245
-
246
- this.handleLeftEl.className = 'wavesurfer-handle wavesurfer-handle-start';
247
- this.handleRightEl.className = 'wavesurfer-handle wavesurfer-handle-end';
248
-
249
- // Default CSS properties for both handles.
250
- const css = {
251
- cursor: this.vertical ? 'row-resize' : 'col-resize',
252
- position: 'absolute',
253
- top: '0px',
254
- width: '2px',
255
- height: '100%',
256
- backgroundColor: 'rgba(0, 0, 0, 1)'
257
- };
258
-
259
- // Merge CSS properties per handle.
260
- const handleLeftCss =
261
- this.handleStyle.left !== 'none'
262
- ? Object.assign(
263
- { left: '0px' },
264
- css,
265
- this.handleStyle.left
266
- )
267
- : null;
268
- const handleRightCss =
269
- this.handleStyle.right !== 'none'
270
- ? Object.assign(
271
- { right: '0px' },
272
- css,
273
- this.handleStyle.right
274
- )
275
- : null;
276
-
277
- if (handleLeftCss) {
278
- this.style(this.handleLeftEl, handleLeftCss);
279
- }
280
-
281
- if (handleRightCss) {
282
- this.style(this.handleRightEl, handleRightCss);
283
- }
284
- }
285
-
286
- this.updateRender();
287
- this.bindEvents();
288
- }
289
-
290
- formatTime(start, end) {
291
- if (this.formatTimeCallback) {
292
- return this.formatTimeCallback(start, end);
293
- }
294
- return (start == end ? [start] : [start, end])
295
- .map((time) =>
296
- [
297
- Math.floor((time % 3600) / 60), // minutes
298
- ('00' + Math.floor(time % 60)).slice(-2) // seconds
299
- ].join(':')
300
- )
301
- .join('-');
302
- }
303
-
304
- getWidth() {
305
- return this.wavesurfer.drawer.width / this.wavesurfer.params.pixelRatio;
306
- }
307
-
308
- /* Update element's position, width, color. */
309
- updateRender() {
310
- // duration varies during loading process, so don't overwrite important data
311
- const dur = this.wavesurfer.getDuration();
312
- const width = this.getWidth();
313
-
314
- let startLimited = this.start;
315
- let endLimited = this.end;
316
- if (startLimited < 0) {
317
- startLimited = 0;
318
- endLimited = endLimited - startLimited;
319
- }
320
- if (endLimited > dur) {
321
- endLimited = dur;
322
- startLimited = dur - (endLimited - startLimited);
323
- }
324
-
325
- if (this.minLength != null) {
326
- endLimited = Math.max(startLimited + this.minLength, endLimited);
327
- }
328
-
329
- if (this.maxLength != null) {
330
- endLimited = Math.min(startLimited + this.maxLength, endLimited);
331
- }
332
-
333
- if (this.element != null) {
334
- // Calculate the left and width values of the region such that
335
- // no gaps appear between regions.
336
- const left = Math.round((startLimited / dur) * width);
337
- const regionWidth = Math.round((endLimited / dur) * width) - left;
338
-
339
- this.style(this.element, {
340
- left: left + 'px',
341
- width: regionWidth + 'px',
342
- backgroundColor: this.color,
343
- cursor: this.drag ? 'move' : 'default'
344
- });
345
-
346
- for (const attrname in this.attributes) {
347
- this.element.setAttribute(
348
- 'data-region-' + attrname,
349
- this.attributes[attrname]
350
- );
351
- }
352
-
353
- if (this.showTooltip) {
354
- this.element.title = this.formatTime(this.start, this.end);
355
- }
356
- }
357
- }
358
-
359
- /* Bind audio events. */
360
- bindInOut() {
361
- this.firedIn = false;
362
- this.firedOut = false;
363
-
364
- const onProcess = (time) => {
365
- let start = Math.round(this.start * 10) / 10;
366
- let end = Math.round(this.end * 10) / 10;
367
- time = Math.round(time * 10) / 10;
368
-
369
- if (
370
- !this.firedOut &&
371
- this.firedIn &&
372
- (start > time || end <= time)
373
- ) {
374
- this.firedOut = true;
375
- this.firedIn = false;
376
- this.fireEvent('out');
377
- this.wavesurfer.fireEvent('region-out', this);
378
- }
379
- if (!this.firedIn && start <= time && end > time) {
380
- this.firedIn = true;
381
- this.firedOut = false;
382
- this.fireEvent('in');
383
- this.wavesurfer.fireEvent('region-in', this);
384
- }
385
- };
386
-
387
- this.wavesurfer.backend.on('audioprocess', onProcess);
388
-
389
- this.on('remove', () => {
390
- this.wavesurfer.backend.un('audioprocess', onProcess);
391
- });
392
-
393
- /* Loop playback. */
394
- this.on('out', () => {
395
- if (this.loop) {
396
- const realTime = this.wavesurfer.getCurrentTime();
397
- if (realTime >= this.start && realTime <= this.end) {
398
- this.wavesurfer.play(this.start);
399
- }
400
- }
401
- });
402
- }
403
-
404
- /* Bind DOM events. */
405
- bindEvents() {
406
- const preventContextMenu = this.preventContextMenu;
407
-
408
- this.element.addEventListener('mouseenter', (e) => {
409
- this.fireEvent('mouseenter', e);
410
- this.wavesurfer.fireEvent('region-mouseenter', this, e);
411
- });
412
-
413
- this.element.addEventListener('mouseleave', (e) => {
414
- this.fireEvent('mouseleave', e);
415
- this.wavesurfer.fireEvent('region-mouseleave', this, e);
416
- });
417
-
418
- this.element.addEventListener('click', (e) => {
419
- e.preventDefault();
420
- this.fireEvent('click', e);
421
- this.wavesurfer.fireEvent('region-click', this, e);
422
- });
423
-
424
- this.element.addEventListener('dblclick', (e) => {
425
- e.stopPropagation();
426
- e.preventDefault();
427
- this.fireEvent('dblclick', e);
428
- this.wavesurfer.fireEvent('region-dblclick', this, e);
429
- });
430
-
431
- this.element.addEventListener('contextmenu', (e) => {
432
- if (preventContextMenu) {
433
- e.preventDefault();
434
- }
435
- this.fireEvent('contextmenu', e);
436
- this.wavesurfer.fireEvent('region-contextmenu', this, e);
437
- });
438
-
439
- /* Drag or resize on mousemove. */
440
- if (this.drag || this.resize) {
441
- this.bindDragEvents();
442
- }
443
-
444
- /* Edit content */
445
- if (this.contentEditable){
446
- this.contentEl.addEventListener('blur', this.onContentBlur.bind(this));
447
- this.contentEl.addEventListener('click', this.onContentClick.bind(this));
448
- }
449
- /* Remove button */
450
- if (this.removeButton){
451
- this.removeButtonEl.addEventListener('click', this.onRemove.bind(this));
452
- }
453
-
454
- this.on('remove', () => {
455
- this.contentEl.removeEventListener('blur', this.onContentBlur.bind(this));
456
- this.contentEl.removeEventListener('click', this.onContentClick.bind(this));
457
- this.removeButtonEl.removeEventListener('click', this.onRemove.bind(this));
458
- });
459
- }
460
-
461
- bindDragEvents() {
462
- const container = this.wavesurfer.drawer.container;
463
- const scrollSpeed = this.scrollSpeed;
464
- const scrollThreshold = this.scrollThreshold;
465
- let startTime;
466
- let touchId;
467
- let drag;
468
- let maxScroll;
469
- let resize;
470
- let updated = false;
471
- let scrollDirection;
472
- let wrapperRect;
473
- let regionLeftHalfTime;
474
- let regionRightHalfTime;
475
-
476
- // Scroll when the user is dragging within the threshold
477
- const edgeScroll = (event) => {
478
- let orientedEvent = this.util.withOrientation(event, this.vertical);
479
- const duration = this.wavesurfer.getDuration();
480
- if (!scrollDirection || (!drag && !resize)) {
481
- return;
482
- }
483
-
484
- const x = orientedEvent.clientX;
485
- let distanceBetweenCursorAndWrapperEdge = 0;
486
- let regionHalfTimeWidth = 0;
487
- let adjustment = 0;
488
-
489
- // Get the currently selected time according to the mouse position
490
- let time = this.regionsUtil.getRegionSnapToGridValue(
491
- this.wavesurfer.drawer.handleEvent(event) * duration
492
- );
493
-
494
- if (drag) {
495
- // Considering the point of contact with the region while edgescrolling
496
- if (scrollDirection === -1) {
497
- regionHalfTimeWidth = regionLeftHalfTime * this.wavesurfer.params.minPxPerSec;
498
- distanceBetweenCursorAndWrapperEdge = x - wrapperRect.left;
499
- } else {
500
- regionHalfTimeWidth = regionRightHalfTime * this.wavesurfer.params.minPxPerSec;
501
- distanceBetweenCursorAndWrapperEdge = wrapperRect.right - x;
502
- }
503
- } else {
504
- // Considering minLength while edgescroll
505
- let minLength = this.minLength;
506
- if (!minLength) {
507
- minLength = 0;
508
- }
509
-
510
- if (resize === 'start') {
511
- if (time > this.end - minLength) {
512
- time = this.end - minLength;
513
- adjustment = scrollSpeed * scrollDirection;
514
- }
515
-
516
- if (time < 0) {
517
- time = 0;
518
- }
519
- } else if (resize === 'end') {
520
- if (time < this.start + minLength) {
521
- time = this.start + minLength;
522
- adjustment = scrollSpeed * scrollDirection;
523
- }
524
-
525
- if (time > duration) {
526
- time = duration;
527
- }
528
- }
529
- }
530
-
531
- // Don't edgescroll if region has reached min or max limit
532
- const wrapperScrollLeft = this.wrapper.scrollLeft;
533
-
534
- if (scrollDirection === -1) {
535
- if (Math.round(wrapperScrollLeft) === 0) {
536
- return;
537
- }
538
-
539
- if (Math.round(wrapperScrollLeft - regionHalfTimeWidth + distanceBetweenCursorAndWrapperEdge) <= 0) {
540
- return;
541
- }
542
- } else {
543
- if (Math.round(wrapperScrollLeft) === maxScroll) {
544
- return;
545
- }
546
-
547
- if (Math.round(wrapperScrollLeft + regionHalfTimeWidth - distanceBetweenCursorAndWrapperEdge) >= maxScroll) {
548
- return;
549
- }
550
- }
551
-
552
- // Update scroll position
553
- let scrollLeft = wrapperScrollLeft - adjustment + scrollSpeed * scrollDirection;
554
-
555
- if (scrollDirection === -1) {
556
- const calculatedLeft = Math.max(0 + regionHalfTimeWidth - distanceBetweenCursorAndWrapperEdge, scrollLeft);
557
- this.wrapper.scrollLeft = scrollLeft = calculatedLeft;
558
- } else {
559
- const calculatedRight = Math.min(maxScroll - regionHalfTimeWidth + distanceBetweenCursorAndWrapperEdge, scrollLeft);
560
- this.wrapper.scrollLeft = scrollLeft = calculatedRight;
561
- }
562
-
563
- const delta = time - startTime;
564
- startTime = time;
565
-
566
- // Continue dragging or resizing
567
- drag ? this.onDrag(delta) : this.onResize(delta, resize);
568
-
569
- // Repeat
570
- window.requestAnimationFrame(() => {
571
- edgeScroll(event);
572
- });
573
- };
574
-
575
- const onDown = (event) => {
576
- const duration = this.wavesurfer.getDuration();
577
- if (event.touches && event.touches.length > 1) {
578
- return;
579
- }
580
- touchId = event.targetTouches ? event.targetTouches[0].identifier : null;
581
-
582
- // stop the event propagation, if this region is resizable or draggable
583
- // and the event is therefore handled here.
584
- if (this.drag || this.resize) {
585
- event.stopPropagation();
586
- }
587
-
588
- // Store the selected startTime we begun dragging or resizing
589
- startTime = this.regionsUtil.getRegionSnapToGridValue(
590
- this.wavesurfer.drawer.handleEvent(event, true) * duration
591
- );
592
-
593
- // Store the selected point of contact when we begin dragging
594
- regionLeftHalfTime = startTime - this.start;
595
- regionRightHalfTime = this.end - startTime;
596
-
597
- // Store for scroll calculations
598
- maxScroll = this.wrapper.scrollWidth - this.wrapper.clientWidth;
599
-
600
- wrapperRect = this.util.withOrientation(
601
- this.wrapper.getBoundingClientRect(),
602
- this.vertical
603
- );
604
-
605
- this.isResizing = false;
606
- this.isDragging = false;
607
- if (event.target.tagName.toLowerCase() === 'handle') {
608
- this.isResizing = true;
609
- resize = event.target.classList.contains('wavesurfer-handle-start')
610
- ? 'start'
611
- : 'end';
612
- } else {
613
- this.isDragging = true;
614
- drag = true;
615
- resize = false;
616
- }
617
- };
618
- const onUp = (event) => {
619
- if (event.touches && event.touches.length > 1) {
620
- return;
621
- }
622
-
623
- if (drag || resize) {
624
- this.isDragging = false;
625
- this.isResizing = false;
626
- drag = false;
627
- scrollDirection = null;
628
- resize = false;
629
- }
630
-
631
- if (updated) {
632
- updated = false;
633
- this.util.preventClick();
634
- this.fireEvent('update-end', event);
635
- this.wavesurfer.fireEvent('region-update-end', this, event);
636
- }
637
- };
638
- const onMove = (event) => {
639
- const duration = this.wavesurfer.getDuration();
640
- let orientedEvent = this.util.withOrientation(event, this.vertical);
641
- let delta = null;
642
-
643
- if (event.touches && event.touches.length > 1) {
644
- return;
645
- }
646
- if (event.targetTouches && event.targetTouches[0].identifier != touchId) {
647
- return;
648
- }
649
- if (!drag && !resize) {
650
- return;
651
- }
652
-
653
- const oldTime = startTime;
654
- let time = this.regionsUtil.getRegionSnapToGridValue(
655
- this.wavesurfer.drawer.handleEvent(event) * duration
656
- );
657
-
658
- if (drag) {
659
- // To maintain relative cursor start point while dragging
660
- const maxEnd = this.wavesurfer.getDuration();
661
- if (time > maxEnd - regionRightHalfTime) {
662
- time = maxEnd - regionRightHalfTime;
663
- }
664
-
665
- if (time - regionLeftHalfTime < 0) {
666
- time = regionLeftHalfTime;
667
- }
668
- }
669
-
670
- if (resize) {
671
- // To maintain relative cursor start point while resizing
672
- // we have to handle for minLength
673
- let minLength = this.minLength;
674
- if (!minLength) {
675
- minLength = 0;
676
- }
677
-
678
- if (resize === 'start') {
679
- if (time > this.end - minLength) {
680
- time = this.end - minLength;
681
- }
682
-
683
- if (time < 0) {
684
- time = 0;
685
- }
686
- } else if (resize === 'end') {
687
- if (time < this.start + minLength) {
688
- // Calculate the end time based on the min length of the region.
689
- time = this.start + minLength;
690
- delta = time - (this.end + (time - startTime));
691
- }
692
-
693
- if (time > duration) {
694
- time = duration;
695
- }
696
- }
697
- }
698
-
699
- if (!delta) {
700
- delta = time - startTime;
701
- }
702
-
703
- startTime = time;
704
-
705
- // Drag
706
- if (this.drag && drag) {
707
- updated = updated || !!delta;
708
- this.onDrag(delta);
709
- }
710
-
711
- // Resize
712
- if (this.resize && resize) {
713
- updated = updated || !!delta;
714
- this.onResize(delta, resize);
715
- }
716
-
717
- if (
718
- this.scroll && container.clientWidth < this.wrapper.scrollWidth
719
- ) {
720
- // Triggering edgescroll from within edgeScrollWidth
721
- let x = orientedEvent.clientX;
722
-
723
- // Check direction
724
- if (x < wrapperRect.left + this.edgeScrollWidth) {
725
- scrollDirection = -1;
726
- } else if (x > wrapperRect.right - this.edgeScrollWidth) {
727
- scrollDirection = 1;
728
- } else {
729
- scrollDirection = null;
730
- }
731
-
732
- if (scrollDirection) {
733
- edgeScroll(event);
734
- }
735
- }
736
- };
737
-
738
- this.element.addEventListener('mousedown', onDown);
739
- this.element.addEventListener('touchstart', onDown);
740
-
741
- document.body.addEventListener('mousemove', onMove);
742
- document.body.addEventListener('touchmove', onMove, {passive: false});
743
-
744
- document.addEventListener('mouseup', onUp);
745
- document.body.addEventListener('touchend', onUp);
746
-
747
- this.on('remove', () => {
748
- document.removeEventListener('mouseup', onUp);
749
- document.body.removeEventListener('touchend', onUp);
750
- document.body.removeEventListener('mousemove', onMove);
751
- document.body.removeEventListener('touchmove', onMove);
752
- });
753
-
754
- this.wavesurfer.on('destroy', () => {
755
- document.removeEventListener('mouseup', onUp);
756
- document.body.removeEventListener('touchend', onUp);
757
- });
758
- }
759
-
760
- onDrag(delta) {
761
- const maxEnd = this.wavesurfer.getDuration();
762
- if (this.end + delta > maxEnd) {
763
- delta = maxEnd - this.end;
764
- }
765
-
766
- if (this.start + delta < 0) {
767
- delta = this.start * -1;
768
- }
769
-
770
- const eventParams = {
771
- direction: this._getDragDirection(delta),
772
- action: 'drag'
773
- };
774
-
775
- this.update({
776
- start: this.start + delta,
777
- end: this.end + delta
778
- }, eventParams);
779
- }
780
-
781
- /**
782
- * Returns the direction of dragging region based on delta
783
- * Negative delta means region is moving to the left
784
- * Positive - to the right
785
- * For zero delta the direction is not defined
786
- * @param {number} delta Drag offset
787
- * @returns {string|null} Direction 'left', 'right' or null
788
- */
789
- _getDragDirection(delta) {
790
- if (delta < 0) {
791
- return 'left';
792
- }
793
- if (delta > 0) {
794
- return 'right';
795
- }
796
- return null;
797
- }
798
-
799
- /**
800
- * @example
801
- * onResize(-5, 'start') // Moves the start point 5 seconds back
802
- * onResize(0.5, 'end') // Moves the end point 0.5 seconds forward
803
- *
804
- * @param {number} delta How much to add or subtract, given in seconds
805
- * @param {string} direction 'start 'or 'end'
806
- */
807
- onResize(delta, direction) {
808
- const duration = this.wavesurfer.getDuration();
809
- const eventParams = {
810
- action: 'resize',
811
- direction: direction === 'start' ? 'left' : 'right'
812
- };
813
-
814
- if (direction === 'start') {
815
- // Check if changing the start by the given delta would result in the region being smaller than minLength
816
- if (delta > 0 && this.end - (this.start + delta) < this.minLength) {
817
- delta = this.end - this.minLength - this.start;
818
- }
819
-
820
- // Check if changing the start by the given delta would result in the region being larger than maxLength
821
- if (delta < 0 && this.end - (this.start + delta) > this.maxLength) {
822
- delta = this.end - this.start - this.maxLength;
823
- }
824
-
825
- if (delta < 0 && (this.start + delta) < 0) {
826
- delta = this.start * -1;
827
- }
828
-
829
- this.update({
830
- start: Math.min(this.start + delta, this.end),
831
- end: Math.max(this.start + delta, this.end)
832
- }, eventParams);
833
- } else {
834
- // Check if changing the end by the given delta would result in the region being smaller than minLength
835
- if (delta < 0 && this.end + delta - this.start < this.minLength) {
836
- delta = this.start + this.minLength - this.end;
837
- }
838
-
839
- // Check if changing the end by the given delta would result in the region being larger than maxLength
840
- if (delta > 0 && this.end + delta - this.start > this.maxLength) {
841
- delta = this.maxLength - (this.end - this.start);
842
- }
843
-
844
- if (delta > 0 && (this.end + delta) > duration) {
845
- delta = duration - this.end;
846
- }
847
-
848
- this.update({
849
- start: Math.min(this.end + delta, this.start),
850
- end: Math.max(this.end + delta, this.start)
851
- }, eventParams);
852
- }
853
- }
854
-
855
- onContentBlur(event){
856
- const {text: oldText} = this.data || {};
857
- const text = event.target.innerText;
858
- const data = {...this.data, text };
859
- const eventParams = {action: 'contentEdited', oldText, text};
860
- this.update({data}, eventParams);
861
- }
862
-
863
- onContentClick(event){
864
- event.stopPropagation();
865
- }
866
-
867
- onRemove(event){
868
- event.stopPropagation();
869
- this.remove();
870
- }
871
-
872
- updateHandlesResize(resize) {
873
- let cursorStyle;
874
- if (resize) {
875
- cursorStyle = this.vertical ? 'row-resize' : 'col-resize';
876
- } else {
877
- cursorStyle = 'auto';
878
- }
879
-
880
- this.handleLeftEl && this.style(this.handleLeftEl, { cursor: cursorStyle });
881
- this.handleRightEl && this.style(this.handleRightEl, { cursor: cursorStyle });
882
- }
883
- }