aboutsummaryrefslogtreecommitdiffstats
path: root/youtube/static/js/transcript-table.js
blob: ac81444b2ae1752c54169c883f9ab1f8c6424d02 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
var details_tt, select_tt, table_tt;

function renderCues() {
  var tt = Q("video").textTracks[select_tt.selectedIndex];
  let cuesL = [...tt.cues];

  clearNode(table_tt);
  console.log("render cues..", tt.cues.length);

  var tt_type = cuesL[0].text.startsWith(" \n");
  for (let i=0; i < cuesL.length; i++) {
    let txt, startTime = tt.cues[i].startTime;
    if (tt_type) {
      if (i % 2) continue;
      txt = tt.cues[i].text.split('\n')[1].replace(/<[\d:.]*?><c>(.*?)<\/c>/g, "$1");
    } else {
      txt = tt.cues[i].text;
    }

    let tr, td, a;
    tr = document.createElement("tr");

    td = document.createElement("td")
    a = document.createElement("a");
    a.appendChild(text(toMS(startTime)));
    a.href = "javascript:;";  // TODO: replace this with ?t parameter
    a.addEventListener("click", (e) => {
      Q("video").currentTime = startTime;
    })
    td.appendChild(a);
    tr.appendChild(td);

    td = document.createElement("td")
    td.appendChild(text(txt));
    tr.appendChild(td);

    table_tt.appendChild(tr);;
  };

  var lastActiveRow = null;
  function colorCurRow(e) {
    // console.log("cuechange:", e);
    var idxC = cuesL.findIndex((c) => c == tt.activeCues[0]);
    var idxT = tt_type ? Math.floor(idxC / 2) : idxC;

    if (lastActiveRow) lastActiveRow.style.backgroundColor = "";
    if (idxT < 0) return;
    var row = table_tt.rows[idxT];
    row.style.backgroundColor = "#0cc12e42";
    lastActiveRow = row;
  }
  colorCurRow();
  tt.addEventListener("cuechange", colorCurRow);
}

function loadCues() {
  let tts = Q("video").textTracks;
  let tt = tts[select_tt.selectedIndex];
  let dst_mode = "hidden";
  for (let ttI of tts) {
    if (ttI.mode === "showing") dst_mode = "showing";
    if (ttI !== tt) ttI.mode = "disabled";
  }
  if (tt.mode == "disabled") tt.mode = dst_mode;

  var iC = setInterval(() => {
    if (tt.cues && tt.cues.length) {
      renderCues();
      clearInterval(iC);
    }
  }, 100);
}

window.addEventListener('DOMContentLoaded', function() {
  let tts = Q("video").textTracks;
  if (!tts.length) return;

  details_tt = document.createElement("details");
  details_tt.addEventListener("toggle", () => {
    if (details_tt.open) loadCues();
  });

  var s = document.createElement("summary");
  s.appendChild(text("Transcript"));
  details_tt.appendChild(s);

  var divR = document.createElement("div");
  select_tt = document.createElement("select");
  for (let tt of tts) {
    let option = document.createElement("option");
    option.appendChild(text(tt.label));
    select_tt.appendChild(option);
  }
  select_tt.selectedIndex = getDefaultTranscriptTrackIdx();
  select_tt.addEventListener("change", loadCues);
  divR.appendChild(select_tt);

  table_tt = document.createElement("table");
  table_tt.id = "transcript-table";
  table_tt.appendChild(text("loading.."));
  divR.appendChild(table_tt);

  tts.addEventListener("change", (e) => {
    // console.log(e);
    var idx = getActiveTranscriptTrackIdx();  // sadly not provided by 'e'
    if (tts[idx].mode == "showing") {
      select_tt.selectedIndex = idx;
      loadCues();
    }
    else if (details_tt.open && tts[idx].mode == "disabled") {
      tts[idx].mode = "hidden";  // so we still receive 'oncuechange'
    }
  })

  details_tt.appendChild(divR);
  Q(".side-videos").prepend(details_tt);
});