mirror of
https://github.com/mehotkhan/BandersnatchInteractive.git
synced 2025-07-27 17:23:22 +00:00
first commit
This commit is contained in:
commit
08e385231b
8 changed files with 33543 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
Black.Mirror.Bandersnatch.2018.720p.WEB-DL.x264.DUAL.mkv
|
||||
Black.Mirror.Bandersnatch.2018.WEBRip.x264-NoGRP.srt
|
1
README.md
Normal file
1
README.md
Normal file
|
@ -0,0 +1 @@
|
|||
# BandersnatchInteractive
|
7131
assets/SegmentMap.js
Normal file
7131
assets/SegmentMap.js
Normal file
File diff suppressed because it is too large
Load diff
742
assets/SubPlayerJS.js
Normal file
742
assets/SubPlayerJS.js
Normal file
|
@ -0,0 +1,742 @@
|
|||
!window.jQuery && document.write(unescape('%3Cscript src="https://code.jquery.com/jquery-2.1.1.min.js"%3E%3C%2Fscript%3E%3Cscript src="jquery.ajax-cross-origin.min.js"%3E%3C%2Fscript%3E'));
|
||||
|
||||
//loads video
|
||||
var timeStamp = 0 + ":" + 0 + ":" + 0 + "." + 0;
|
||||
var lineNumber = 0;
|
||||
var currentTime = 0;
|
||||
var videoPlayerLoaded = false;
|
||||
var subtitleIsSet = false;
|
||||
var guiIsvisible = false;
|
||||
var isPlaying = false;
|
||||
var isFullScreen = false;
|
||||
var isSubtitleEnabled = true;
|
||||
var isSeeking = false;
|
||||
var isParsing = false;
|
||||
var subtitleArray = [];
|
||||
var ammountOfVideos = 0;
|
||||
var fontsArray = [];
|
||||
|
||||
|
||||
|
||||
class SubPlayerJS {
|
||||
|
||||
constructor(div, file) {
|
||||
this.div = div;
|
||||
this.file = file;
|
||||
this.timeStamp = timeStamp;
|
||||
this.previousVidWidth;
|
||||
this.previousVidHeight;
|
||||
this.lineNumber = lineNumber;
|
||||
this.currentTime = currentTime;
|
||||
this.interval;
|
||||
this.videoPlayerLoaded = videoPlayerLoaded;
|
||||
this.subtitleIsSet = subtitleIsSet;
|
||||
this.guiIsvisible = false;
|
||||
this.isPlaying = isPlaying;
|
||||
this.isFullScreen = isFullScreen;
|
||||
this.isSubtitleEnabled = isSubtitleEnabled;
|
||||
this.subtitleArray = [];
|
||||
this.isSeeking = isSeeking;
|
||||
this.timer;
|
||||
|
||||
|
||||
if (!$("link[href='http://fonts.googleapis.com/icon?family=Material+Icons']").length) {
|
||||
loadjscssfile("http://fonts.googleapis.com/icon?family=Material+Icons", "css");
|
||||
}
|
||||
if (!$("link[href='https://rawgit.com/EldinZenderink/SubPlayerJS/master/SubPlayerJS.css']").length) {
|
||||
loadjscssfile("https://rawgit.com/EldinZenderink/SubPlayerJS/master/SubPlayerJS.css", "css");
|
||||
}
|
||||
if (!$("link[href='https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.6/css/materialize.min.css']").length) {
|
||||
loadjscssfile("https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.6/css/materialize.min.css", "css");
|
||||
}
|
||||
|
||||
ammountOfVideos++;
|
||||
subtitleArray.push([]);
|
||||
fontsArray.push({});
|
||||
this.loadVideo(ammountOfVideos);
|
||||
|
||||
this.videoid = ammountOfVideos;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
parseSubtitle(){
|
||||
this.resetSubtitle();
|
||||
var subPlayerVideo = SubPlayerJS.getVideo(this.videoid.toString());
|
||||
var previousTime = 0;
|
||||
var previousTotalAVBytesDecoded = 0;
|
||||
var bitRate = 0;
|
||||
var curTime = 0;
|
||||
var totalAVBytesDecoded= 0;
|
||||
var packsParsed = 0;
|
||||
var packsSize = 0;
|
||||
var packsContainingSubtitle = 0;
|
||||
var timeItSeekedTo = 0;
|
||||
var timeSeekTook = 0;
|
||||
var audioBytesDecoded = 0;
|
||||
var videoBytesDecoded = 0;
|
||||
var bitRate = 0;
|
||||
var curTime = 0;
|
||||
var guessedBytePosition = 0;
|
||||
var parsedSubtitle = [];
|
||||
var needsToSeek = false;
|
||||
var isPlaying = false;
|
||||
var sourceUrl = this.file;
|
||||
var videoid = this.videoid.toString();
|
||||
console.log(videoid);
|
||||
console.log(subPlayerVideo);
|
||||
subPlayerVideo.onended = function(e) {
|
||||
isPlaying = false;
|
||||
};
|
||||
subPlayerVideo.onplay = function(){
|
||||
isPlaying = true;
|
||||
}
|
||||
subPlayerVideo.onpause = function(){
|
||||
isPlaying = false;
|
||||
console.log("is pausing");
|
||||
console.log(subPlayerVideo.currentTime);
|
||||
}
|
||||
subPlayerVideo.onseeking = function(){
|
||||
|
||||
|
||||
timeItSeekedTo = subPlayerVideo.currentTime;
|
||||
|
||||
|
||||
if(!needsToSeek){
|
||||
if(timeItSeekedTo < previousTime){
|
||||
needsToSeek = true;
|
||||
var parsedSubtitleLength = parsedSubtitle.length;
|
||||
|
||||
for(var x = 0; x < parsedSubtitleLength; x++){
|
||||
var timeOfSubtitle = parsedSubtitle[x].time;
|
||||
if(Math.round(timeOfSubtitle) > Math.round(timeItSeekedTo)){
|
||||
guessedBytePosition = totalAVBytesDecoded - parsedSubtitle[x].decodedBytes;
|
||||
subPlayerVideo.currentTime = timeOfSubtitle;
|
||||
return;
|
||||
}
|
||||
}
|
||||
needsToSeek = false;
|
||||
} else {
|
||||
subPlayerVideo.currentTime = previousTime;
|
||||
needsToSeek = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
subPlayerVideo.ontimeupdate = function(){
|
||||
|
||||
audioBytesDecoded = subPlayerVideo.webkitAudioDecodedByteCount;
|
||||
videoBytesDecoded = subPlayerVideo.webkitVideoDecodedByteCount;
|
||||
totalAVBytesDecoded = videoBytesDecoded + audioBytesDecoded;
|
||||
curTime = subPlayerVideo.currentTime;
|
||||
bitRate = totalAVBytesDecoded / curTime;
|
||||
|
||||
|
||||
|
||||
var startRequest = Math.round(previousTotalAVBytesDecoded - guessedBytePosition) ;
|
||||
var endRequest = Math.round(totalAVBytesDecoded - guessedBytePosition) ;
|
||||
packsSize = endRequest - startRequest;
|
||||
|
||||
if(subPlayerVideo.currentTime < timeItSeekedTo){
|
||||
subPlayerVideo.playbackRate = 100;
|
||||
} else {
|
||||
needsToSeek = false;
|
||||
subPlayerVideo.playbackRate = 1;
|
||||
var oReq2 = new XMLHttpRequest();
|
||||
oReq2.open("GET", sourceUrl, true);
|
||||
oReq2.setRequestHeader('Range', 'bytes=' + startRequest + '-' + endRequest);
|
||||
oReq2.responseType = "blob";
|
||||
|
||||
oReq2.onload = function(oEvent) {
|
||||
console.log("Received file!");
|
||||
var blob = oReq2.response;
|
||||
packsParsed++;
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(){
|
||||
var binaryString = this.result;
|
||||
if(binaryString.indexOf("0,,")){
|
||||
var searchResult = binaryString.split("0,,");
|
||||
var resultLength = searchResult.length;
|
||||
if(resultLength > 1){
|
||||
var parsed = "";
|
||||
for(var x = 1; x < resultLength; x++){
|
||||
var decoded = decodeURI(encodeURI(searchResult[x]).split('%E2%80%BA')[0]) + " \r\n";
|
||||
if(decoded.indexOf('%E2%80%BA') < 0 && decoded !== undefined){
|
||||
parsed = parsed + decoded;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
parsedSubtitle.push({time: curTime, decodedBytes: previousTotalAVBytesDecoded});
|
||||
packsContainingSubtitle++;
|
||||
//document.querySelector('#result').innerHTML = parsed;
|
||||
$('#subtitle_' + videoid.toString()).html('<div style="font-family: Sans-Serif;">' + parsed.replace("\\N", "<br />") + '</div>');
|
||||
console.log(videoid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
reader.readAsText(blob, 'ISO-8859-1');
|
||||
};
|
||||
oReq2.send(null);
|
||||
|
||||
}
|
||||
|
||||
|
||||
var data = " \
|
||||
Time: " + curTime + " \r\n \
|
||||
BitRate: " + (bitRate / 100) + "kbps \r\n \
|
||||
Audio Bytes Decoded: " + (audioBytesDecoded / 1000000) + "mb \r\n \
|
||||
Video Bytes Decoded: " + (videoBytesDecoded / 1000000) + "mb \r\n \
|
||||
Total Bytes Decoded: " + (totalAVBytesDecoded / 1000000) + " mb \r\n \
|
||||
Buffer Length: " + subPlayerVideo.buffered.length + "\r\n \
|
||||
Buffer Start: " + subPlayerVideo.buffered.start(subPlayerVideo.buffered.length - 1) + "\r\n \
|
||||
Buffer End: " + subPlayerVideo.buffered.end(subPlayerVideo.buffered.length - 1) + "\r\n \
|
||||
Packs Parsed: " + packsParsed + "\r\n \
|
||||
Packs Contianing Subtitle: " + packsContainingSubtitle + " \r\n \
|
||||
Timedifference seek: " + timeSeekTook + " \r\n \
|
||||
guessedBytePosition: " + guessedBytePosition + " \r\n \
|
||||
Packs Size: " + packsSize;
|
||||
|
||||
//document.querySelector('#videodata').innerHTML = data;
|
||||
|
||||
previousTotalAVBytesDecoded = totalAVBytesDecoded;
|
||||
//previousTime = curTime;
|
||||
|
||||
}
|
||||
setInterval(function(){
|
||||
if(previousTime != curTime){
|
||||
previousTime = curTime;
|
||||
}
|
||||
|
||||
}, 1000);
|
||||
|
||||
|
||||
}
|
||||
|
||||
setSubtitle(subtitleurl) {
|
||||
this.resetSubtitle();
|
||||
this.subtitle = subtitleurl;
|
||||
|
||||
if (subtitleurl != "" && subtitleurl != null && subtitleurl != 0) {
|
||||
this.getSubtitle(this.videoid);
|
||||
} else {
|
||||
this.subtitleIsSet = false;
|
||||
$('#enableSub_' + ammountOfVideos.toString()).html('<i class="material-icons" style="color: rgb(96, 96, 96);">subtitles</i>');
|
||||
}
|
||||
|
||||
this.getTimeStamp();
|
||||
|
||||
}
|
||||
|
||||
setWidth(width) {
|
||||
this.videoWidth = width;
|
||||
|
||||
}
|
||||
|
||||
setHeight(height) {
|
||||
this.videoHeight = height;
|
||||
}
|
||||
|
||||
resetSubtitle() {
|
||||
$('#subtitle_' + this.videoid.toString()).html('');
|
||||
}
|
||||
|
||||
loadVideo(videoid) {
|
||||
var vidwidth = 0;
|
||||
var vidheight = 0;
|
||||
|
||||
try {
|
||||
clearInterval(this.interval);
|
||||
} catch (e) {
|
||||
console.log("no interval running");
|
||||
}
|
||||
|
||||
if (this.videoWidth != null && this.videoWidth != "" && this.videoWidth != 0) {
|
||||
vidwidth = this.videoWidth;
|
||||
} else {
|
||||
vidwidth = "100%";
|
||||
}
|
||||
|
||||
if (this.videoHeight != null && this.videoHeight != "" && this.videoHeight != 0) {
|
||||
vidheight = this.videoHeight;
|
||||
} else {
|
||||
vidheight = "";
|
||||
}
|
||||
|
||||
if (!this.videoPlayerLoaded || this.previousVidHeight != h || this.previousVidWidth != w) {
|
||||
|
||||
$(this.div).html('<div class="outer-container-SPJS " id="outerContainer_' + videoid.toString() + '">\
|
||||
<div class="inner-container-SPJS " id="innerContainer_' + videoid.toString() + '">\
|
||||
<div class="video-overlay-SPJS" id="subtitle_' + videoid.toString() + '"><br /></div>\
|
||||
<div style="min-width: 100%;" class="control-SPJS" id="controlDiv_' + videoid.toString() + '"></div>\
|
||||
<video id="SubPlayerVideo_' + videoid.toString() + '" width="' + vidwidth + '" height="' + vidheight + '">\
|
||||
<source id="videoSource_' + videoid.toString() + '" src="">\
|
||||
Your browser does not support HTML5 video.\
|
||||
</video>\
|
||||
</div>\
|
||||
</div>');
|
||||
this.videoPlayerLoaded = true;
|
||||
}
|
||||
|
||||
this.previousVidWidth = this.videoWidth;
|
||||
this.previousVidHeight = this.videoHeight;
|
||||
|
||||
var subPlayerVideo = SubPlayerJS.getVideo(videoid.toString());
|
||||
subPlayerVideo = subPlayerVideo;
|
||||
subPlayerVideo.src = this.file;
|
||||
subPlayerVideo.addEventListener('loadedmetadata', function() {
|
||||
var max = subPlayerVideo.duration;
|
||||
|
||||
$('#controlDiv_' + videoid.toString()).html('<div id="allcontrols_' + videoid.toString() + '" style="width: 100%;"><a href="javascript:;" style="bottom: 7px;" id="playpause_' + videoid.toString() + '" onclick="SubPlayerJS.startPlayVideo(' + videoid.toString() + ')"><i class="material-icons" style="color: rgb(255, 255, 255);">play_arrow</i></a><span style="visibility:hidden"> | </span><input onclick="SubPlayerJS.onSeekBarClick(' + videoid.toString() + ')" style="min-width: 80%; bottom: 9px;" type="range" id="seekbar_' + videoid.toString() + '" min="0" max="' + max + '" /><span style="visibility:hidden"> | </span><a id="fullScreen_' + videoid.toString() + '" href="javascript:;" style=" style="" onclick="SubPlayerJS.makeFullScreen(' + videoid.toString() + ')"><i class="material-icons" style="font-size: 24px; color: rgb(255, 255, 255);" >fullscreen</i></a><span style="visibility:hidden"> | </span><a href="javascript:;" id="enableSub_' + videoid.toString() + '" onclick="SubPlayerJS.enaDisaSub(' + videoid.toString() + ')"> <i class="material-icons" style="color: rgb(255, 255, 255);">subtitles</i></a></div>');
|
||||
$('#seekbar_' + videoid.toString()).val(0).css("width", "80%").css("right", "5px");
|
||||
|
||||
$('#allcontrols').hide();
|
||||
|
||||
setTimeout(function() {
|
||||
setInterval(function() {
|
||||
if (!this.isSeeking) {
|
||||
$('#seekbar_' + videoid.toString()).val(subPlayerVideo.currentTime);
|
||||
}
|
||||
}, 1000);
|
||||
}, 0);
|
||||
});
|
||||
|
||||
$('#outerContainer_' + videoid.toString()).on("change mousemove", function() {
|
||||
$('#outerContainer_' + videoid.toString()).css({
|
||||
cursor: "auto"
|
||||
});
|
||||
$('#allcontrols_' + videoid.toString()).show();
|
||||
|
||||
clearTimeout(this.timer);
|
||||
this.timer = setTimeout(function() {
|
||||
$('#allcontrols_' + videoid.toString()).hide();
|
||||
$('#outerContainer_' + videoid.toString()).css({
|
||||
cursor: "none"
|
||||
});
|
||||
}, 4000);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
getSubtitle(videoid) {
|
||||
var extension = this.subtitle.replace(/^.*\./, '');
|
||||
$.ajax({
|
||||
url: this.subtitle,
|
||||
type: 'get',
|
||||
async: false,
|
||||
success: function(data) {
|
||||
switch (extension) {
|
||||
case "ass":
|
||||
console.log("SubPlayerJS: SSA (SubStationAlpha) Supported!");
|
||||
SubPlayerJS.parseSubStationAlpha(data, videoid);
|
||||
break;
|
||||
case "srt":
|
||||
|
||||
console.log("SubPlayerJS: SRT (SubRip) Supported!");
|
||||
SubPlayerJS.parseSubRip(data, videoid);
|
||||
break;
|
||||
case "vtt":
|
||||
console.log("SubPlayerJS: Comming soon!");
|
||||
break;
|
||||
case "sub":
|
||||
console.log("SubPlayerJS: Maybe supported in future!");
|
||||
break;
|
||||
case "smi":
|
||||
console.log("SubPlayerJS: Maybe supported in future!");
|
||||
break;
|
||||
case "usf":
|
||||
console.log("SubPlayerJS: Maybe supported in future!");
|
||||
break;
|
||||
default:
|
||||
console.log("SubPlayerJS: Subtitle with extension: " + extension + " is NOT supported!");
|
||||
break;
|
||||
}
|
||||
console.log("SubPlayerJS: Succesfully read subtitle!");
|
||||
},
|
||||
error: function(err) {
|
||||
console.log("SubPlayerJS: FAILED TO LOAD SUBTITLE: " + err);
|
||||
this.subtitleIsSet = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getTimeStamp() {
|
||||
var subPlayerVideo = SubPlayerJS.getVideo(this.videoid.toString());
|
||||
var that = this;
|
||||
var videoid = this.videoid.toString();
|
||||
this.interval = setInterval(function() {
|
||||
var curTimeSecond = subPlayerVideo.currentTime;
|
||||
this.currentTime = curTimeSecond;
|
||||
setTimeout(that.showSubtitle(curTimeSecond, videoid), 0);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
showSubtitle(time, videoid) {
|
||||
var localArray = subtitleArray[videoid - 1];
|
||||
var fonts = fontsArray[videoid - 1];
|
||||
if(fonts.length < 1){
|
||||
fonts["Default"] = "Verdana";
|
||||
}
|
||||
try {
|
||||
var currentText = localArray[this.lineNumber];
|
||||
var secondOfTimeStart = currentText[0];
|
||||
var secondOfTimeEnd = currentText[1];
|
||||
|
||||
if (time < secondOfTimeStart) {
|
||||
|
||||
var index = 0;
|
||||
this.lineNumber = 0;
|
||||
$('#subtitle_' + videoid.toString()).html('');
|
||||
var arrayLength = localArray.length;
|
||||
for (var i = 0; i < arrayLength; i++) {
|
||||
var timeStart = parseInt(localArray[i][0]);
|
||||
var timeEnd = parseInt(localArray[i][1]);
|
||||
|
||||
if (time > timeStart) {
|
||||
this.lineNumber = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$('#subtitle_' + videoid.toString()).html('');
|
||||
} else {
|
||||
if (time > secondOfTimeEnd) {
|
||||
this.lineNumber++;
|
||||
$('#subtitle_' + videoid.toString()).html('');
|
||||
} else {
|
||||
var fullText = currentText[2];
|
||||
var fontstyletouse;
|
||||
if(currentText[3] == null || currentText[3].length == 0){
|
||||
fontstyletouse = "Default";
|
||||
} else {
|
||||
fontstyletouse = currentText[3];
|
||||
}
|
||||
$('#subtitle_' + videoid.toString()).html('<div style="font-family: ' + fonts[fontstyletouse] + '">' + fullText.substring(0, fullText.length - 1).replace("\\N", "<br />") + '</div>');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
try{
|
||||
var index = 0;
|
||||
this.lineNumber = 0;
|
||||
$('#subtitle_' + videoid.toString()).html('');
|
||||
var arrayLength = localArray.length;
|
||||
for (var i = 0; i < arrayLength; i++) {
|
||||
var timeStart = parseInt(localArray[i][0]);
|
||||
var timeEnd = parseInt(localArray[i][1]);
|
||||
|
||||
if (time > timeStart) {
|
||||
this.lineNumber = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (e){
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static getVideo(ammount){
|
||||
return document.getElementById('SubPlayerVideo_' + ammount);
|
||||
}
|
||||
|
||||
static timeStampToSeconds(timestamp, fileType) {
|
||||
var totalSeconds = 0;
|
||||
switch(fileType){
|
||||
case "ass":
|
||||
var parts = timestamp.split(':');
|
||||
var hour = parts[0];
|
||||
var minute = parts[1];
|
||||
var second = parts[2];
|
||||
totalSeconds = hour * 3600 + minute * 60 + parseInt(second);
|
||||
break;
|
||||
case "srt":
|
||||
var parts = timestamp.split(':');
|
||||
var hour = parts[0];
|
||||
var minute = parts[1];
|
||||
var second = parts[2].split('\r\n')[0];
|
||||
totalSeconds = hour * 3600 + minute * 60 + parseInt(second);
|
||||
break;
|
||||
}
|
||||
|
||||
return totalSeconds;
|
||||
}
|
||||
|
||||
static parseSubStationAlpha(ssa, videoid) {
|
||||
var fonts = {};
|
||||
console.log(this.fonts);
|
||||
var styling = ssa.split("Styles]")[1].split("[Events]")[0].split("\n");
|
||||
$.each(styling, function(key, style) {
|
||||
if(style.indexOf("Style:") > -1){
|
||||
var information = style.split(':')[1].split(',');
|
||||
var styletype = information[0].trim();
|
||||
var font = information[1].trim();
|
||||
console.log("STYLE TYPE = " + styletype + ", FONT: " + font);
|
||||
fonts[styletype] = font;
|
||||
fontsArray[videoid - 1] = fonts;
|
||||
console.log(this.fonts);
|
||||
}
|
||||
|
||||
});
|
||||
this.loadFont(videoid);
|
||||
var lines = ssa.split("\n");
|
||||
$.each(lines, function(key, line) {
|
||||
if (line.indexOf("Dialogue") > -1) {
|
||||
var parts = line.split(',');
|
||||
parts[0] = SubPlayerJS.timeStampToSeconds(parts[1], "ass");
|
||||
parts[1] = SubPlayerJS.timeStampToSeconds(parts[2], "ass");
|
||||
var text = "";
|
||||
for(var i = 9; i < line.split(',').length; i++){
|
||||
text = text + line.split(',')[i] + ",";
|
||||
}
|
||||
parts[2] = text;
|
||||
|
||||
parts[3] = parts[3];
|
||||
|
||||
for(var i = 4; i < line.split(',').length; i++){
|
||||
parts[i] = "";
|
||||
}
|
||||
subtitleArray[videoid - 1].push(parts);
|
||||
}
|
||||
});
|
||||
this.subtitleIsSet = true;
|
||||
}
|
||||
|
||||
static parseSubRip(srt, videoid){
|
||||
var lines = srt.split(/[\r\n]+[\r\n]+/);
|
||||
$.each(lines, function(key, line) {
|
||||
if (line.indexOf("-->") > -1) {
|
||||
var parts = line.split(/[\r\n]+/)[1].split(/[\r\n]+/)[0].split('-->');
|
||||
parts[0] = SubPlayerJS.timeStampToSeconds(parts[0], "srt");
|
||||
parts[1] = SubPlayerJS.timeStampToSeconds(parts[1], "srt");
|
||||
|
||||
|
||||
var text = "";
|
||||
for(var i = 2; i < line.split(/[\r\n]+/).length; i++){
|
||||
text = text + line.split(/[\r\n]+/)[i] + "<br />";
|
||||
}
|
||||
parts[2] = text;
|
||||
subtitleArray[videoid - 1].push(parts);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static enaDisaSub(videoid) {
|
||||
if (this.isSubtitleEnabled) {
|
||||
this.isSubtitleEnabled = false;
|
||||
|
||||
$('#subtitle_' + videoid.toString()).css("z-index", "-1");
|
||||
$('#enableSub_' + videoid.toString()).html('<i class="material-icons" style="color: rgb(96, 96, 96);">subtitles</i>');
|
||||
|
||||
} else {
|
||||
this.isSubtitleEnabled = true;
|
||||
|
||||
$('#subtitle_' + videoid.toString()).css("z-index", "1");
|
||||
$('#enableSub_' + videoid.toString()).html('<i class="material-icons" style="color: rgb(255, 255, 255);">subtitles</i>');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static startPlayVideo(videoid) {
|
||||
if (!this.isPlaying) {
|
||||
SubPlayerJS.getVideo(videoid).play();
|
||||
$('#playpause_' + videoid.toString()).html('<i class="material-icons" style="color: rgb(255, 255, 255);">pause</i>');
|
||||
this.isPlaying = true;
|
||||
} else {
|
||||
SubPlayerJS.getVideo(videoid).pause();
|
||||
$('#playpause_' + videoid.toString()).html('<i class="material-icons" style="color: rgb(255, 255, 255);">play_arrow</i>');
|
||||
this.isPlaying = false;
|
||||
}
|
||||
}
|
||||
|
||||
static onSeekBarClick(videoid) {
|
||||
var currentPosition = $('#seekbar_' + videoid.toString()).val();
|
||||
SubPlayerJS.getVideo(videoid).currentTime = currentPosition;
|
||||
// console.log(currentPosition);
|
||||
return false;
|
||||
}
|
||||
|
||||
static makeFullScreen(videoid) {
|
||||
var i = document.getElementById('innerContainer_' + videoid.toString());
|
||||
|
||||
// go full-screen
|
||||
|
||||
if (!this.isFullScreen) {
|
||||
|
||||
if (i.requestFullscreen) {
|
||||
i.requestFullscreen();
|
||||
} else if (i.webkitRequestFullscreen) {
|
||||
i.webkitRequestFullscreen();
|
||||
} else if (i.mozRequestFullScreen) {
|
||||
i.mozRequestFullScreen();
|
||||
} else if (i.msRequestFullscreen) {
|
||||
i.msRequestFullscreen();
|
||||
}
|
||||
console.log("going into fullscreen");
|
||||
|
||||
$('#SubPlayerVideo_' + videoid.toString()).css({
|
||||
position: 'fixed', //or fixed depending on needs
|
||||
top: 0,
|
||||
left: 0,
|
||||
height: '100%',
|
||||
"background-color": "black"
|
||||
});
|
||||
|
||||
$('#subtitle_' + videoid.toString()).css({
|
||||
position: 'fixed', //or fixed depending on needs
|
||||
top: '80%',
|
||||
left: 0,
|
||||
height: '100%',
|
||||
width: '100%'
|
||||
});
|
||||
|
||||
$('#controlDiv_' + videoid.toString()).css({
|
||||
position: 'fixed', //or fixed depending on needs
|
||||
top: '85%',
|
||||
left: 0,
|
||||
width: '100%'
|
||||
});
|
||||
$('#fullScreen_' + videoid.toString()).html('<i class="material-icons" style="color: rgb(255, 255, 255);">fullscreen_exit</i>');
|
||||
this.isFullScreen = true;
|
||||
} else {
|
||||
console.log("exiting fullscreen");
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
} else if (document.webkitExitFullscreen) {
|
||||
document.webkitExitFullscreen();
|
||||
} else if (document.mozCancelFullScreen) {
|
||||
document.mozCancelFullScreen();
|
||||
} else if (document.msExitFullscreen) {
|
||||
document.msExitFullscreen();
|
||||
}
|
||||
|
||||
$('#SubPlayerVideo_' + videoid.toString()).css({
|
||||
position: 'relative',
|
||||
"background-color": "",
|
||||
height: ''
|
||||
});
|
||||
|
||||
$('#subtitle_' + videoid.toString()).css({
|
||||
position: 'absolute', //or fixed depending on needs
|
||||
top: '80%',
|
||||
left: 0,
|
||||
height: '',
|
||||
width: '100%'
|
||||
});
|
||||
|
||||
|
||||
$('#controlDiv_' + videoid.toString()).css({
|
||||
position: 'absolute', //or fixed depending on needs
|
||||
top: '85%',
|
||||
left: 0,
|
||||
width: '100%'
|
||||
});
|
||||
$('#fullScreen_' + videoid.toString()).html('<i class="material-icons" style="color: rgb(255, 255, 255);">fullscreen</i>');
|
||||
this.isFullScreen = false;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
static loadFont(videoid){
|
||||
console.log("LOADING FONTS");
|
||||
console.log(fontsArray[videoid - 1]);
|
||||
var fonts = fontsArray[videoid - 1];
|
||||
for (var style in fonts) {
|
||||
var font = fonts[style].split(' ')[0];
|
||||
|
||||
var downloadFont = true;
|
||||
if (typeof(Storage) !== "undefined") {
|
||||
if(localStorage.getItem(style) !== null){
|
||||
console.log("LOADED FONT: " + font + " FROM LOCAL STORAGE :D" );
|
||||
loadjscssfile("data:text/css;base64," + localStorage.getItem(font), "css");
|
||||
downloadFont = false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(downloadFont){
|
||||
console.log("downloading: " + font);
|
||||
$.ajax({
|
||||
async: false,
|
||||
url: 'https://crossorigin.me/https://www.onlinewebfonts.com/search?q=' + font,
|
||||
success: function(data) {
|
||||
//console.log(data);
|
||||
var foundUrl = data.substring(data.indexOf("class=\"url")).split('"')[3].split('"')[0].replace("/download/", "");
|
||||
var fontstyle = data.substring(data.indexOf("class=\"url")).split('"')[5].substring(1 ).split('<')[0];
|
||||
console.log("foundUrl: " + foundUrl);
|
||||
console.log("fontstyle: " + fontstyle);
|
||||
|
||||
$.ajax({
|
||||
async: true,
|
||||
url: "https://crossorigin.me/https://db.onlinewebfonts.com/c/" + foundUrl + "?family=" + fontstyle,
|
||||
success: function(data) {
|
||||
if (typeof(Storage) !== "undefined") {
|
||||
// Store
|
||||
localStorage.setItem(font, btoa(unescape(encodeURIComponent(data))));
|
||||
console.log("saved subtitle: " + fontstyle + " as base64 in localstorage");
|
||||
} else {
|
||||
console.log("did notsaved subtitle: " + fontstyle + " as base64 in localstorage");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
loadjscssfile("https://db.onlinewebfonts.com/c/" + foundUrl + "?family=" + fontstyle, "css");
|
||||
for (var style2 in fonts) {
|
||||
//console.log(fonts[style2] + " =?= " + fonts[style] + "-?>" + fontstyle);
|
||||
if( fonts[style2] == fonts[style]){
|
||||
fonts[style2] = fontstyle;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
fontsArray[videoid - 1] = fonts;
|
||||
console.log("done");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
function loadjscssfile(filename, filetype) {
|
||||
if (filetype == "js") { //if filename is a external JavaScript file
|
||||
var fileref = document.createElement('script')
|
||||
fileref.setAttribute("type", "text/javascript")
|
||||
fileref.setAttribute("src", filename)
|
||||
} else if (filetype == "css") { //if filename is an external CSS file
|
||||
var fileref = document.createElement("link")
|
||||
fileref.setAttribute("rel", "stylesheet")
|
||||
fileref.setAttribute("type", "text/css")
|
||||
fileref.setAttribute("href", filename)
|
||||
}
|
||||
if (typeof fileref != "undefined")
|
||||
document.getElementsByTagName("head")[0].appendChild(fileref)
|
||||
}
|
||||
|
||||
function loadScript(url, callback) {
|
||||
// Adding the script tag to the head as suggested before
|
||||
var head = document.getElementsByTagName('head')[0];
|
||||
var script = document.createElement('script');
|
||||
script.type = 'text/javascript';
|
||||
script.src = url;
|
||||
|
||||
// Then bind the event to the callback function.
|
||||
// There are several events for cross browser compatibility.
|
||||
script.onreadystatechange = callback;
|
||||
script.onload = callback;
|
||||
|
||||
// Fire the loading
|
||||
head.appendChild(script);
|
||||
}
|
24959
assets/bandersnatch.js
Normal file
24959
assets/bandersnatch.js
Normal file
File diff suppressed because it is too large
Load diff
430
assets/scripts.js
Normal file
430
assets/scripts.js
Normal file
|
@ -0,0 +1,430 @@
|
|||
var segmentMap = SegmentMap;
|
||||
var bv = bandersnatch.videos['80988062'].interactiveVideoMoments.value;
|
||||
var choicePoints = bv.choicePointNavigatorMetadata.choicePointsMetadata.choicePoints;
|
||||
var momentsBySegment = bv.momentsBySegment;
|
||||
var segmentGroups = bv.segmentGroups;
|
||||
var captions = {};
|
||||
var currentSegment;
|
||||
var currentMoment;
|
||||
var nextSegment = null;
|
||||
var momentSelected = null;
|
||||
var persistentState = bv.stateHistory;
|
||||
var globalChoices = {};
|
||||
|
||||
function msToString(ms) {
|
||||
return new Date(ms).toUTCString().split(' ')[4];
|
||||
}
|
||||
|
||||
function getCurrentMs() {
|
||||
return Math.round(document.getElementById("video").currentTime * 1000.0);
|
||||
}
|
||||
|
||||
function generateJs(cond) {
|
||||
if (cond[0] == 'persistentState') {
|
||||
return '!!persistentState["' + cond[1] + '"]';
|
||||
} else if (cond[0] == 'not') {
|
||||
return '!(' + generateJs(cond[1]) + ')';
|
||||
} else if (cond[0] == 'and') {
|
||||
var conds = [];
|
||||
for (var i = 1; i < cond.length; i++) {
|
||||
conds.push('(' + generateJs(cond[i]) + ')');
|
||||
}
|
||||
return '(' + conds.join(' && ') + ')';
|
||||
} else if (cond[0] == 'or') {
|
||||
var conds = [];
|
||||
for (var i = 1; i < cond.length; i++) {
|
||||
conds.push('(' + generateJs(cond[i]) + ')');
|
||||
}
|
||||
return '(' + conds.join(' || ') + ')';
|
||||
} else {
|
||||
console.log('unsupported condition!', cond);
|
||||
return 'true';
|
||||
}
|
||||
}
|
||||
|
||||
function checkPrecondition(segmentId) {
|
||||
let precondition = bv.preconditions[segmentId];
|
||||
|
||||
if (precondition) {
|
||||
let cond = generateJs(precondition);
|
||||
let match = eval(cond);
|
||||
|
||||
console.log(cond, '==', match);
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function findSegment(id) {
|
||||
if (id.startsWith('nsg-')) {
|
||||
id = id.substr(4);
|
||||
}
|
||||
if (SegmentMap.segments[id]) {
|
||||
// check precondition
|
||||
return id;
|
||||
}
|
||||
|
||||
if (segmentGroups[id]) {
|
||||
for (v of segmentGroups[id]) {
|
||||
if (v.segmentGroup) {
|
||||
return findSegment(v.segmentGroup);
|
||||
} else if (v.segment) {
|
||||
// check precondition
|
||||
return v.segment;
|
||||
} else {
|
||||
if (checkPrecondition(v))
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
function getChoiceMs(choiceId) {
|
||||
var segmentId = findSegment(choiceId);
|
||||
return getSegmentMs(segmentId);
|
||||
}
|
||||
|
||||
function getSegmentId(ms) {
|
||||
for (const [k, v] of Object.entries(SegmentMap.segments)) {
|
||||
if (ms >= v.startTimeMs && ms < v.endTimeMs) {
|
||||
return k;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getSegmentMs(segmentId) {
|
||||
return segmentMap.segments[segmentId].startTimeMs;
|
||||
}
|
||||
|
||||
function getMoment(ms) {
|
||||
for (const [k, v] of Object.entries(momentsBySegment)) {
|
||||
for (r of v)
|
||||
if (r.type == 'scene:cs_bs') {
|
||||
if (ms >= r.startMs && ms < r.endMs) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function newList(id) {
|
||||
var ul = document.getElementById(id);
|
||||
while (ul.firstChild) {
|
||||
ul.removeChild(ul.firstChild);
|
||||
}
|
||||
return ul;
|
||||
}
|
||||
|
||||
function addItem(ul, text, url) {
|
||||
var li = document.createElement("li");
|
||||
var a = document.createElement("a");
|
||||
a.textContent = text;
|
||||
a.setAttribute('href', url);
|
||||
li.appendChild(a);
|
||||
ul.appendChild(li);
|
||||
}
|
||||
|
||||
function setNextSegment(segmentId, comment) {
|
||||
console.log('setNextSegment', segmentId, comment);
|
||||
nextSegment = segmentId;
|
||||
var ul = newList("nextSegment");
|
||||
var caption = 'nextSegment: ' + segmentId;
|
||||
addItem(ul, comment ? caption + ' (' + comment + ')' : caption,
|
||||
'javascript:playSegment("' + segmentId + '")');
|
||||
}
|
||||
|
||||
function addZones(segmentId) {
|
||||
var ul = newList("interactionZones");
|
||||
var caption = 'currentSegment(' + segmentId + ')';
|
||||
addItem(ul, caption, 'javascript:playSegment("' + segmentId + '")');
|
||||
|
||||
var v = segmentMap.segments[segmentId];
|
||||
if (v && v.ui && v.ui.interactionZones) {
|
||||
var index = 0;
|
||||
for (z of v.ui.interactionZones) {
|
||||
var startMs = z[0];
|
||||
var stopMs = z[1];
|
||||
var caption = segmentId + ' interactionZone ' + index;
|
||||
addItem(ul, caption, 'javascript:seek(' + startMs + ')');
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
var ul = newList("nextSegments");
|
||||
for (const [k, v] of Object.entries(segmentMap.segments[segmentId].next)) {
|
||||
var caption = captions[k] ? captions[k] : k;
|
||||
if (segmentMap.segments[segmentId].defaultNext == k) {
|
||||
caption = '[' + caption + ']';
|
||||
setNextSegment(k);
|
||||
}
|
||||
addItem(ul, caption, 'javascript:playSegment("' + k + '")');
|
||||
}
|
||||
}
|
||||
|
||||
function addChoices(r) {
|
||||
var ul = newList("choices");
|
||||
document.getElementById("choiceCaption").innerHTML = '';
|
||||
if (!r) return;
|
||||
index = 0;
|
||||
|
||||
for (x of r.choices) {
|
||||
console.log(x.id, 'choice saved');
|
||||
globalChoices[x.id] = x;
|
||||
|
||||
var caption = r.defaultChoiceIndex == index ? '[' + x.text + ']' : x.text;
|
||||
addItem(ul, caption, 'javascript:choice("' +
|
||||
(x.segmentId ? x.segmentId : (x.sg ? x.sg : x.id)) + '", "' + x.text + '", "' + x.id + '")');
|
||||
index++;
|
||||
}
|
||||
|
||||
document.getElementById("choiceCaption").innerHTML = choicePoints[r.id].description;
|
||||
}
|
||||
|
||||
|
||||
function updateProgressBar(ms, r) {
|
||||
var p = 0;
|
||||
|
||||
if (r && ms > r.startMs && ms < r.endMs) {
|
||||
p = 100 - Math.floor((ms - r.startMs) * 100 / (r.endMs - r.startMs));
|
||||
}
|
||||
|
||||
document.getElementById("progress").style.width = p + '%';
|
||||
}
|
||||
|
||||
var timerId = 0;
|
||||
|
||||
var switchFrom = null;
|
||||
var switchTo = null;
|
||||
|
||||
function ontimeout(nextSegment) {
|
||||
console.log('ontimeout', nextSegment);
|
||||
|
||||
if (switchFrom != currentSegment || switchTo != nextSegment) {
|
||||
playSegment(nextSegment);
|
||||
}
|
||||
|
||||
switchFrom = currentSegment;
|
||||
switchTo = nextSegment;
|
||||
}
|
||||
|
||||
function ontimeupdate(evt) {
|
||||
var ms = getCurrentMs();
|
||||
|
||||
var segmentId = getSegmentId(ms);
|
||||
|
||||
// ontimeupdate resolution is about a second, better use timer
|
||||
clearTimeout(timerId);
|
||||
if (segmentId && nextSegment && nextSegment != segmentId) {
|
||||
var timeLeft = SegmentMap.segments[segmentId].endTimeMs - ms;
|
||||
timerId = setTimeout(ontimeout, timeLeft, nextSegment);
|
||||
}
|
||||
|
||||
if (currentSegment != segmentId) {
|
||||
console.log('ontimeupdate', currentSegment, segmentId, ms, msToString(ms));
|
||||
currentSegment = segmentId;
|
||||
addZones(segmentId);
|
||||
currentMoment = null;
|
||||
addChoices(0);
|
||||
}
|
||||
|
||||
var r = getMoment(ms);
|
||||
if (r && momentSelected != r.id) {
|
||||
updateProgressBar(ms, r);
|
||||
if (currentMoment != r.id) {
|
||||
currentMoment = r.id;
|
||||
console.log('interaction', currentMoment);
|
||||
addChoices(r);
|
||||
}
|
||||
} else {
|
||||
currentMoment = null;
|
||||
addChoices(0);
|
||||
updateProgressBar(0);
|
||||
}
|
||||
}
|
||||
|
||||
function jumpForward(ms) {
|
||||
var ms = getCurrentMs();
|
||||
var segmentId = getSegmentId(ms);
|
||||
var v = segmentMap.segments[segmentId];
|
||||
|
||||
var interactionMs = 0;
|
||||
if (v && v.ui && v.ui.interactionZones) {
|
||||
for (z of v.ui.interactionZones) {
|
||||
var startMs = z[0];
|
||||
var stopMs = z[1];
|
||||
if (ms < startMs)
|
||||
interactionMs = startMs;
|
||||
}
|
||||
}
|
||||
|
||||
if (interactionMs) {
|
||||
seek(interactionMs);
|
||||
} else {
|
||||
playSegment(nextSegment);
|
||||
}
|
||||
}
|
||||
|
||||
function jumpBack() {
|
||||
var ms = getCurrentMs();
|
||||
var segmentId = getSegmentId(ms);
|
||||
var startMs = getSegmentMs(segmentId);
|
||||
var previousSegment = getSegmentId(startMs - 1000);
|
||||
console.log('jumpBack from-to', segmentId, previousSegment);
|
||||
playSegment(previousSegment);
|
||||
}
|
||||
|
||||
function toggleFullScreen() {
|
||||
console.log('toggleFullScreen');
|
||||
var c = document.getElementById("c");
|
||||
if (!document.fullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement) {
|
||||
if (c.requestFullscreen) {
|
||||
c.requestFullscreen();
|
||||
} else if (c.msRequestFullscreen) {
|
||||
c.msRequestFullscreen();
|
||||
} else if (c.mozRequestFullScreen) {
|
||||
c.mozRequestFullScreen();
|
||||
} else if (c.webkitRequestFullscreen) {
|
||||
c.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
|
||||
}
|
||||
} else {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
} else if (document.msExitFullscreen) {
|
||||
document.msExitFullscreen();
|
||||
} else if (document.mozCancelFullScreen) {
|
||||
document.mozCancelFullScreen();
|
||||
} else if (document.webkitExitFullscreen) {
|
||||
document.webkitExitFullscreen();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function togglePlayPause() {
|
||||
var v = document.getElementById("video");
|
||||
if (v.paused) v.play();
|
||||
else v.pause();
|
||||
}
|
||||
|
||||
function onload() {
|
||||
var video_selector = document.getElementById("video");
|
||||
var file_selector = document.getElementById("file-selector");
|
||||
if (video_selector.getAttribute("src") == '') {
|
||||
console.log('no video')
|
||||
file_selector.style.display = 'table';
|
||||
document.getElementById("wrapper-video").style.display = 'none';
|
||||
}
|
||||
document.getElementById('fileinput').addEventListener('change', function () {
|
||||
var file = this.files[0];
|
||||
// This code is only for demo ...
|
||||
var fileUrl = URL.createObjectURL(file)
|
||||
console.log(file);
|
||||
console.log(fileUrl)
|
||||
video_selector.src = fileUrl;
|
||||
file_selector.style.display = 'none';
|
||||
document.getElementById("wrapper-video").style.display = 'block';
|
||||
}, false);
|
||||
|
||||
video_selector.ontimeupdate = ontimeupdate;
|
||||
|
||||
var c = document.getElementById("c");
|
||||
c.ondblclick = toggleFullScreen;
|
||||
c.onclick = function () {
|
||||
// can't togglePlayPause here, choice buttons stop the video
|
||||
// should use preventdefault or something
|
||||
// use spacebar for now
|
||||
// mind that autoplay is disabled in latest chrome, so play after click
|
||||
document.getElementById("video").play();
|
||||
};
|
||||
|
||||
document.onkeypress = function (e) {
|
||||
if (e.code == 'KeyF')
|
||||
toggleFullScreen();
|
||||
if (e.code == 'KeyR')
|
||||
playSegment(0);
|
||||
if (e.code == 'Space')
|
||||
togglePlayPause();
|
||||
}
|
||||
|
||||
document.onkeydown = function (evt) {
|
||||
var v = document.getElementById("video");
|
||||
|
||||
if (evt.key == 'ArrowLeft') {
|
||||
jumpBack();
|
||||
}
|
||||
|
||||
if (evt.key == 'ArrowRight') {
|
||||
jumpForward();
|
||||
}
|
||||
}
|
||||
|
||||
if (location.hash) {
|
||||
var segmentId = location.hash.slice(1);
|
||||
playSegment(segmentId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function seek(ms) {
|
||||
clearTimeout(timerId);
|
||||
console.log('seek', ms);
|
||||
momentSelected = null;
|
||||
document.getElementById("video").currentTime = ms / 1000.0;
|
||||
}
|
||||
|
||||
function choice(choiceId, text, id) {
|
||||
var segmentId = findSegment(choiceId);
|
||||
console.log('choice', choiceId, 'nextSegment', segmentId);
|
||||
applyImpression(globalChoices[id]);
|
||||
setNextSegment(segmentId, text);
|
||||
momentSelected = choiceId;
|
||||
addChoices(0);
|
||||
}
|
||||
|
||||
function applyImpression(obj) {
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
impressionData = obj.impressionData;
|
||||
|
||||
if (impressionData && impressionData.type == 'userState') {
|
||||
for (const [variable, value] of Object.entries(impressionData.data.persistent)) {
|
||||
console.log('persistentState set', variable, '=', value);
|
||||
persistentState[variable] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function applyPlaybackImpression(segmentId) {
|
||||
let moments = momentsBySegment[segmentId];
|
||||
|
||||
if (!moments) {
|
||||
console.log('warning - no moments');
|
||||
return;
|
||||
}
|
||||
|
||||
for (moment of moments) {
|
||||
if (moment.type != 'notification:playbackImpression') {
|
||||
continue;
|
||||
}
|
||||
|
||||
applyImpression(moment);
|
||||
}
|
||||
}
|
||||
|
||||
function playSegment(segmentId) {
|
||||
clearTimeout(timerId);
|
||||
if (!segmentId || segmentId == "undefined")
|
||||
segmentId = '1A';
|
||||
console.log('playSegment', segmentId);
|
||||
applyPlaybackImpression(segmentId);
|
||||
location.hash = segmentId;
|
||||
document.title = 'Bandersnatch - Chapter ' + segmentId;
|
||||
var ms = getSegmentMs(segmentId);
|
||||
seek(ms);
|
||||
}
|
229
assets/styles.css
Normal file
229
assets/styles.css
Normal file
|
@ -0,0 +1,229 @@
|
|||
body {
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
|
||||
}
|
||||
|
||||
.main {
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
video {
|
||||
width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.controls {
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
ul {
|
||||
font: 20px sans-serif;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
justify-content: space-around;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
flex: 0 1 auto;
|
||||
list-style-type: none;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: #0403031f;
|
||||
display: table;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
width: 50%;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
li:first-child {
|
||||
background: #ffffff45;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#progress {
|
||||
background-color: #ff00007d;
|
||||
width: 0%;
|
||||
height: 29px;
|
||||
margin: auto;
|
||||
border-radius: 4px;
|
||||
position: relative;
|
||||
top: 0;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#choiceCaption,
|
||||
#interactionZones,
|
||||
#nextSegments,
|
||||
#nextSegment {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* comment to show links */
|
||||
a {
|
||||
color: #ffffffa6;
|
||||
text-decoration: none;
|
||||
text-shadow: 0px 0px 10px #000;
|
||||
animation: choices 3s forwards;
|
||||
font-size: 4em;
|
||||
/* display: block; */
|
||||
/* margin: 50%; */
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: white;
|
||||
}
|
||||
|
||||
a:active,
|
||||
a:focus {
|
||||
color: white;
|
||||
text-decoration: underline solid white
|
||||
}
|
||||
|
||||
@keyframes choices {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
video::cue {
|
||||
font: 60% sans-serif;
|
||||
color: white;
|
||||
background: none;
|
||||
text-shadow: 0px 0px 10px #000;
|
||||
}
|
||||
|
||||
#c {
|
||||
margin: auto;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#c:-webkit-full-screen {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
#c:-moz-full-screen {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
#c:-ms-fullscreen {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
#c:fullscreen {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
section[role="banner"] {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#wrapper-video {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#wrapper-video video {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
min-width: 50%;
|
||||
min-height: 50%;
|
||||
}
|
||||
|
||||
video::-webkit-media-controls-panel {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
#file-selector {
|
||||
display: none;
|
||||
background: #00000073;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
display: table;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.file-area {
|
||||
position: relative;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.file-area input[type=file] {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.file-area .file-dummy {
|
||||
width: 100%;
|
||||
padding: 50px 30px;
|
||||
border: 2px dashed #ccc;
|
||||
background-color: #fff;
|
||||
text-align: center;
|
||||
transition: background 0.3s ease-in-out;
|
||||
margin: 0 auto;
|
||||
width: 50%;
|
||||
height: 25%;
|
||||
font-size: 8em;
|
||||
padding: 9%;
|
||||
}
|
||||
|
||||
.file-area .file-dummy .success {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.file-area:hover .file-dummy {
|
||||
border: 2px dashed #1abc9c;
|
||||
}
|
||||
|
||||
.file-area input[type=file]:valid+.file-dummy {
|
||||
border-color: #1abc9c;
|
||||
}
|
||||
|
||||
.file-area input[type=file]:valid+.file-dummy .success {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.file-area input[type=file]:valid+.file-dummy .default {
|
||||
display: inline-block;
|
||||
}
|
49
index.html
Normal file
49
index.html
Normal file
|
@ -0,0 +1,49 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>Bandersnatch Interactive</title>
|
||||
<script src="assets/bandersnatch.js"></script>
|
||||
<script src="assets/SegmentMap.js"></script>
|
||||
<script src="assets/scripts.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="assets/styles.css">
|
||||
<link </head> <body onload=onload()>
|
||||
<div>
|
||||
<div id="c">
|
||||
<section role="banner">
|
||||
<div id="file-selector">
|
||||
<div class="file-area">
|
||||
<input id="fileinput" type="file">
|
||||
<div class="file-dummy">
|
||||
<span class="default">Select video file </span>
|
||||
<span class="success">Great, your file is selected</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div id="wrapper-video">
|
||||
<video id="video" src="">
|
||||
|
||||
</video>
|
||||
<div class="controls">
|
||||
<div id="choiceCaption"></div>
|
||||
<div id="progress"></div>
|
||||
<div class="buttons">
|
||||
<ul id="choices"></ul>
|
||||
<ul id="interactionZones"></ul>
|
||||
<ul id="nextSegments"></ul>
|
||||
<ul id="nextSegment"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue