@checksub_team/peaks_timeline
Version:
JavaScript UI component for displaying audio waveforms
394 lines (356 loc) • 11.3 kB
JavaScript
/**
* @file
*
* Defines the {@link Segment} class.
*
* @module segment
*/
define([
'./utils'
], function(Utils) {
'use strict';
function validateSegment(peaks, options, context) {
var shouldNotifyUpdate = false;
if (!Utils.isValidTime(options.startTime)) {
throw new TypeError('peaks.segments.' + context + ': startTime should be a valid number');
}
if (!Utils.isValidTime(options.endTime)) {
options.endTime = options.startTime;
shouldNotifyUpdate = true;
}
options.startTime = Utils.roundTime(options.startTime);
options.endTime = Utils.roundTime(options.endTime);
if (options.startTime < 0) {
options.startTime = 0;
shouldNotifyUpdate = true;
}
if (options.endTime < 0) {
options.endTime = 0;
shouldNotifyUpdate = true;
}
else if (options.endTime - options.startTime < peaks.options.minSegmentSize) {
options.endTime = options.startTime + peaks.options.minSegmentSize;
shouldNotifyUpdate = true;
}
options.startTime = Utils.roundTime(options.startTime);
options.endTime = Utils.roundTime(options.endTime);
if (options.opacity < 0 || options.opacity > 1) {
throw new RangeError('peaks.segments.' + context + ': opacity should be between 0 and 1');
}
if (Utils.isNullOrUndefined(options.labelText)) {
options.labelText = '';
}
else if (!Utils.isString(options.labelText)) {
throw new TypeError('peaks.segments.' + context + ': labelText must be a string');
}
if (!Utils.isInteger(options.line)) {
throw new TypeError('peaks.segments.' + context + ': line must be an integer');
}
if (Utils.isNullOrUndefined(options.editable)) {
options.editable = true;
}
else if (!Utils.isBoolean(options.editable)) {
throw new TypeError('peaks.segments.' + context + ': editable must be a boolean');
}
if (Utils.isNullOrUndefined(options.hoverColor)) {
options.hoverColor = Utils.shadeColor(options.color, 20);
}
else if (!Utils.isValidColor(options.hoverColor)) {
throw new TypeError('peaks.segments.' + context + ': hoverColor must be a boolean');
}
if (Utils.isNullOrUndefined(options.warningColor)) {
options.warningColor = '#E48023';
}
else if (!Utils.isValidColor(options.warningColor)) {
throw new TypeError('peaks.segments.' + context + ': warningColor must be a boolean');
}
return shouldNotifyUpdate;
}
/**
* A segment is a region of time, with associated label and color.
*
* @class
* @alias Segment
*
* @param {Peaks} peaks A reference to the Peaks instance.
* @param {String} id A unique identifier for the segment.
* @param {Number} startTime Segment start time, in seconds.
* @param {Number} endTime Segment end time, in seconds.
* @param {String} labelText Segment label text.
* @param {String} color Segment waveform color.
* @param {Number} opacity Segment waveform opacity.
* @param {Boolean} editable If <code>true</code> the segment start and
* end times can be adjusted via the user interface.
* @param {Boolean} allowDeletion If <code>true</code> the segment can be
* deleted using the delete key.
* @param {Number} line The id of the line to add the segment to.
* @param {Array<String>} indicators Array containing the colors
* of all indicators.
*/
function Segment(peaks, id, startTime, endTime, duration, labelText,
color, textColor, handleTextColor, hoverColor, warningColor, opacity,
borderColor, borderWidth, borderRadius, editable, allowDeletion, line,
indicators) {
var opts = {
startTime: startTime,
endTime: endTime,
duration: duration,
labelText: labelText,
color: color,
textColor: textColor,
handleTextColor: handleTextColor,
hoverColor: hoverColor,
warningColor: warningColor,
opacity: opacity,
borderColor: borderColor,
borderWidth: borderWidth,
borderRadius: borderRadius,
editable: editable,
allowDeletion: allowDeletion,
line: line,
indicators: indicators
};
var shouldNotifyUpdate = validateSegment(peaks, opts, 'add()');
this._peaks = peaks;
this._id = id;
this._startTime = opts.startTime;
this._endTime = opts.endTime;
this._duration = opts.duration;
this._labelText = opts.labelText;
this._color = opts.color;
this._hoverColor = opts.hoverColor;
this._textColor = opts.textColor;
this._handleTextColor = opts.handleTextColor;
this._warningColor = opts.warningColor;
this._opacity = opts.opacity;
this._borderColor = opts.borderColor;
this._borderWidth = opts.borderWidth;
this._borderRadius = opts.borderRadius;
this._editable = opts.editable;
this._allowDeletion = opts.allowDeletion;
this._line = opts.line;
this._indicators = opts.indicators;
this._minSize = peaks.options.minSegmentSize;
this._relativeId = 0;
this._selected = false;
if (shouldNotifyUpdate) {
peaks.emit('segments.updated', [this]);
}
}
Object.defineProperties(Segment.prototype, {
id: {
enumerable: true,
get: function() {
return this._id;
}
},
startTime: {
enumerable: true,
get: function() {
return this._startTime;
},
set: function(time) {
this._startTime = Utils.roundTime(time);
}
},
endTime: {
enumerable: true,
get: function() {
return this._endTime;
},
set: function(time) {
this._endTime = Utils.roundTime(time);
}
},
duration: {
enumerable: true,
get: function() {
return this._duration;
},
set: function(duration) {
this._duration = Utils.roundTime(duration);
}
},
labelText: {
enumerable: true,
get: function() {
return this._labelText;
}
},
color: {
enumerable: true,
get: function() {
return this._color;
}
},
hoverColor: {
enumerable: true,
get: function() {
return this._hoverColor;
}
},
textColor: {
enumerable: true,
get: function() {
return this._textColor;
}
},
handleTextColor: {
enumerable: true,
get: function() {
return this._handleTextColor;
}
},
warningColor: {
enumerable: true,
get: function() {
return this._warningColor;
}
},
opacity: {
enumerable: true,
get: function() {
return this._opacity;
}
},
borderColor: {
enumerable: true,
get: function() {
return this._borderColor;
}
},
borderWidth: {
enumerable: true,
get: function() {
return this._borderWidth;
}
},
borderRadius: {
enumerable: true,
get: function() {
return this._borderRadius;
}
},
editable: {
enumerable: true,
get: function() {
return this._editable;
}
},
allowDeletion: {
enumerable: true,
get: function() {
return this._allowDeletion;
}
},
line: {
enumerable: true,
get: function() {
return this._line;
}
},
indicators: {
enumerable: true,
get: function() {
return this._indicators;
}
},
minSize: {
enumerable: true,
get: function() {
return this._minSize;
}
},
relativeId: {
enumerable: true,
get: function() {
return this._relativeId;
},
set: function(newId) {
this._relativeId = newId;
}
},
selected: {
enumerable: true,
get: function() {
return this._selected;
},
set: function(selected) {
this._selected = selected;
}
}
});
Segment.prototype.update = function(options) {
var opts = {
startTime: this.startTime,
endTime: this.endTime,
duration: this.duration,
labelText: this.labelText,
color: this.color,
textColor: this.textColor,
handleTextColor: this.handleTextColor,
hoverColor: this.hoverColor,
warningColor: this.warningColor,
opacity: this.opacity,
borderColor: this.borderColor,
borderWidth: this.borderWidth,
borderRadius: this.borderRadius,
editable: this.editable,
allowDeletion: this.allowDeletion,
line: this.line,
indicators: this.indicators
};
Utils.extend(opts, options);
validateSegment(this._peaks, opts, 'update()');
this._startTime = opts.startTime;
this._endTime = opts.endTime;
this._duration = opts.duration;
this._labelText = opts.labelText;
this._color = opts.color;
this._textColor = opts.textColor;
this._handleTextColor = opts.handleTextColor;
this._hoverColor = opts.hoverColor;
this._warningColor = opts.warningColor;
this._opacity = opts.opacity;
this._borderColor = opts.borderColor;
this._borderWidth = opts.borderWidth;
this._borderRadius = opts.borderRadius;
this._editable = opts.editable;
this._allowDeletion = opts.allowDeletion;
this._line = opts.line;
this._indicators = opts.indicators;
this._peaks.emit('segment.updated', this);
};
Segment.prototype.setSelected = function(selected) {
this._selected = selected;
this._peaks.emit('segment.selected', this);
};
/**
* Returns <code>true</code> if the segment overlaps a given time region.
*
* @param {Number} startTime The start of the time region, in seconds.
* @param {Number} endTime The end of the time region, in seconds.
* @returns {Boolean}
*
* @see http://wiki.c2.com/?TestIfDateRangesOverlap
*/
Segment.prototype.isVisible = function(startTime, endTime) {
return this.startTime < endTime && startTime < this.endTime;
};
/**
* Update the indicators of this segment.
*
* @param {Array<String>} newIndicators The new indicators.
*/
Segment.prototype.setIndicators = function(newIndicators) {
this._indicators = newIndicators;
this._peaks.emit('segment.setIndicators', this);
};
/**
* Returns <code>true</code> if a warning should be shown
*/
Segment.prototype.shouldShowWarning = function() {
return this.duration > Utils.roundTime(this.endTime - this.startTime);
};
return Segment;
});