Auto-format JS files with prettier

Prettier is a tool for formatting JS files.
We add a minimal configuration to suit our purposes, and run it on all our JS files.

The main things this corrects is mixed tab and space indent issues (replacing fully with tabs),
overly long lines, inconsistent quote usage (prefers double-quotes instead), and missing semicolons.
pull/225/head
Mike Lang 3 years ago committed by Mike Lang
parent 6c97bd462e
commit ce73f7b0ea

@ -0,0 +1,11 @@
# Config for auto-formatting of our JS files using prettier
# https://prettier.io/docs/en/configuration.html
# This is NOT a length limit but a hint to the auto-formatter for how long lines should try to be.
printWidth: 100
# Use tabs for indentation, spaces for alignment
useTabs: true
# do {foo: bar} not { foo: bar }. personal preference.
bracketSpacing: false
# prefer "arg => body" over "(arg) => body" when possible
arrowParens: avoid

@ -1,423 +1,515 @@
var desertBusStart = new Date("1970-01-01T00:00:00Z"); var desertBusStart = new Date("1970-01-01T00:00:00Z");
var timeFormat = 'AGO'; var timeFormat = "AGO";
pageSetup = function(isEditor) { pageSetup = function (isEditor) {
//Get values from ThrimShim
//Get values from ThrimShim if (isEditor && /id=/.test(document.location.search)) {
if(isEditor && /id=/.test(document.location.search)) { var rowId = /id=(.*)(?:&|$)/.exec(document.location.search)[1];
var rowId = /id=(.*)(?:&|$)/.exec(document.location.search)[1]; fetch("/thrimshim/" + rowId)
fetch("/thrimshim/"+rowId).then(data => data.json()).then(function (data) { .then(data => data.json())
if (!data) { .then(function (data) {
alert("No video available for stream."); if (!data) {
return; alert("No video available for stream.");
} return;
document.data = data }
desertBusStart = new Date(data.bustime_start); document.data = data;
document.getElementById("VideoTitlePrefix").value = data.title_prefix; desertBusStart = new Date(data.bustime_start);
document.getElementById("VideoTitle").setAttribute("maxlength", data.title_max_length); document.getElementById("VideoTitlePrefix").value = data.title_prefix;
document.getElementById("VideoTitle").setAttribute("maxlength", data.title_max_length);
document.getElementById("StreamName").value = data.video_channel;
document.getElementById("hiddenSubmissionID").value = data.id; document.getElementById("StreamName").value = data.video_channel;
// for editor, switch to bustime since that's the default document.getElementById("hiddenSubmissionID").value = data.id;
timeFormat = 'BUSTIME'; // for editor, switch to bustime since that's the default
// Apply padding - start 1min early, finish 2min late because these times are generally timeFormat = "BUSTIME";
// rounded down to the minute, so if something ends at "00:10" it might actually end // Apply padding - start 1min early, finish 2min late because these times are generally
// at 00:10:59 so we should pad to 00:12:00. // rounded down to the minute, so if something ends at "00:10" it might actually end
var start = (data.event_start) ? new Date(fromTimestamp(data.event_start).getTime() - 60*1000) : null; // at 00:10:59 so we should pad to 00:12:00.
var end = (data.event_end) ? new Date(fromTimestamp(data.event_end).getTime() + 2*60*1000) : null; var start = data.event_start
setTimeRange(start, end); ? new Date(fromTimestamp(data.event_start).getTime() - 60 * 1000)
// title and description both default to row description : null;
document.getElementById("VideoTitle").value = data.video_title ? data.video_title : data.description; var end = data.event_end
document.getElementById("VideoDescription").value = data.video_description ? data.video_description : data.description; ? new Date(fromTimestamp(data.event_end).getTime() + 2 * 60 * 1000)
// tags default to tags from sheet : null;
document.getElementById("VideoTags").value = tags_list_to_string(data.video_tags ? data.video_tags : data.tags); setTimeRange(start, end);
// title and description both default to row description
// If any edit notes, show them document.getElementById("VideoTitle").value = data.video_title
if (data.notes.length > 0) { ? data.video_title
document.getElementById("EditNotes").value = data.notes; : data.description;
document.getElementById("EditNotesPane").style.display = "block"; document.getElementById("VideoDescription").value = data.video_description
} ? data.video_description
: data.description;
// Restore advanced options. If any of these are non-default, automatically expand the advanced options pane. // tags default to tags from sheet
setOptions('uploadLocation', data.upload_locations, data.upload_location); document.getElementById("VideoTags").value = tags_list_to_string(
document.getElementById("AllowHoles").checked = data.allow_holes; data.video_tags ? data.video_tags : data.tags
document.getElementById("uploaderWhitelist").value = (!!data.uploader_whitelist) ? data.uploader_whitelist.join(",") : ""; );
if (
( // If any edit notes, show them
data.upload_locations.length > 0 if (data.notes.length > 0) {
&& data.upload_location != null document.getElementById("EditNotes").value = data.notes;
&& data.upload_location != data.upload_locations[0] document.getElementById("EditNotesPane").style.display = "block";
) }
|| data.allow_holes
|| !!data.uploader_whitelist // Restore advanced options. If any of these are non-default, automatically expand the advanced options pane.
) { setOptions("uploadLocation", data.upload_locations, data.upload_location);
document.getElementById('wubloaderAdvancedInputTable').style.display = "block"; document.getElementById("AllowHoles").checked = data.allow_holes;
} document.getElementById("uploaderWhitelist").value = !!data.uploader_whitelist
? data.uploader_whitelist.join(",")
loadPlaylist(isEditor, data.video_start, data.video_end, data.video_quality); : "";
}); if (
} (data.upload_locations.length > 0 &&
else { data.upload_location != null &&
if (isEditor) { document.getElementById('SubmitButton').disabled = true; } data.upload_location != data.upload_locations[0]) ||
data.allow_holes ||
fetch("/thrimshim/defaults").then(data => data.json()).then(function (data) { !!data.uploader_whitelist
if (!data) { ) {
alert("Editor results call failed, is thrimshim running?"); document.getElementById("wubloaderAdvancedInputTable").style.display = "block";
return; }
}
desertBusStart = new Date(data.bustime_start); loadPlaylist(isEditor, data.video_start, data.video_end, data.video_quality);
document.getElementById("StreamName").value = data.video_channel; });
if (isEditor) { } else {
document.getElementById("VideoTitlePrefix").value = data.title_prefix; if (isEditor) {
document.getElementById("VideoTitle").setAttribute("maxlength", data.title_max_length); document.getElementById("SubmitButton").disabled = true;
setOptions('uploadLocation', data.upload_locations); }
}
fetch("/thrimshim/defaults")
// Default time format changes depending on mode. .then(data => data.json())
// But in both cases the default input value is 10min ago / "", .then(function (data) {
// it's just for editor we convert it before the user sees. if (!data) {
if (isEditor) { alert("Editor results call failed, is thrimshim running?");
toggleTimeInput('BUSTIME'); return;
} }
desertBusStart = new Date(data.bustime_start);
loadPlaylist(isEditor); document.getElementById("StreamName").value = data.video_channel;
}); if (isEditor) {
document.getElementById("VideoTitlePrefix").value = data.title_prefix;
} document.getElementById("VideoTitle").setAttribute("maxlength", data.title_max_length);
setOptions("uploadLocation", data.upload_locations);
}
// Default time format changes depending on mode.
// But in both cases the default input value is 10min ago / "",
// it's just for editor we convert it before the user sees.
if (isEditor) {
toggleTimeInput("BUSTIME");
}
loadPlaylist(isEditor);
});
}
}; };
// Time-formatting functions // Time-formatting functions
parseDuration = function(duration) { parseDuration = function (duration) {
var direction = 1; var direction = 1;
if(duration.startsWith("-")) { if (duration.startsWith("-")) {
duration = duration.slice(1); duration = duration.slice(1);
direction = -1; direction = -1;
} }
var parts = duration.split(':'); var parts = duration.split(":");
return (parseInt(parts[0]) + (parts[1] || "0")/60 + (parts[2] || "0")/3600) * 60 * 60 * direction; return (
} (parseInt(parts[0]) + (parts[1] || "0") / 60 + (parts[2] || "0") / 3600) * 60 * 60 * direction
);
toBustime = function(date) { };
return (date < desertBusStart ? "-":"") + videojs.formatTime(Math.abs((date - desertBusStart)/1000), 600.01).padStart(7, "0:");
toBustime = function (date) {
return (
(date < desertBusStart ? "-" : "") +
videojs.formatTime(Math.abs((date - desertBusStart) / 1000), 600.01).padStart(7, "0:")
);
}; };
fromBustime = function(bustime) { fromBustime = function (bustime) {
return new Date(desertBusStart.getTime() + 1000 * parseDuration(bustime)); return new Date(desertBusStart.getTime() + 1000 * parseDuration(bustime));
}; };
toTimestamp = function(date) { toTimestamp = function (date) {
return date.toISOString().substring(0, 19); return date.toISOString().substring(0, 19);
} };
fromTimestamp = function(ts) { fromTimestamp = function (ts) {
return new Date(ts + "Z"); return new Date(ts + "Z");
} };
toAgo = function(date) { toAgo = function (date) {
now = new Date() now = new Date();
return (date < now ? "":"-") + videojs.formatTime(Math.abs((date - now)/1000), 600.01).padStart(7, "0:"); return (
} (date < now ? "" : "-") +
videojs.formatTime(Math.abs((date - now) / 1000), 600.01).padStart(7, "0:")
);
};
fromAgo = function(ago) { fromAgo = function (ago) {
return new Date(new Date().getTime() - 1000 * parseDuration(ago)); return new Date(new Date().getTime() - 1000 * parseDuration(ago));
} };
// Set the stream start/end range from a pair of Dates using the current format // Set the stream start/end range from a pair of Dates using the current format
// If given null, sets to blank. // If given null, sets to blank.
setTimeRange = function(start, end) { setTimeRange = function (start, end) {
var toFunc = { var toFunc = {
UTC: toTimestamp, UTC: toTimestamp,
BUSTIME: toBustime, BUSTIME: toBustime,
AGO: toAgo, AGO: toAgo,
}[timeFormat]; }[timeFormat];
document.getElementById("StreamStart").value = (start) ? toFunc(start) : ""; document.getElementById("StreamStart").value = start ? toFunc(start) : "";
document.getElementById("StreamEnd").value = (end) ? toFunc(end) : ""; document.getElementById("StreamEnd").value = end ? toFunc(end) : "";
} };
// Get the current start/end range as Dates using the current format // Get the current start/end range as Dates using the current format
// Returns an object containing 'start' and 'end' fields. // Returns an object containing 'start' and 'end' fields.
// If either is empty / invalid, returns null. // If either is empty / invalid, returns null.
getTimeRange = function() { getTimeRange = function () {
var fromFunc = { var fromFunc = {
UTC: fromTimestamp, UTC: fromTimestamp,
BUSTIME: fromBustime, BUSTIME: fromBustime,
AGO: fromAgo, AGO: fromAgo,
}[timeFormat]; }[timeFormat];
var convert = function(value) { var convert = function (value) {
if (!value) { return null; } if (!value) {
var date = fromFunc(value); return null;
return (isNaN(date)) ? null : date; }
}; var date = fromFunc(value);
return { return isNaN(date) ? null : date;
start: convert(document.getElementById("StreamStart").value), };
end: convert(document.getElementById("StreamEnd").value), return {
}; start: convert(document.getElementById("StreamStart").value),
} end: convert(document.getElementById("StreamEnd").value),
};
getTimeRangeAsTimestamp = function() { };
var range = getTimeRange();
return { getTimeRangeAsTimestamp = function () {
// if not null, format as timestamp var range = getTimeRange();
start: range.start && toTimestamp(range.start), return {
end: range.end && toTimestamp(range.end), // if not null, format as timestamp
}; start: range.start && toTimestamp(range.start),
} end: range.end && toTimestamp(range.end),
};
toggleHiddenPane = function(paneID) { };
var pane = document.getElementById(paneID);
pane.style.display = (pane.style.display === "none") ? "block":"none"; toggleHiddenPane = function (paneID) {
} var pane = document.getElementById(paneID);
pane.style.display = pane.style.display === "none" ? "block" : "none";
toggleUltrawide = function() { };
var body = document.getElementsByTagName("Body")[0];
body.classList.contains("ultrawide") ? body.classList.remove("ultrawide"):body.classList.add("ultrawide"); toggleUltrawide = function () {
} var body = document.getElementsByTagName("Body")[0];
body.classList.contains("ultrawide")
toggleTimeInput = function(toggleInput) { ? body.classList.remove("ultrawide")
// Get times using current format, then change format, then write them back : body.classList.add("ultrawide");
var range = getTimeRange(); };
timeFormat = toggleInput;
setTimeRange(range.start, range.end); toggleTimeInput = function (toggleInput) {
} // Get times using current format, then change format, then write them back
var range = getTimeRange();
timeFormat = toggleInput;
setTimeRange(range.start, range.end);
};
// For a given select input element id, add the given list of options. // For a given select input element id, add the given list of options.
// If selected is given, it should be the name of an option to select. // If selected is given, it should be the name of an option to select.
// Otherwise the first one is used. // Otherwise the first one is used.
setOptions = function(element, options, selected) { setOptions = function (element, options, selected) {
if (!selected && options.length > 0) { if (!selected && options.length > 0) {
selected = options[0] selected = options[0];
} }
options.forEach(function(option) { options.forEach(function (option) {
document.getElementById(element).innerHTML += '<option value="'+option+'" '+(option==selected ? 'selected':'')+'>'+option+'</option>'; document.getElementById(element).innerHTML +=
}); '<option value="' +
} option +
'" ' +
buildQuery = function(params) { (option == selected ? "selected" : "") +
return Object.keys(params).filter(key => params[key] !== null).map(key => ">" +
encodeURIComponent(key) + '=' + encodeURIComponent(params[key]) option +
).join('&'); "</option>";
} });
};
loadPlaylist = function(isEditor, startTrim, endTrim, defaultQuality) {
var playlist = "/playlist/" + document.getElementById("StreamName").value + ".m3u8"; buildQuery = function (params) {
return Object.keys(params)
var range = getTimeRangeAsTimestamp(); .filter(key => params[key] !== null)
var queryString = buildQuery(range); .map(key => encodeURIComponent(key) + "=" + encodeURIComponent(params[key]))
.join("&");
};
loadPlaylist = function (isEditor, startTrim, endTrim, defaultQuality) {
var playlist = "/playlist/" + document.getElementById("StreamName").value + ".m3u8";
var range = getTimeRangeAsTimestamp();
var queryString = buildQuery(range);
// Preserve existing edit times // Preserve existing edit times
if (player && player.trimmingControls && player.vhs.playlists.master) { if (player && player.trimmingControls && player.vhs.playlists.master) {
var discontinuities = mapDiscontinuities(); var discontinuities = mapDiscontinuities();
if (!startTrim) { if (!startTrim) {
startTrim = getRealTimeForPlayerTime(discontinuities, player.trimmingControls().options.startTrim); startTrim = getRealTimeForPlayerTime(
if (startTrim) {startTrim = startTrim.replace('Z','');} discontinuities,
player.trimmingControls().options.startTrim
);
if (startTrim) {
startTrim = startTrim.replace("Z", "");
}
} }
if (!endTrim) { if (!endTrim) {
endTrim = getRealTimeForPlayerTime(discontinuities, player.trimmingControls().options.endTrim); endTrim = getRealTimeForPlayerTime(
if (endTrim) {endTrim = endTrim.replace('Z','');} discontinuities,
player.trimmingControls().options.endTrim
);
if (endTrim) {
endTrim = endTrim.replace("Z", "");
}
} }
} }
setupPlayer(isEditor, playlist + '?' + queryString, startTrim, endTrim); setupPlayer(isEditor, playlist + "?" + queryString, startTrim, endTrim);
//Get quality levels for advanced properties / download //Get quality levels for advanced properties / download
document.getElementById('qualityLevel').innerHTML = ""; document.getElementById("qualityLevel").innerHTML = "";
fetch('/files/' + document.getElementById('StreamName').value).then(data => data.json()).then(function (data) { fetch("/files/" + document.getElementById("StreamName").value)
if (!data.length) { .then(data => data.json())
console.log("Could not retrieve quality levels"); .then(function (data) {
return; if (!data.length) {
} console.log("Could not retrieve quality levels");
var qualityLevels = data.sort().reverse(); return;
setOptions('qualityLevel', qualityLevels, defaultQuality); }
if (!!defaultQuality && qualityLevels.length > 0 && defaultQuality != qualityLevels[0]) { var qualityLevels = data.sort().reverse();
document.getElementById('wubloaderAdvancedInputTable').style.display = "block"; setOptions("qualityLevel", qualityLevels, defaultQuality);
} if (!!defaultQuality && qualityLevels.length > 0 && defaultQuality != qualityLevels[0]) {
}); document.getElementById("wubloaderAdvancedInputTable").style.display = "block";
}
});
}; };
thrimbletrimmerSubmit = function(state, override_changes=false) { thrimbletrimmerSubmit = function (state, override_changes = false) {
document.getElementById('SubmitButton').disabled = true; document.getElementById("SubmitButton").disabled = true;
var discontinuities = mapDiscontinuities(); var discontinuities = mapDiscontinuities();
var start = getRealTimeForPlayerTime(discontinuities, player.trimmingControls().options.startTrim); var start = getRealTimeForPlayerTime(
if (start) {start = start.replace('Z','');} discontinuities,
player.trimmingControls().options.startTrim
);
if (start) {
start = start.replace("Z", "");
}
var end = getRealTimeForPlayerTime(discontinuities, player.trimmingControls().options.endTrim); var end = getRealTimeForPlayerTime(discontinuities, player.trimmingControls().options.endTrim);
if (end) {end = end.replace('Z','');} if (end) {
end = end.replace("Z", "");
var wubData = { }
video_start:start,
video_end:end, var wubData = {
video_title:document.getElementById("VideoTitle").value, video_start: start,
video_description:document.getElementById("VideoDescription").value, video_end: end,
video_tags:tags_string_to_list(document.getElementById("VideoTags").value), video_title: document.getElementById("VideoTitle").value,
allow_holes:document.getElementById('AllowHoles').checked, video_description: document.getElementById("VideoDescription").value,
upload_location:document.getElementById('uploadLocation').value, video_tags: tags_string_to_list(document.getElementById("VideoTags").value),
video_channel:document.getElementById("StreamName").value, allow_holes: document.getElementById("AllowHoles").checked,
video_quality:document.getElementById('qualityLevel').options[document.getElementById('qualityLevel').options.selectedIndex].value, upload_location: document.getElementById("uploadLocation").value,
uploader_whitelist:(document.getElementById('uploaderWhitelist').value ? document.getElementById('uploaderWhitelist').value.split(','):null), video_channel: document.getElementById("StreamName").value,
state:state, video_quality:
document.getElementById("qualityLevel").options[
document.getElementById("qualityLevel").options.selectedIndex
].value,
uploader_whitelist: document.getElementById("uploaderWhitelist").value
? document.getElementById("uploaderWhitelist").value.split(",")
: null,
state: state,
//pass back the sheet columns to check if any have changed //pass back the sheet columns to check if any have changed
sheet_name:document.data.sheet_name, sheet_name: document.data.sheet_name,
event_start:document.data.event_start, event_start: document.data.event_start,
event_end:document.data.event_end, event_end: document.data.event_end,
category:document.data.category, category: document.data.category,
description:document.data.description, description: document.data.description,
notes:document.data.notes, notes: document.data.notes,
tags:document.data.tags, tags: document.data.tags,
}; };
if (!!user) { if (!!user) {
wubData.token = user.getAuthResponse().id_token wubData.token = user.getAuthResponse().id_token;
} }
if (override_changes) { if (override_changes) {
wubData["override_changes"] = true; wubData["override_changes"] = true;
} }
console.log(wubData); console.log(wubData);
console.log(JSON.stringify(wubData)); console.log(JSON.stringify(wubData));
if (!wubData.video_start) {alert("No start time set"); return;} if (!wubData.video_start) {
if (!wubData.video_end) {alert("No end time set"); return;} alert("No start time set");
return;
}
if (!wubData.video_end) {
alert("No end time set");
return;
}
//Submit to thrimshim //Submit to thrimshim
var rowId = /id=(.*)(?:&|$)/.exec(document.location.search)[1]; var rowId = /id=(.*)(?:&|$)/.exec(document.location.search)[1];
fetch("/thrimshim/" + rowId, { fetch("/thrimshim/" + rowId, {
method: 'POST', method: "POST",
headers: { headers: {
'Accept': 'application/json', Accept: "application/json",
'Content-Type': 'application/json' "Content-Type": "application/json",
}, },
body: JSON.stringify(wubData) body: JSON.stringify(wubData),
}) }).then(response =>
.then(response => response.text().then(text => { response.text().then(text => {
if (!response.ok) { if (!response.ok) {
var error = response.statusText + ": " + text; var error = response.statusText + ": " + text;
if (response.status == 409) { if (response.status == 409) {
dialogue = text + "\nClick Ok to submit anyway; Click Cancel to return to editing" dialogue = text + "\nClick Ok to submit anyway; Click Cancel to return to editing";
if (confirm(dialogue)) { if (confirm(dialogue)) {
thrimbletrimmerSubmit(state, true); thrimbletrimmerSubmit(state, true);
} }
} else { } else {
alert(error); alert(error);
} }
} else if (state == 'EDITED') { } else if (state == "EDITED") {
alert(`Edit submitted for video from ${start} to ${end}`) alert(`Edit submitted for video from ${start} to ${end}`);
} else { } else {
alert("Draft saved"); alert("Draft saved");
} }
document.getElementById('SubmitButton').disabled = false; document.getElementById("SubmitButton").disabled = false;
})); })
);
}; };
thrimbletrimmerDownload = function(isEditor) { thrimbletrimmerDownload = function (isEditor) {
var range = getTimeRangeAsTimestamp(); var range = getTimeRangeAsTimestamp();
if (isEditor) { if (isEditor) {
if(player.trimmingControls().options.startTrim >= player.trimmingControls().options.endTrim) { if (player.trimmingControls().options.startTrim >= player.trimmingControls().options.endTrim) {
alert("End Time must be greater than Start Time"); alert("End Time must be greater than Start Time");
return; return;
} }
var discontinuities = mapDiscontinuities(); var discontinuities = mapDiscontinuities();
range.start = getRealTimeForPlayerTime(discontinuities, player.trimmingControls().options.startTrim); range.start = getRealTimeForPlayerTime(
range.end = getRealTimeForPlayerTime(discontinuities, player.trimmingControls().options.endTrim); discontinuities,
} player.trimmingControls().options.startTrim
);
var targetURL = "/cut/" + document.getElementById("StreamName").value + range.end = getRealTimeForPlayerTime(
"/"+document.getElementById('qualityLevel').options[document.getElementById('qualityLevel').options.selectedIndex].value+".ts" + discontinuities,
"?" + buildQuery({ player.trimmingControls().options.endTrim
start: range.start, );
end: range.end, }
var targetURL =
"/cut/" +
document.getElementById("StreamName").value +
"/" +
document.getElementById("qualityLevel").options[
document.getElementById("qualityLevel").options.selectedIndex
].value +
".ts" +
"?" +
buildQuery({
start: range.start,
end: range.end,
// In non-editor, always use rough cut. They don't have the edit controls to do // In non-editor, always use rough cut. They don't have the edit controls to do
// fine time selection anyway. // fine time selection anyway.
type: (isEditor) ? ( type: isEditor
document.getElementById('DownloadType').options[document.getElementById('DownloadType').options.selectedIndex].value ? document.getElementById("DownloadType").options[
) : "rough", document.getElementById("DownloadType").options.selectedIndex
// Always allow holes in non-editor, accidentially including holes isn't important ].value
allow_holes: (isEditor) ? String(document.getElementById('AllowHoles').checked) : "true", : "rough",
}); // Always allow holes in non-editor, accidentially including holes isn't important
console.log(targetURL); allow_holes: isEditor ? String(document.getElementById("AllowHoles").checked) : "true",
document.getElementById('DownloadLink').href = targetURL; });
document.getElementById('DownloadLink').style.display = ""; console.log(targetURL);
document.getElementById("DownloadLink").href = targetURL;
document.getElementById("DownloadLink").style.display = "";
}; };
thrimbletrimmerManualLink = function() { thrimbletrimmerManualLink = function () {
document.getElementById("ManualButton").disabled = true; document.getElementById("ManualButton").disabled = true;
var rowId = /id=(.*)(?:&|$)/.exec(document.location.search)[1]; var rowId = /id=(.*)(?:&|$)/.exec(document.location.search)[1];
var upload_location = (document.getElementById("ManualYoutube").checked) ? "youtube-manual" : "manual"; var upload_location = document.getElementById("ManualYoutube").checked
var body = {link: document.getElementById("ManualLink").value, upload_location: upload_location}; ? "youtube-manual"
if (!!user) { : "manual";
body.token = user.getAuthResponse().id_token; var body = {
} link: document.getElementById("ManualLink").value,
fetch("/thrimshim/manual-link/"+rowId, { upload_location: upload_location,
method: 'POST', };
headers: { if (!!user) {
'Accept': 'application/json', body.token = user.getAuthResponse().id_token;
'Content-Type': 'application/json' }
}, fetch("/thrimshim/manual-link/" + rowId, {
body: JSON.stringify(body) method: "POST",
}) headers: {
.then(response => response.text().then(text => { Accept: "application/json",
if (!response.ok) { "Content-Type": "application/json",
var error = response.statusText + ": " + text; },
console.log(error); body: JSON.stringify(body),
alert(error); }).then(response =>
document.getElementById("ManualButton").disabled = false; response.text().then(text => {
} else { if (!response.ok) {
alert("Manual link set to " + body.link); var error = response.statusText + ": " + text;
setTimeout(() => { window.location.href = '/thrimbletrimmer/dashboard.html'; }, 500); console.log(error);
} alert(error);
})); document.getElementById("ManualButton").disabled = false;
} else {
alert("Manual link set to " + body.link);
setTimeout(() => {
window.location.href = "/thrimbletrimmer/dashboard.html";
}, 500);
}
})
);
}; };
thrimbletrimmerResetLink = function(force) { thrimbletrimmerResetLink = function (force) {
var rowId = /id=(.*)(?:&|$)/.exec(document.location.search)[1]; var rowId = /id=(.*)(?:&|$)/.exec(document.location.search)[1];
if(force && !confirm( if (
'Are you sure you want to reset this event? ' + force &&
'This will set the row back to UNEDITED and forget about any video that already may exist. ' + !confirm(
'It is intended as a last-ditch command to clear a malfunctioning cutter, ' + "Are you sure you want to reset this event? " +
'or if a video needs to be re-edited and replaced. ' + "This will set the row back to UNEDITED and forget about any video that already may exist. " +
'IT IS YOUR RESPONSIBILITY TO DEAL WITH ANY VIDEO THAT MAY HAVE ALREADY BEEN UPLOADED. ' "It is intended as a last-ditch command to clear a malfunctioning cutter, " +
)) { "or if a video needs to be re-edited and replaced. " +
return; "IT IS YOUR RESPONSIBILITY TO DEAL WITH ANY VIDEO THAT MAY HAVE ALREADY BEEN UPLOADED. "
} )
document.getElementById("ResetButton").disabled = true; ) {
document.getElementById("CancelButton").disabled = true; return;
var body = {} }
if (!!user) { document.getElementById("ResetButton").disabled = true;
body.token = user.getAuthResponse().id_token; document.getElementById("CancelButton").disabled = true;
} var body = {};
fetch("/thrimshim/reset/"+rowId + "?force=" + force, { if (!!user) {
method: 'POST', body.token = user.getAuthResponse().id_token;
headers: { }
'Accept': 'application/json', fetch("/thrimshim/reset/" + rowId + "?force=" + force, {
'Content-Type': 'application/json' method: "POST",
}, headers: {
body: JSON.stringify(body) Accept: "application/json",
}) "Content-Type": "application/json",
.then(response => response.text().then(text => { },
if (!response.ok) { body: JSON.stringify(body),
var error = response.statusText + ": " + text; }).then(response =>
console.log(error); response.text().then(text => {
alert(error); if (!response.ok) {
document.getElementById("ResetButton").disabled = false; var error = response.statusText + ": " + text;
document.getElementById("CancelButton").disabled = true; console.log(error);
} else { alert(error);
alert("Row has been " + ((force) ? "reset" : "cancelled") +". Reloading..."); document.getElementById("ResetButton").disabled = false;
setTimeout(() => { window.location.reload(); }, 500); document.getElementById("CancelButton").disabled = true;
} } else {
})); alert("Row has been " + (force ? "reset" : "cancelled") + ". Reloading...");
setTimeout(() => {
window.location.reload();
}, 500);
}
})
);
}; };
tags_list_to_string = function(tag_list) { tags_list_to_string = function (tag_list) {
return tag_list.join(", "); return tag_list.join(", ");
} };
tags_string_to_list = function(tag_string) { tags_string_to_list = function (tag_string) {
return tag_string.split(",").map(tag => tag.trim()).filter(tag => tag.length > 0); return tag_string
} .split(",")
.map(tag => tag.trim())
.filter(tag => tag.length > 0);
};
round_trip_tag_string = function() { round_trip_tag_string = function () {
var element = document.getElementById("VideoTags"); var element = document.getElementById("VideoTags");
element.value = tags_list_to_string( element.value = tags_list_to_string(tags_string_to_list(element.value));
tags_string_to_list( };
element.value
)
);
}

@ -8,92 +8,95 @@ function changeSpeed(direction) {
var newIndex = currentIndex + direction; var newIndex = currentIndex + direction;
if (newIndex < 0 || newIndex >= speeds.length) { if (newIndex < 0 || newIndex >= speeds.length) {
// out of range // out of range
return return;
} }
player.playbackRate(speeds[newIndex]); player.playbackRate(speeds[newIndex]);
} }
document.addEventListener('keypress', (event) => { document.addEventListener("keypress", event => {
//if(event.target.nodeName == "BODY") { //if(event.target.nodeName == "BODY") {
if(event.target.nodeName !== "INPUT" && event.target.nodeName !== "TEXTAREA") { if (event.target.nodeName !== "INPUT" && event.target.nodeName !== "TEXTAREA") {
switch(event.key) { switch (event.key) {
case "j": case "j":
player.currentTime(player.currentTime()-10); player.currentTime(player.currentTime() - 10);
break; break;
case "k": case "k":
case " ": // also pause on space case " ": // also pause on space
player.paused() ? player.play():player.pause(); player.paused() ? player.play() : player.pause();
break; break;
case "l": case "l":
player.currentTime(player.currentTime()+10); player.currentTime(player.currentTime() + 10);
break; break;
case ",": case ",":
player.currentTime(player.currentTime()-0.1); player.currentTime(player.currentTime() - 0.1);
break; break;
case ".": case ".":
player.currentTime(player.currentTime()+0.1); player.currentTime(player.currentTime() + 0.1);
break; break;
case "i": case "i":
player.trimmingControls().updateTrimTimes(player.currentTime(), player.trimmingControls().options.endTrim); player
break; .trimmingControls()
case "o": .updateTrimTimes(player.currentTime(), player.trimmingControls().options.endTrim);
player.trimmingControls().updateTrimTimes(player.trimmingControls().options.startTrim, player.currentTime()); break;
break; case "o":
player
.trimmingControls()
.updateTrimTimes(player.trimmingControls().options.startTrim, player.currentTime());
break;
case "=": case "=":
changeSpeed(1); changeSpeed(1);
break break;
case "-": case "-":
changeSpeed(-1); changeSpeed(-1);
break break;
case "0": case "0":
player.currentTime(0); player.currentTime(0);
break; break;
case "1": case "1":
player.currentTime(player.duration()*0.1); player.currentTime(player.duration() * 0.1);
break; break;
case "2": case "2":
player.currentTime(player.duration()*0.2); player.currentTime(player.duration() * 0.2);
break; break;
case "3": case "3":
player.currentTime(player.duration()*0.3); player.currentTime(player.duration() * 0.3);
break; break;
case "4": case "4":
player.currentTime(player.duration()*0.4); player.currentTime(player.duration() * 0.4);
break; break;
case "5": case "5":
player.currentTime(player.duration()*0.5); player.currentTime(player.duration() * 0.5);
break; break;
case "6": case "6":
player.currentTime(player.duration()*0.6); player.currentTime(player.duration() * 0.6);
break; break;
case "7": case "7":
player.currentTime(player.duration()*0.7); player.currentTime(player.duration() * 0.7);
break; break;
case "8": case "8":
player.currentTime(player.duration()*0.8); player.currentTime(player.duration() * 0.8);
break; break;
case "9": case "9":
player.currentTime(player.duration()*0.9); player.currentTime(player.duration() * 0.9);
break; break;
} }
} }
// const keyName = event.key; // const keyName = event.key;
// console.log('keypress event\n\n' + 'key: ' + keyName); // console.log('keypress event\n\n' + 'key: ' + keyName);
// console.log(event.target.nodeName); // console.log(event.target.nodeName);
}); });
//Arrow keys only detected on keydown, keypress only works in "some" browsers //Arrow keys only detected on keydown, keypress only works in "some" browsers
document.addEventListener('keydown', (event) => { document.addEventListener("keydown", event => {
if(event.target.nodeName !== "INPUT" && event.target.nodeName !== "TEXTAREA") { if (event.target.nodeName !== "INPUT" && event.target.nodeName !== "TEXTAREA") {
switch(event.keyCode) { switch (event.keyCode) {
case 37: case 37:
player.currentTime(player.currentTime()-5); player.currentTime(player.currentTime() - 5);
break; break;
case 39: case 39:
player.currentTime(player.currentTime()+5); player.currentTime(player.currentTime() + 5);
break; break;
}
} }
}
}); });

@ -1,98 +1,115 @@
var player = null; var player = null;
function setupPlayer(isEditor, source, startTrim, endTrim) { function setupPlayer(isEditor, source, startTrim, endTrim) {
document.getElementById("my-player").style.display = ""; document.getElementById("my-player").style.display = "";
//Make poster of DB logo in correct aspect ratio, to control initial size of fluid container. //Make poster of DB logo in correct aspect ratio, to control initial size of fluid container.
var options = { var options = {
sources: [{ src: source }], sources: [{src: source}],
liveui: true, liveui: true,
//fluid:true, //fluid:true,
controls:true, controls: true,
autoplay:false, autoplay: false,
width:1280, width: 1280,
height:420, height: 420,
playbackRates: [0.5, 1, 1.25, 1.5, 2], playbackRates: [0.5, 1, 1.25, 1.5, 2],
inactivityTimeout: 0, inactivityTimeout: 0,
controlBar: { controlBar: {
fullscreenToggle: true, fullscreenToggle: true,
volumePanel: { volumePanel: {
inline: false inline: false,
} },
} },
}; };
if(player) { //Destroy and recreate the player if it already exists. if (player) {
player.dispose(); //Destroy and recreate the player if it already exists.
document.getElementById("EditorContainer").innerHTML = ` player.dispose();
document.getElementById("EditorContainer").innerHTML = `
<video id="my-player" class="video-js" controls disablePictureInPicture preload="auto"> <video id="my-player" class="video-js" controls disablePictureInPicture preload="auto">
<p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a></p> <p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a></p>
</video> </video>
`; `;
} }
player = videojs('my-player', options, function onPlayerReady() { player = videojs("my-player", options, function onPlayerReady() {
videojs.log('Your player is ready!'); videojs.log("Your player is ready!");
// Set player volume to 50% by default // Set player volume to 50% by default
var defaultVolume = 0.5; var defaultVolume = 0.5;
this.volume(defaultVolume); this.volume(defaultVolume);
// In this context, `this` is the player that was created by Video.js. // In this context, `this` is the player that was created by Video.js.
this.on('ready', function() { this.on("ready", function () {
//this.play(); //this.play();
}); });
this.vhs.playlists.on('loadedmetadata', function() { this.vhs.playlists.on("loadedmetadata", function () {
// setTimeout(function() { player.play(); }, 1000); // setTimeout(function() { player.play(); }, 1000);
player.hasStarted(true); //So it displays all the controls. player.hasStarted(true); //So it displays all the controls.
if (isEditor) { if (isEditor) {
var stream_start = player.vhs.playlists.master.playlists.filter(playlist => typeof playlist.discontinuityStarts !== "undefined")[0].dateTimeObject; var stream_start = player.vhs.playlists.master.playlists.filter(
startTrim = startTrim ? (new Date(startTrim+"Z")-stream_start)/1000:0; playlist => typeof playlist.discontinuityStarts !== "undefined"
endTrim = endTrim ? (new Date(endTrim+"Z")-stream_start)/1000:player.duration(); )[0].dateTimeObject;
var trimmingControls = player.trimmingControls({ startTrim:startTrim, endTrim:endTrim }); startTrim = startTrim ? (new Date(startTrim + "Z") - stream_start) / 1000 : 0;
} endTrim = endTrim ? (new Date(endTrim + "Z") - stream_start) / 1000 : player.duration();
}); var trimmingControls = player.trimmingControls({startTrim: startTrim, endTrim: endTrim});
}
});
// How about an event listener? // How about an event listener?
this.on('ended', function() { this.on("ended", function () {
videojs.log('Awww...over so soon?!'); videojs.log("Awww...over so soon?!");
}); });
this.on('error', function() { this.on("error", function () {
videojs.log("Could not load video stream"); videojs.log("Could not load video stream");
alert("No video available for stream."); alert("No video available for stream.");
}) });
}); });
var hlsQS = player.hlsQualitySelector(); var hlsQS = player.hlsQualitySelector();
} }
mapDiscontinuities = function() { mapDiscontinuities = function () {
var playlist = player.vhs.playlists.master.playlists.filter(playlist => typeof playlist.discontinuityStarts !== "undefined")[0]; //Only one of the playlists will have the discontinuity or stream start objects, and it's not necessarily the first one or the source one. var playlist = player.vhs.playlists.master.playlists.filter(
var discontinuities = playlist.discontinuityStarts.map(segmentIndex => { return {segmentIndex:segmentIndex, segmentTimestamp:playlist.segments[segmentIndex].dateTimeObject, playbackIndex:null}; }); playlist => typeof playlist.discontinuityStarts !== "undefined"
//var lastDiscontinuity = Math.max(...playlist.discontinuityStarts); )[0]; //Only one of the playlists will have the discontinuity or stream start objects, and it's not necessarily the first one or the source one.
var lastDiscontinuity = playlist.discontinuityStarts.slice(-1).pop(); //Assumes discontinuities are sorted in ascending order. var discontinuities = playlist.discontinuityStarts.map(segmentIndex => {
return {
segmentIndex: segmentIndex,
segmentTimestamp: playlist.segments[segmentIndex].dateTimeObject,
playbackIndex: null,
};
});
//var lastDiscontinuity = Math.max(...playlist.discontinuityStarts);
var lastDiscontinuity = playlist.discontinuityStarts.slice(-1).pop(); //Assumes discontinuities are sorted in ascending order.
var durationMarker = 0; var durationMarker = 0;
for (var index = 0; index <= lastDiscontinuity; index++) { for (var index = 0; index <= lastDiscontinuity; index++) {
let segment = playlist.segments[index]; let segment = playlist.segments[index];
if(segment.discontinuity) { if (segment.discontinuity) {
discontinuities.find(discontinuity => discontinuity.segmentIndex == index).playbackIndex = durationMarker; discontinuities.find(discontinuity => discontinuity.segmentIndex == index).playbackIndex =
} durationMarker;
durationMarker += segment.duration; }
} durationMarker += segment.duration;
}
return discontinuities; return discontinuities;
}; };
getRealTimeForPlayerTime = function(discontinuities, playbackIndex) { getRealTimeForPlayerTime = function (discontinuities, playbackIndex) {
var streamStart = player.vhs.playlists.master.playlists.filter(playlist => typeof playlist.dateTimeObject !== "undefined")[0].dateTimeObject; //Only one of the playlists will have the discontinuity or stream start objects, and it's not necessarily the first one or the source one. var streamStart = player.vhs.playlists.master.playlists.filter(
playlist => typeof playlist.dateTimeObject !== "undefined"
)[0].dateTimeObject; //Only one of the playlists will have the discontinuity or stream start objects, and it's not necessarily the first one or the source one.
//Find last discontinuity before playbackIndex //Find last discontinuity before playbackIndex
var lastDiscontinuity = discontinuities.filter(discontinuity => discontinuity.playbackIndex < playbackIndex).slice(-1).pop(); var lastDiscontinuity = discontinuities
if(lastDiscontinuity) { .filter(discontinuity => discontinuity.playbackIndex < playbackIndex)
streamStart = lastDiscontinuity.segmentTimestamp; .slice(-1)
playbackIndex -= lastDiscontinuity.playbackIndex; .pop();
} if (lastDiscontinuity) {
streamStart = lastDiscontinuity.segmentTimestamp;
playbackIndex -= lastDiscontinuity.playbackIndex;
}
var realTime = streamStart.getTime()+playbackIndex*1000; var realTime = streamStart.getTime() + playbackIndex * 1000;
return (isFinite(realTime)) ? new Date(realTime).toISOString() : null; return isFinite(realTime) ? new Date(realTime).toISOString() : null;
}; };

Loading…
Cancel
Save