|
/** |
|
* A component that displays the parts of media that have been played. |
|
* |
|
* **WARNING**: Doesn't work with live streaming content |
|
*/ |
|
class PlayedControl extends videojs.getComponent('Component') { |
|
constructor(player, options) { |
|
super(player, options); |
|
this.timeUpdateHandler = this.timeUpdateHandler.bind(this); |
|
|
|
this.player().on('timeupdate', this.timeUpdateHandler); |
|
} |
|
|
|
/** |
|
* Create PlayedControl DOM Element. |
|
* |
|
* @returns {Element} |
|
*/ |
|
createEl() { |
|
return super.createEl('div', { |
|
className: 'vjs-played-control', |
|
}); |
|
} |
|
|
|
/** |
|
* Dispose PlayedControl component. |
|
* |
|
* @param {Object} options |
|
*/ |
|
dispose(options) { |
|
this.player().off('timeupdate', this.timeUpdateHandler); |
|
super.dispose(options); |
|
} |
|
|
|
/** |
|
* Create or update the range element. |
|
* |
|
* @param {Number} index |
|
* @param {Number} start |
|
* @param {Number} end |
|
* @param {Number} duration |
|
*/ |
|
rangeEl(index, start, end, duration) { |
|
/** @type {Element} */ |
|
let rangeEl = this.$(`.vjs-range-${index}`); |
|
|
|
if (!rangeEl) { |
|
rangeEl = videojs.dom.createEl('div', { |
|
className: `vjs-played-range vjs-range-${index}`, |
|
}); |
|
|
|
this.el().append(rangeEl); |
|
} |
|
|
|
rangeEl.style.left = `${this.rangeElLeft(start, duration)}%`; |
|
rangeEl.style.width = `${this.rangeElWidth(start, end, duration)}%`; |
|
} |
|
|
|
/** |
|
* Defines width of rangeEl element. |
|
* |
|
* @param {Number} start |
|
* @param {Number} end |
|
* @param {Number} duration |
|
* |
|
* @returns {Number} |
|
*/ |
|
rangeElWidth(start, end, duration) { |
|
const percentage = ((end - start) / duration) * 100; |
|
|
|
return Math.round(percentage); |
|
} |
|
|
|
/** |
|
* Defines left position of rangeEl element. |
|
* |
|
* @param {Number} start |
|
* @param {Number} duration |
|
* |
|
* @returns |
|
*/ |
|
rangeElLeft(start, duration) { |
|
const percentage = (start / duration) * 100; |
|
|
|
return Math.round(percentage); |
|
} |
|
|
|
/** |
|
* Information about the current playback session. |
|
* |
|
* @typedef {Object} PlayedInfo |
|
* @property {Array.<Array.<Number>>} ranges |
|
* @property {Number} timePlayed |
|
* @property {Number} percentagePlayed |
|
* |
|
* @returns {PlayedInfo} |
|
*/ |
|
playedInfo() { |
|
const ranges = []; |
|
|
|
for (let i = 0; i != player.played().length; i++) { |
|
ranges.push([player.played().start(i), player.played().end(i)]); |
|
} |
|
|
|
const timePlayed = ranges.reduce( |
|
(accumulator, currentValue) => |
|
currentValue[1] - currentValue[0] + accumulator, |
|
0 |
|
); |
|
|
|
const percentagePlayed = (timePlayed / this.player().duration()) * 100; |
|
|
|
return { |
|
ranges, |
|
timePlayed, |
|
percentagePlayed, |
|
}; |
|
} |
|
|
|
timeUpdateHandler() { |
|
/** @type {TimeRanges} */ |
|
const playedRanges = this.player().played(); |
|
/** @type {Number} */ |
|
const duration = this.player().duration(); |
|
|
|
if (playedRanges.length < this.el().children.length) { |
|
videojs.dom.emptyEl(this.el()); |
|
} |
|
|
|
for (let i = 0; i < playedRanges.length; i++) { |
|
const start = playedRanges.start(i); |
|
const end = playedRanges.end(i); |
|
|
|
this.rangeEl(i, start, end, duration); |
|
} |
|
} |
|
} |
|
|
|
videojs.registerComponent('PlayedControl', PlayedControl); |
|
|
|
export default PlayedControl; |