@checksub_team/peaks_timeline 1.4.17

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/src/source.js ADDED
@@ -0,0 +1,688 @@
1
+ /**
2
+ * @file
3
+ *
4
+ * Defines the {@link source} class.
5
+ *
6
+ * @module source
7
+ */
8
+
9
+ define([
10
+ './utils'
11
+ ], function(Utils) {
12
+ 'use strict';
13
+
14
+ function validateSource(peaks, options, context) {
15
+ if (!Utils.isValidTime(options.startTime)) {
16
+ throw new TypeError('peaks.sources.' + context + ': startTime should be a valid number');
17
+ }
18
+
19
+ if (!Utils.isValidTime(options.endTime)) {
20
+ throw new TypeError('peaks.sources.' + context + ': endTime should be a valid number');
21
+ }
22
+
23
+ if (!Utils.isValidTime(options.duration) || options.duration <= 0) {
24
+ options.duration = 0;
25
+ }
26
+ else if (options.duration < peaks.options.minSourceSize) {
27
+ options.duration = peaks.options.minSourceSize;
28
+ }
29
+
30
+ options.duration = Utils.roundTime(options.duration);
31
+
32
+ if (options.startTime < 0) {
33
+ throw new RangeError('peaks.sources.' + context + ': startTime should be positive');
34
+ }
35
+
36
+ if (options.endTime < 0) {
37
+ throw new RangeError('peaks.sources.' + context + ': endTime should be positive');
38
+ }
39
+
40
+ if (options.endTime <= options.startTime) {
41
+ throw new RangeError(
42
+ 'peaks.sources.' + context + ': endTime should be greater than startTime'
43
+ );
44
+ }
45
+
46
+ if (options.endTime - options.startTime < peaks.options.minSourceSize) {
47
+ options.endTime = options.startTime + peaks.options.minSourceSize;
48
+ }
49
+
50
+ if (!Utils.isValidTime(options.mediaStartTime) || options.mediaStartTime < 0) {
51
+ options.mediaStartTime = 0;
52
+ }
53
+
54
+ if (!Utils.isValidTime(options.mediaEndTime)
55
+ || (options.mediaEndTime < options.mediaStartTime)
56
+ || (options.mediaEndTime - options.mediaStartTime !== options.endTime - options.startTime)) {
57
+ options.mediaEndTime = options.mediaStartTime + (options.endTime - options.startTime);
58
+ }
59
+
60
+ if (options.duration && options.mediaEndTime > options.duration) {
61
+ var timeWidth = options.mediaEndTime - options.mediaStartTime;
62
+
63
+ options.mediaEndTime = options.duration;
64
+ if (options.duration > timeWidth) {
65
+ options.mediaStartTime = options.mediaEndTime - timeWidth;
66
+ options.endTime = options.startTime + timeWidth;
67
+ }
68
+ else {
69
+ options.mediaStartTime = 0;
70
+ options.endTime = options.startTime + options.duration;
71
+ }
72
+ }
73
+
74
+ options.startTime = Utils.roundTime(options.startTime);
75
+ options.endTime = Utils.roundTime(options.endTime);
76
+ options.mediaStartTime = Utils.roundTime(options.mediaStartTime);
77
+ options.mediaEndTime = Utils.roundTime(options.mediaEndTime);
78
+
79
+ if (Utils.isNullOrUndefined(options.title)) {
80
+ options.title = '';
81
+ }
82
+ else if (!Utils.isString(options.title)) {
83
+ throw new TypeError('peaks.sources.' + context + ': title must be a string');
84
+ }
85
+
86
+ if (Utils.isNullOrUndefined(options.url)) {
87
+ options.url = '';
88
+ }
89
+ else if (!Utils.isString(options.url)) {
90
+ throw new TypeError('peaks.sources.' + context + ': url must be a string');
91
+ }
92
+
93
+ if (Utils.isNullOrUndefined(options.previewUrl)) {
94
+ options.previewUrl = '';
95
+ }
96
+ else if (!Utils.isString(options.previewUrl)) {
97
+ throw new TypeError('peaks.sources.' + context + ': previewUrl must be a string');
98
+ }
99
+
100
+ if (Utils.isNullOrUndefined(options.binaryUrl)) {
101
+ options.binaryUrl = '';
102
+ }
103
+ else if (!Utils.isString(options.binaryUrl)) {
104
+ throw new TypeError('peaks.sources.' + context + ': binaryUrl must be a string');
105
+ }
106
+
107
+ if (!Utils.isValidColor(options.color)) {
108
+ throw new TypeError('peaks.sources.' + context + ': color should be a valid CSS color');
109
+ }
110
+
111
+ if (!Utils.isValidColor(options.borderColor)) {
112
+ options.borderColor = options.color;
113
+ }
114
+
115
+ if (Utils.isNullOrUndefined(options.selectedColor)) {
116
+ options.selectedColor = null;
117
+ }
118
+ else if (!Utils.isValidColor(options.selectedColor)) {
119
+ throw new TypeError(
120
+ 'peaks.sources.' + context + ': selectedColor should be a valid CSS color'
121
+ );
122
+ }
123
+
124
+ if (Utils.isNullOrUndefined(options.textColor)) {
125
+ options.textColor = '#000000';
126
+ }
127
+ else if (!Utils.isValidColor(options.textColor)) {
128
+ throw new TypeError('peaks.sources.' + context + ': textColor should be a valid CSS color');
129
+ }
130
+
131
+ if (Utils.isNullOrUndefined(options.borderWidth)) {
132
+ options.borderWidth = 0;
133
+ }
134
+
135
+ if (Utils.isNullOrUndefined(options.wrapped)) {
136
+ options.wrapped = false;
137
+ }
138
+ else if (!Utils.isBoolean(options.wrapped)) {
139
+ throw new TypeError('peaks.sources.' + context + ': wrapped must be a boolean');
140
+ }
141
+
142
+ if (!Utils.isInteger(options.position)) {
143
+ throw new TypeError('peaks.sources.' + context + ': position must be an integer');
144
+ }
145
+
146
+ if (Utils.isNullOrUndefined(options.draggable)) {
147
+ options.draggable = true;
148
+ }
149
+ else if (!Utils.isBoolean(options.draggable)) {
150
+ throw new TypeError('peaks.sources.' + context + ': draggable must be a boolean');
151
+ }
152
+
153
+ if (Utils.isNullOrUndefined(options.resizable)) {
154
+ options.resizable = true;
155
+ }
156
+ else if (!Utils.isBoolean(options.resizable)) {
157
+ throw new TypeError('peaks.sources.' + context + ': resizable must be a boolean');
158
+ }
159
+
160
+ if (Utils.isNullOrUndefined(options.wrapping)) {
161
+ options.wrapping = 'both';
162
+ }
163
+ else if (!Utils.isString(options.wrapping)) {
164
+ throw new TypeError('peaks.sources.' + context + ': wrapping must be a string');
165
+ }
166
+
167
+ if (Utils.isNullOrUndefined(options.previewHeight)) {
168
+ options.previewHeight = 0;
169
+ }
170
+ else if (!Utils.isInteger(options.previewHeight)) {
171
+ throw new TypeError('peaks.sources.' + context + ': previewHeight must be an integer');
172
+ }
173
+
174
+ if (Utils.isNullOrUndefined(options.binaryHeight)) {
175
+ options.binaryHeight = 0;
176
+ }
177
+ else if (!Utils.isInteger(options.binaryHeight)) {
178
+ throw new TypeError('peaks.sources.' + context + ': binaryHeight must be an integer');
179
+ }
180
+
181
+ if (options.previewUrl && !options.previewHeight) {
182
+ if (options.binaryHeight) {
183
+ options.previewHeight = Math.max(peaks.options.lineHeight - options.binaryHeight, 0);
184
+ }
185
+ else {
186
+ options.previewHeight = peaks.options.lineHeight / 2;
187
+ }
188
+ }
189
+
190
+ if (options.binaryUrl && !options.binaryHeight) {
191
+ options.binaryHeight = Math.max(peaks.options.lineHeight - options.previewHeight, 0);
192
+ }
193
+
194
+ if (options.wrapping === 'reduced') {
195
+ options.wrapped = true;
196
+ }
197
+ else if (options.wrapping === 'complete') {
198
+ options.wrapped = false;
199
+ }
200
+ }
201
+
202
+ /**
203
+ * A source is an external media resource, represented on the timeline.
204
+ *
205
+ * @class
206
+ * @alias Source
207
+ *
208
+ * @param {Peaks} peaks A reference to the Peaks instance.
209
+ * @param {String} id A unique identifier for the source.
210
+ * @param {String} title Name of the source.
211
+ * @param {String} url Reference to the media element this source is representing.
212
+ * @param {Number} startTime Source start time, in seconds.
213
+ * @param {Number} endTime Source end time, in seconds.
214
+ * @param {String} color Color of the background.
215
+ * @param {Boolean} wrapped If <code>true</code> the source representation will
216
+ * be reduced to a line, taking less space.
217
+ * @param {Number} position Position of the source on the timeline.
218
+ * Correspond to the index of the line.
219
+ * @param {Boolean} segments If <code>true</code> this source will integrate the segments.
220
+ */
221
+
222
+ function Source(peaks, id, originId, elementId, title, url, previewUrl, binaryUrl, kind,
223
+ duration, startTime, endTime, mediaStartTime, mediaEndTime, color, borderColor,
224
+ selectedColor, textColor, borderWidth, wrapped, position, draggable, resizable, wrapping,
225
+ previewHeight, binaryHeight) {
226
+ var opts = {
227
+ title: title,
228
+ url: url,
229
+ previewUrl: previewUrl,
230
+ binaryUrl: binaryUrl,
231
+ kind: kind,
232
+ duration: duration,
233
+ startTime: startTime,
234
+ endTime: endTime,
235
+ mediaStartTime: mediaStartTime,
236
+ mediaEndTime: mediaEndTime,
237
+ color: color,
238
+ borderColor: borderColor,
239
+ selectedColor: selectedColor,
240
+ textColor: textColor,
241
+ borderWidth: borderWidth,
242
+ wrapped: wrapped,
243
+ position: position,
244
+ draggable: draggable,
245
+ resizable: resizable,
246
+ wrapping: wrapping,
247
+ previewHeight: previewHeight,
248
+ binaryHeight: binaryHeight
249
+ };
250
+
251
+ validateSource(peaks, opts, 'add()');
252
+
253
+ this._peaks = peaks;
254
+ this._id = id;
255
+ this._originId = originId;
256
+ this._elementId = elementId;
257
+ this._title = opts.title;
258
+ this._url = opts.url;
259
+ this._previewUrl = opts.previewUrl;
260
+ this._binaryUrl = opts.binaryUrl;
261
+ this._kind = opts.kind;
262
+ this._duration = opts.duration;
263
+ this._startTime = opts.startTime;
264
+ this._endTime = opts.endTime;
265
+ this._mediaStartTime = opts.mediaStartTime;
266
+ this._mediaEndTime = opts.mediaEndTime;
267
+ this._color = opts.color;
268
+ this._borderColor = opts.borderColor;
269
+ this._selectedColor = opts.selectedColor || Utils.shadeColor(opts.color, 30);
270
+ this._textColor = opts.textColor;
271
+ this._borderWidth = opts.borderWidth;
272
+ this._wrapped = opts.wrapped;
273
+ this._position = opts.position;
274
+ this._draggable = opts.draggable;
275
+ this._resizable = opts.resizable;
276
+ this._wrapping = opts.wrapping;
277
+ this._previewHeight = opts.previewHeight;
278
+ this._binaryHeight = opts.binaryHeight;
279
+ this._minSize = peaks.options.minSourceSize;
280
+ }
281
+
282
+ Object.defineProperties(Source.prototype, {
283
+ id: {
284
+ enumerable: true,
285
+ get: function() {
286
+ return this._id;
287
+ }
288
+ },
289
+ originId: {
290
+ enumerable: true,
291
+ get: function() {
292
+ return this._originId;
293
+ }
294
+ },
295
+ elementId: {
296
+ enumerable: true,
297
+ get: function() {
298
+ return this._elementId;
299
+ }
300
+ },
301
+ title: {
302
+ enumerable: true,
303
+ get: function() {
304
+ return this._title;
305
+ },
306
+
307
+ set: function(title) {
308
+ this._title = title;
309
+ }
310
+ },
311
+ url: {
312
+ enumerable: true,
313
+ get: function() {
314
+ return this._url;
315
+ }
316
+ },
317
+ previewUrl: {
318
+ enumerable: true,
319
+ get: function() {
320
+ return this._previewUrl;
321
+ }
322
+ },
323
+ binaryUrl: {
324
+ enumerable: true,
325
+ get: function() {
326
+ return this._binaryUrl;
327
+ }
328
+ },
329
+ kind: {
330
+ enumerable: true,
331
+ get: function() {
332
+ return this._kind;
333
+ },
334
+
335
+ set: function(kind) {
336
+ this._kind = kind;
337
+ }
338
+ },
339
+ duration: {
340
+ enumerable: true,
341
+ get: function() {
342
+ return this._duration;
343
+ }
344
+ },
345
+ startTime: {
346
+ enumerable: true,
347
+ get: function() {
348
+ return this._startTime;
349
+ }
350
+ },
351
+ endTime: {
352
+ enumerable: true,
353
+ get: function() {
354
+ return this._endTime;
355
+ }
356
+ },
357
+ mediaStartTime: {
358
+ enumerable: true,
359
+ get: function() {
360
+ return this._mediaStartTime;
361
+ },
362
+
363
+ set: function(mediaStartTime) {
364
+ this._mediaStartTime = mediaStartTime;
365
+ }
366
+ },
367
+ mediaEndTime: {
368
+ enumerable: true,
369
+ get: function() {
370
+ return this._mediaEndTime;
371
+ },
372
+
373
+ set: function(mediaEndTime) {
374
+ this._mediaEndTime = mediaEndTime;
375
+ }
376
+ },
377
+ color: {
378
+ enumerable: true,
379
+ get: function() {
380
+ return this._color;
381
+ },
382
+
383
+ set: function(color) {
384
+ this._color = color;
385
+ }
386
+ },
387
+ borderColor: {
388
+ enumerable: true,
389
+ get: function() {
390
+ return this._borderColor;
391
+ },
392
+
393
+ set: function(borderColor) {
394
+ this._borderColor = borderColor;
395
+ }
396
+ },
397
+ selectedColor: {
398
+ enumerable: true,
399
+ get: function() {
400
+ return this._selectedColor;
401
+ },
402
+
403
+ set: function(selectedColor) {
404
+ this._selectedColor = selectedColor;
405
+ }
406
+ },
407
+ textColor: {
408
+ enumerable: true,
409
+ get: function() {
410
+ return this._textColor;
411
+ },
412
+
413
+ set: function(textColor) {
414
+ this._textColor = textColor;
415
+ }
416
+ },
417
+ borderWidth: {
418
+ enumerable: true,
419
+ get: function() {
420
+ return this._borderWidth;
421
+ },
422
+
423
+ set: function(borderWidth) {
424
+ this._borderWidth = borderWidth;
425
+ }
426
+ },
427
+ wrapped: {
428
+ enumerable: true,
429
+ get: function() {
430
+ return this._wrapped;
431
+ },
432
+
433
+ set: function(wrapped) {
434
+ this._wrapped = wrapped;
435
+ }
436
+ },
437
+ position: {
438
+ enumerable: true,
439
+ get: function() {
440
+ return this._position;
441
+ },
442
+
443
+ set: function(position) {
444
+ this._position = position;
445
+ }
446
+ },
447
+ segments: {
448
+ enumerable: true,
449
+ get: function() {
450
+ return this._segments;
451
+ }
452
+ },
453
+ draggable: {
454
+ enumerable: true,
455
+ get: function() {
456
+ return this._draggable;
457
+ }
458
+ },
459
+ resizable: {
460
+ enumerable: true,
461
+ get: function() {
462
+ return this._resizable;
463
+ }
464
+ },
465
+ wrapping: {
466
+ enumerable: true,
467
+ get: function() {
468
+ return this._wrapping;
469
+ },
470
+
471
+ set: function(wrapping) {
472
+ this._wrapping = wrapping;
473
+ }
474
+ },
475
+ previewHeight: {
476
+ enumerable: true,
477
+ get: function() {
478
+ return this._previewHeight;
479
+ },
480
+
481
+ set: function(previewHeight) {
482
+ this._previewHeight = previewHeight;
483
+ }
484
+ },
485
+ binaryHeight: {
486
+ enumerable: true,
487
+ get: function() {
488
+ return this._binaryHeight;
489
+ },
490
+
491
+ set: function(binaryHeight) {
492
+ this._binaryHeight = binaryHeight;
493
+ }
494
+ },
495
+ minSize: {
496
+ enumerable: true,
497
+ get: function() {
498
+ return this._minSize;
499
+ }
500
+ }
501
+ });
502
+
503
+ Source.prototype.updateTimes = function(newStartTime, newEndTime) {
504
+ if (newStartTime !== null) {
505
+ if (this._duration && newEndTime === null) {
506
+ newStartTime = Utils.roundTime(Math.max(this._endTime - this._duration, newStartTime));
507
+ }
508
+ else {
509
+ newStartTime = Utils.roundTime(newStartTime);
510
+ }
511
+ }
512
+
513
+ if (newEndTime !== null) {
514
+ if (this._duration && newStartTime === null) {
515
+ newEndTime = Utils.roundTime(Math.min(this._startTime + this._duration, newEndTime));
516
+ }
517
+ else {
518
+ newEndTime = Utils.roundTime(newEndTime);
519
+ }
520
+ }
521
+
522
+ if ((newStartTime === null && newEndTime !== null)
523
+ || (newStartTime !== null && newEndTime === null)) {
524
+ this._updateMediaRange(this._startTime, newStartTime, this._endTime, newEndTime);
525
+ }
526
+
527
+ if (newStartTime !== null) {
528
+ this._startTime = newStartTime;
529
+ }
530
+ if (newEndTime !== null) {
531
+ this._endTime = newEndTime;
532
+ }
533
+ };
534
+
535
+ Source.prototype._updateMediaRange = function(oldStartTime, newStartTime, oldEndTime,
536
+ newEndTime) {
537
+ var startDiff = 0;
538
+ var endDiff = 0;
539
+ var upperLimit;
540
+
541
+ if (this._duration) {
542
+ upperLimit = this._duration;
543
+ }
544
+ else {
545
+ upperLimit = Number.POSITIVE_INFINITY;
546
+ }
547
+
548
+ if (newStartTime !== null && oldStartTime !== null) {
549
+ startDiff = newStartTime - oldStartTime;
550
+ }
551
+ if (newEndTime !== null && oldEndTime !== null) {
552
+ endDiff = newEndTime - oldEndTime;
553
+ }
554
+
555
+ var newMediaStartTime = this._mediaStartTime;
556
+ var newMediaEndTime = this._mediaEndTime;
557
+
558
+ if (startDiff) {
559
+ if (startDiff < 0) {
560
+ // Try reducing mediaStartTime
561
+ if (newMediaStartTime > 0) {
562
+ var minStartTime = newMediaStartTime + startDiff;
563
+
564
+ newMediaStartTime = Math.max(0, minStartTime);
565
+ if (minStartTime < 0) {
566
+ // Try increasing mediaEndTime
567
+ newMediaEndTime = Math.min(upperLimit, newMediaEndTime - minStartTime);
568
+ }
569
+ }
570
+ else {
571
+ // Try increasing mediaEndTime
572
+ newMediaEndTime = Math.min(upperLimit, newMediaEndTime - startDiff);
573
+ }
574
+ }
575
+ else {
576
+ // Try increasing mediaStartTime
577
+ if (newMediaStartTime < upperLimit) {
578
+ newMediaStartTime = Math.min(upperLimit, newMediaStartTime + startDiff);
579
+ }
580
+ }
581
+ }
582
+
583
+ if (endDiff) {
584
+ if (endDiff > 0) {
585
+ // Try increasing mediaEndTime
586
+ if (newMediaEndTime < upperLimit) {
587
+ var maxEndTime = newMediaEndTime + endDiff;
588
+
589
+ newMediaEndTime = Math.min(upperLimit, maxEndTime);
590
+ if (maxEndTime > upperLimit) {
591
+ // Try reducing mediaStartTime
592
+ newMediaStartTime = Math.max(0, newMediaStartTime - (maxEndTime - upperLimit));
593
+ }
594
+ }
595
+ else {
596
+ // Try reducing mediaStartTime
597
+ newMediaStartTime = Math.max(0, newMediaStartTime - endDiff);
598
+ }
599
+ }
600
+ else {
601
+ if (newEndTime - oldStartTime < upperLimit) {
602
+ if (oldEndTime - oldStartTime > upperLimit) {
603
+ endDiff += (oldEndTime - oldStartTime) - upperLimit;
604
+ }
605
+
606
+ // Try reducing mediaEndTime
607
+ if (newMediaEndTime > 0) {
608
+ newMediaEndTime = Math.max(0, newMediaEndTime + endDiff);
609
+ }
610
+ }
611
+ }
612
+ }
613
+
614
+ this._mediaStartTime = Utils.roundTime(newMediaStartTime);
615
+ this._mediaEndTime = Utils.roundTime(newMediaEndTime);
616
+ };
617
+
618
+ Source.prototype.update = function(options) {
619
+ var opts = {
620
+ title: this.title,
621
+ url: this.url,
622
+ previewUrl: this.previewUrl,
623
+ binaryUrl: this.binaryUrl,
624
+ kind: this.kind,
625
+ duration: this.duration,
626
+ startTime: this.startTime,
627
+ endTime: this.endTime,
628
+ mediaStartTime: this.mediaStartTime,
629
+ mediaEndTime: this.mediaEndTime,
630
+ color: this.color,
631
+ borderColor: this.borderColor,
632
+ selectedColor: this.selectedColor,
633
+ textColor: this.textColor,
634
+ borderWidth: this.borderWidth,
635
+ wrapped: this.wrapped,
636
+ position: this.position,
637
+ draggable: this.draggable,
638
+ resizable: this.resizable,
639
+ wrapping: this.wrapping,
640
+ previewHeight: this.previewHeight,
641
+ binaryHeight: this.binaryHeight
642
+ };
643
+
644
+ Utils.extend(opts, options);
645
+
646
+ validateSource(this._peaks, opts, 'update()');
647
+
648
+ this._title = opts.title;
649
+ this._url = opts.url;
650
+ this._previewUrl = opts.previewUrl;
651
+ this._binaryUrl = opts.binaryUrl;
652
+ this._kind = opts.kind;
653
+ this._duration = opts.duration;
654
+ this._startTime = opts.startTime;
655
+ this._endTime = opts.endTime;
656
+ this._mediaStartTime = opts.mediaStartTime;
657
+ this._mediaEndTime = opts.mediaEndTime;
658
+ this._color = opts.color;
659
+ this._borderColor = opts.borderColor;
660
+ this._selectedColor = opts.selectedColor || Utils.shadeColor(opts.color, 30);
661
+ this._textColor = opts.textColor;
662
+ this._borderWidth = opts.borderWidth;
663
+ this._wrapped = opts.wrapped;
664
+ this._position = opts.position;
665
+ this._draggable = opts.draggable;
666
+ this._resizable = opts.resizable;
667
+ this._wrapping = opts.wrapping;
668
+ this._previewHeight = opts.previewHeight;
669
+ this._binaryHeight = opts.binaryHeight;
670
+
671
+ this._peaks.emit('source.update', this);
672
+ };
673
+
674
+ /**
675
+ * Returns <code>true</code> if the source overlaps a given time region.
676
+ *
677
+ * @param {Number} startTime The start of the time region, in seconds.
678
+ * @param {Number} endTime The end of the time region, in seconds.
679
+ * @returns {Boolean}
680
+ *
681
+ * @see http://wiki.c2.com/?TestIfDateRangesOverlap
682
+ */
683
+ Source.prototype.isVisible = function(startTime, endTime) {
684
+ return this._startTime < endTime && startTime < this._endTime;
685
+ };
686
+
687
+ return Source;
688
+ });