html subtitles refactored

This commit is contained in:
NikolaBorislavovHristov 2019-02-18 17:27:07 +02:00
parent e8a5e86ab5
commit 78b7cd7f16
2 changed files with 49 additions and 42 deletions

View file

@ -1,16 +1,16 @@
var EventEmitter = require('events');
var subtitleUtils = require('./utils/subtitles');
var HTMLSubtitles = function(containerElement) {
function HTMLSubtitles(containerElement) {
if (!(containerElement instanceof HTMLElement)) {
throw new Error('Instance of HTMLElement required as a first argument');
}
var self = this;
var events = new EventEmitter();
var destroyed = false;
var events = new EventEmitter();
var tracks = Object.freeze([]);
var cues = Object.freeze({});
var cuesByTime = null;
var selectedTrackId = null;
var delay = 0;
var stylesElement = document.createElement('style');
@ -51,10 +51,10 @@ var HTMLSubtitles = function(containerElement) {
return Object.freeze(tracks.slice());
case 'selectedTrackId':
return selectedTrackId;
case 'delay':
return delay;
case 'size':
return parseFloat(stylesElement.sheet.cssRules[subtitleStylesIndex].style.fontSize);
case 'delay':
return delay;
case 'darkBackground':
return subtitlesElement.classList.contains('dark-background');
default:
@ -63,7 +63,7 @@ var HTMLSubtitles = function(containerElement) {
case 'setProp':
switch (arguments[1]) {
case 'selectedTrackId':
cues = Object.freeze({});
cuesByTime = null;
selectedTrackId = null;
delay = 0;
for (var i = 0; i < tracks.length; i++) {
@ -82,7 +82,7 @@ var HTMLSubtitles = function(containerElement) {
})
.then(function(text) {
if (typeof text === 'string' && selectedTrackId === track.id) {
cues = subtitleUtils.parse(text);
cuesByTime = subtitleUtils.parse(text);
events.emit('load', Object.freeze({
track: track
}));
@ -98,16 +98,16 @@ var HTMLSubtitles = function(containerElement) {
}
}
return;
case 'delay':
if (!isNaN(arguments[2])) {
delay = parseFloat(arguments[2]);
}
return;
case 'size':
if (!isNaN(arguments[2])) {
stylesElement.sheet.cssRules[subtitleStylesIndex].style.fontSize = parseFloat(arguments[2]) + 'pt';
}
return;
case 'delay':
if (!isNaN(arguments[2])) {
delay = parseFloat(arguments[2]);
}
return;
case 'darkBackground':
if (arguments[2]) {
subtitlesElement.classList.add('dark-background');
@ -149,7 +149,7 @@ var HTMLSubtitles = function(containerElement) {
return;
case 'clearTracks':
tracks = Object.freeze([]);
cues = Object.freeze({});
cuesByTime = null;
selectedTrackId = null;
delay = 0;
return;
@ -158,14 +158,14 @@ var HTMLSubtitles = function(containerElement) {
subtitlesElement.removeChild(subtitlesElement.lastChild);
}
if (isNaN(arguments[2]) || !Array.isArray(cues.times)) {
if (isNaN(arguments[2]) || cuesByTime === null) {
return;
}
var time = arguments[2] + delay;
var cuesForTime = subtitleUtils.cuesForTime(cues, time);
var cuesForTime = subtitleUtils.cuesForTime(cuesByTime, time);
for (var i = 0; i < cuesForTime.length; i++) {
var cueNode = subtitleUtils.render(cuesForTime[i]);
var cueNode = subtitleUtils.render(cuesForTime[i].text);
cueNode.classList.add('cue');
subtitlesElement.append(cueNode, document.createElement('br'));
}

View file

@ -26,60 +26,67 @@ function binarySearchUpperBound(array, value) {
function parse(text) {
var nativeVTTCue = VTTCue;
global.VTTCue = VTTJS.VTTCue;
var cues = [];
var cuesForTime = {};
var parser = new VTTJS.WebVTT.Parser(window, VTTJS.WebVTT.StringDecoder());
global.VTTCue = nativeVTTCue;
var cues = [];
var cuesByTime = {};
parser.oncue = function(c) {
var cue = {
var cue = Object.freeze({
startTime: (c.startTime * 1000) | 0,
endTime: (c.endTime * 1000) | 0,
text: c.text
};
});
cues.push(cue);
cuesForTime[cue.startTime] = cuesForTime[cue.startTime] || [];
cuesForTime[cue.endTime] = cuesForTime[cue.endTime] || [];
cuesByTime[cue.startTime] = cuesByTime[cue.startTime] || [];
cuesByTime[cue.endTime] = cuesByTime[cue.endTime] || [];
};
parser.parse(text);
parser.flush();
cuesForTime.times = Object.keys(cuesForTime)
cuesByTime.times = Object.keys(cuesByTime)
.map(function(time) {
return parseInt(time);
})
.sort(function(t1, t2) {
return t1 - t2;
});
Object.freeze(cues);
Object.freeze(cuesByTime);
Object.freeze(cuesByTime.times);
for (var i = 0; i < cues.length; i++) {
cuesForTime[cues[i].startTime].push(cues[i]);
var startTimeIndex = binarySearchUpperBound(cuesForTime.times, cues[i].startTime);
for (var j = startTimeIndex + 1; j < cuesForTime.times.length; j++) {
if (cues[i].endTime <= cuesForTime.times[j]) {
cuesByTime[cues[i].startTime].push(cues[i]);
var startTimeIndex = binarySearchUpperBound(cuesByTime.times, cues[i].startTime);
for (var j = startTimeIndex + 1; j < cuesByTime.times.length; j++) {
if (cues[i].endTime <= cuesByTime.times[j]) {
break;
}
cuesForTime[cuesForTime.times[j]].push(cues[i]);
cuesByTime[cuesByTime.times[j]].push(cues[i]);
}
}
for (var i = 0; i < cuesForTime.times.length; i++) {
cuesForTime[cuesForTime.times[i]].sort(function(c1, c2) {
for (var i = 0; i < cuesByTime.times.length; i++) {
cuesByTime[cuesByTime.times[i]].sort(function(c1, c2) {
return c1.startTime - c2.startTime ||
c1.endTime - c2.endTime;
});
Object.freeze(cuesByTime[cuesByTime.times[i]]);
}
global.VTTCue = nativeVTTCue;
return Object.freeze(cuesForTime);
return cuesByTime;
}
function cuesForTime(cues, time) {
var index = binarySearchUpperBound(cues.times, time);
return index !== -1 ? cues[cues.times[index]] : [];
function cuesForTime(cuesByTime, time) {
var index = binarySearchUpperBound(cuesByTime.times, time);
return index !== -1 ? cuesByTime[cuesByTime.times[index]] : Object.freeze([]);
}
function render(cue) {
return VTTJS.WebVTT.convertCueToDOMTree(window, cue.text);
function render(text) {
return VTTJS.WebVTT.convertCueToDOMTree(window, text);
}
module.exports = {
parse,
cuesForTime,
render
};
module.exports = Object.freeze({
parse: parse,
cuesForTime: cuesForTime,
render: render
});