1
Fork 0
lorchess.ru/_assets/vendor/pgn4web/video.html

548 lines
18 KiB
HTML

<!DOCTYPE HTML>
<html>
<!--
pgn4web javascript chessboard
copyright (C) 2009-2013 Paolo Casaschi
see README file and http://pgn4web.casaschi.net
for credits, license and more details
-->
<head>
<title>pgn4web integration with HTML5 video</title>
<link rel="shortcut icon" href="pawn.ico" />
<style type="text/css">
html,
body {
margin: 0px;
padding: 0px;
}
body {
color: black;
background: white;
font-family: sans-serif;
}
a {
color: black;
text-decoration: none;
}
.boardTable {
height: 272px;
width: 272px;
box-shadow: 0px 0px 15px #663300;
}
.boardBox {
width: 272px;
text-align:left;
font-weight:bold;
text-shadow: 1px 1px 3px #C4C4C4
}
.videoBox {
box-shadow: 0px 0px 16px #663300;
}
.pieceImage {
height: 26px;
width: 26px;
}
.whiteSquare,
.blackSquare,
.highlightWhiteSquare,
.highlightBlackSquare {
width: 32px;
height: 32px;
border-style: solid;
border-width: 1px;
}
.whiteSquare,
.highlightWhiteSquare {
border-color: #FFCC99;
background: #FFCC99;
}
.blackSquare,
.highlightBlackSquare {
border-color: #CC9966;
background: #CC9966;
}
.highlightWhiteSquare,
.highlightBlackSquare {
border-style: inset;
border-color: #CC9966;
}
</style>
<script type="text/javascript" src="libs/swfobject/swfobject.js"></script>
<script src="pgn4web.js" type="text/javascript"></script>
</head>
<body>
<!-- paste your PGN below and make sure you dont specify an external source with SetPgnUrl() -->
<form style="display: none;"><textarea style="display: none;" id="pgnText">
</textarea></form>
<script type="text/javascript">
"use strict";
function gup(name) {
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
// commented below to match first occurrence (to avoid users overruling setting)
// regexS = regexS+"(?!.*"+regexS+")"; // matches the LAST occurrence
var regex = new RegExp( regexS, "i" );
var results = regex.exec( window.location.href );
if (results !== null) { return decodeURIComponent(results[1]); }
// allows for short version of the URL parameters, for instance sC matches squareColor
var compact_name = name.charAt(0);
for (var i=1; i<name.length; i++) {
if (name.charAt(i).match(/[A-Z]/)) { compact_name = compact_name + name.charAt(i).toLowerCase(); }
}
name = compact_name;
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
regexS = "[\\?&]"+name+"=([^&#]*)";
// commented below to match first occurrence (to avoid users overruling setting)
// regexS = regexS+"(?!.*"+regexS+")"; // matches the LAST occurrence
regex = new RegExp( regexS, "i" );
results = regex.exec( window.location.href );
if (results !== null) { return decodeURIComponent(results[1]); }
return "";
}
SetCommentsIntoMoveText(false);
var pgnFile_default = "";
var videoUrl_default = "";
var youtubeVideoid_default = "";
var videoWidth_default = "480";
var videoHeight_default = "270";
function print_default(value) { return value ? value : "null"; }
var videoHelp = ((gup("help") == "true") || (gup("help") == "t"));
if (videoHelp) {
document.write("<PRE>");
document.write("pgn4web video.html URL parameters:\n");
document.write("\n");
document.write(" - pgnData = PGN URL to load as PGN data source, overrides youtubeVideoid; default " + print_default(pgnFile_default) + "\n");
document.write(" - videoUrl = video URL to load as video source, overrides youtubeVideoid; default " + print_default(videoUrl_default) + "\n");
document.write(" - youtubeVideoid = youtube video id to use as video source and/or as PGN data source (PGN data expected in the youtube video description); default " + print_default(youtubeVideoid_default) + "\n");
document.write("\n");
document.write(" - videoWidth = video width; default " + print_default(videoWidth_default) + "\n");
document.write(" - videoHeigth = video height; default " + print_default(videoHeight_default) + "\n");
document.write(" - videoAutoplay = if set true video autoplays at page load; default true\n");
document.write(" - videoLoop = if set true video loops; default false\n");
document.write(" - horizontalLayout = if set true the chessboard is next to the video, otherwise underneath; default true\n");
document.write("\n");
document.write(" - setupVideotimes = if set true, setup special mode to add video times info to the PGN data; default false\n");
document.write(" - testVideotimes = if set true, detects missing/wrong video times info in the PGN data; default false\n");
document.write(" - ignoreVideotimes = if set true, video times info is ignored; default false\n");
document.write("\n");
document.write(" - help = true\n");
document.write("\n");
document.write("Either the pgnData or the youtubeVideoid URL parameter is required as PGN data source\n");
document.write("Either the videoUrl or the youtubeVideoid URL parameter is required as video source\n");
document.write("\n");
document.write("URL parameters can be shortened: for example pgnData => pd, videoUrl => vu, youtubeVideoid => yv\n");
document.write("Also supplied textual values can be shortened: true => t, false => f\n");
document.write("\n");
document.write("</PRE>\n<HR>\n");
}
var horizontalLayout = ((gup("horizontalLayout") != "false") && (gup("hl") != "f"));
</script>
<center>
<table>
<script type="text/javascript">
"use strict";
if (!horizontalLayout) { document.write('<tr><td height="20"></td></tr>'); }
</script>
<tr><td>
<div id="videoBox" class="videoBox">
<div id="videodiv" style="text-align:center; font-style:italic;">
<video id="videoPlayer" controls="controls"><br/><br/>warning: HTML5 video support required</video>
</div>
</div>
</td>
<script type="text/javascript">
"use strict";
if (horizontalLayout) { document.write('<td width="20"></td>'); }
else { document.write('</tr><tr><td height="20"></td></tr><tr>'); }
</script>
<td align="center">
<div class="boardBox">
<div style="margin-bottom:1em;">
<div id="GameBlackClock" style="float:right;"></div>
<span id="GameBlack"></span>&nbsp;
</div>
<div id="GameBoard"><div style="width:272px; height:272px;"></div></div>
<div style="margin-top:1em;">
<div id="GameWhiteClock" style="float:right;"></div>
<span id="GameWhite"></span>&nbsp;
</div>
</div>
</td></tr></table>
<form id="setupBox" style="display:none;">
<table style="width:100%;"><tr valign="bottom"><td>
<div id="videoTimeInfo" style="font-weight:bold; font-size:small; margin-top:2em;"></div>
</td><td>
</td><td>
<div style="text-align:right; margin-top:2em;">
<span style="font-weight:bold; font-size:small; margin-right:0.5em; margin-left:0.5em;">time correction:</span>
<input id="timeCorrection" type="text" value="-0.3" style="width:6em;" title="time correction in seconds to be added to the captured video time, usually negative to take into account the lag between seeing a move and clicking the capture button, default -0.3" />
</div>
</td></tr><tr valign="bottom"><td style="width:30%">
<div style="font-weight:bold; font-size:small; margin-right:0.5em;">next move: <span id="GameNextMove"></span></div>
</td><td style="width:40%">
<input id="captureButton" type="button" value="capture videotime into the PGN data" disabled="1" onclick="getVideotime();" style="width:100%;" />
</td><td style="width:30%">
<input id="togglevideoButton" type="button" value="play/pause video" disabled="1" onclick="toggleVideoPlayPause();" style="width:100%;" />
</td></tr><tr><td colspan="3">
<textarea id="setupOutput" style="height:200px; width:100%; padding: 10px; border-color: lightgray;">
% you can add video times information to the PGN file by pressing the capture button
% each time a new game starts, including the first game, and each time a move is made;
</textarea>
</td></tr></table>
</form>
</center>
<script type="text/javascript">
"use strict";
// accepts pgnData as alias for pgnFile for consistency with board.html
var pgnFile;
if ((pgnFile = gup("pgnData")) === "") {
if ((pgnFile = gup("pgnFile")) === "") {
pgnFile = pgnFile_default;
}
}
var videoUrl = gup("videoUrl");
if (videoUrl === "") { videoUrl = videoUrl_default; }
var youtubeVideoid = gup("youtubeVideoid");
if (youtubeVideoid === "") { youtubeVideoid = youtubeVideoid_default; }
var videoWidth = gup("videoWidth");
if (videoWidth === "") { videoWidth = videoWidth_default; }
var videoHeight = gup("videoHeight");
if (videoHeight === "") { videoHeight = videoHeight_default; }
var videoAutoplay = ((gup("videoAutoplay") != "false") && (gup("videoAutoplay") != "f"));
var videoLoop = ((gup("videoLoop") == "true") || (gup("videoLoop") == "t"));
var ignoreVideotimes = ((gup("ignoreVideotimes") == "true") || (gup("ignoreVideotimes") == "t"));
var testVideotimes = ((gup("testVideotimes") == "true") || (gup("testVideotimes") == "t"));
var setupVideotimes = ((gup("setupVideotimes") == "true") || (gup("setupVideotimes") == "t"));
document.getElementById("setupBox").style.display = setupVideotimes ? "inline" : "none";
var paramError = "";
var theObj;
if (theObj = document.getElementById("videoBox")) {
if (videoWidth) { theObj.style.width = videoWidth + "px"; }
if (videoHeight) { theObj.style.height = videoHeight + "px"; }
}
if (videoUrl) {
if (theObj = document.getElementById("videoPlayer")) {
theObj.src = videoUrl;
if (videoWidth) { theObj.width = videoWidth; }
if (videoHeight) { theObj.height = videoHeight; }
if (videoAutoplay) { theObj.autoplay = "autoplay"; }
if (videoLoop) { theObj.loop = "loop"; }
}
} else if (youtubeVideoid) {
document.title = "pgn4web integration with youtube";
document.getElementById("videodiv").innerHTML = "<br/><br/>warning: flash video support required";
var expressInstall = null;
var flashvars = { };
var params = { allowScriptAccess: "always", allowFullScreen: "true" };
var atts = { id: "videoPlayer" };
swfobject.embedSWF("http://www.youtube.com/e/" + youtubeVideoid + "?enablejsapi=1&autohide=1" + (videoAutoplay ? "&autoplay=1" : "&autoplay=0") + "&disablekb=1&fs=1" + (videoLoop ? "&loop=1&playlist=" + youtubeVideoid : "&loop=0") + "&rel=0&showinfo=0", "videodiv", videoWidth, videoHeight, "8", expressInstall, flashvars, params, atts);
} else {
paramError += "error: videoUrl or youtubeVideoid URL parameter required as video source\n\n";
}
function youtubeFeedCallback(res) {
if (res && res["data"] && res["data"]["description"]) {
document.getElementById("pgnText").value = res["data"]["description"];
}
gotYuotubeDetails = true;
new_start_pgn4web();
}
function getYoutubeDetails(videoid) {
var headID = document.getElementsByTagName("head")[0];
var newScript = document.createElement("script");
newScript.type = "text/javascript";
newScript.src = "http://gdata.youtube.com/feeds/api/videos/" + videoid + "?v=2&alt=jsonc&callback=youtubeFeedCallback";
headID.appendChild(newScript);
}
if (pgnFile) {
SetPgnUrl(pgnFile);
} else if (youtubeVideoid) {
getYoutubeDetails(youtubeVideoid);
} else {
paramError += "error: pgnData or youtubeVideoid URL parameter required as PGN data source\n\n";
}
if (paramError && (!videoHelp)) {
if (confirm("pgn4web video.html\n\n" + paramError + "click OK for more help")) {
window.location.search += (window.location.search ? "&" : "?") + "help=true";
}
}
SetImagePath ("images/alpha/26");
SetImageType("png");
SetHighlightOption(true);
SetShortcutKeysEnabled(ignoreVideotimes);
if (!ignoreVideotimes) {
clearShortcutSquares("A", "123456");
clearShortcutSquares("BCDEFGH", "1234567");
}
var videotimeForGame = new Array();
function getVideotimeForGame() {
videotimeForGame = new Array();
for (var thisGame=0; thisGame<numberOfGames; thisGame++) {
videotimeForGame[thisGame] = parseFloat(customPgnHeaderTag("VideoTime", null, thisGame));
if (!videotimeForGame[thisGame]) { videotimeForGame[thisGame] = 0; }
}
}
var videotimeAtPly = new Array();
function getVideotimeAtPly() {
videotimeAtPly = new Array();
for (var thisPly=StartPly; thisPly<=StartPly+PlyNumber; thisPly++) {
videotimeAtPly[thisPly] = parseFloat(customPgnCommentTag("vt", null, thisPly));
if (!videotimeAtPly[thisPly]) { videotimeAtPly[thisPly] = 0; }
}
}
function customFunctionOnPgnGameLoad() {
if (setupVideotimes) {
document.getElementById("togglevideoButton").disabled = 0;
document.getElementById("captureButton").disabled = 0;
document.getElementById("captureButton").focus();
}
getVideotimeAtPly();
}
function runTestVidoetimes() {
for (var thisGame=0; thisGame<numberOfGames; thisGame++) {
if ((thisGame>0) && (videotimeForGame[thisGame] <= videotimeForGame[thisGame-1])) {
alert("warning: " + pgnFile + " missing/wrong VideoTime header tag for game " + (thisGame+1));
return false;
}
Init(thisGame);
for (var thisPly=StartPly; thisPly<=StartPly+PlyNumber; thisPly++) {
if ((thisPly>StartPly) && (videotimeAtPly[thisPly] <= videotimeAtPly[thisPly-1])) {
alert("warning: " + pgnFile + " missing/wrong %vt comment at ply " + thisPly + " of game " + (thisGame+1));
return false;
}
}
}
alert("info: " + pgnFile + " video time values looks ok");
return true;
}
var syncInterval = 456; // milliseconds
var syncTimer = null;
function customFunctionOnPgnTextLoad() {
getVideotimeForGame();
if (testVideotimes) { runTestVidoetimes(); }
if (syncTimer) { clearTimeout(syncTimer); }
if (!ignoreVideotimes) { syncTimer = setTimeout("syncBoard();", syncInterval); }
}
// assumes arrayValues ordered
function findIndexInOrderedArray(target, arrayValues, arrayFirst, arrayLast, previous) {
if (previous < arrayFirst) { previous = arrayFirst; }
if (previous > arrayLast ) { previous = arrayLast ; }
var found = previous;
if ((previous > arrayFirst) && (target < arrayValues[previous])) {
for (var index=previous; (index>arrayFirst) && (target < arrayValues[index]); index--) {}
found = index;
} else if ((previous < arrayLast) && (target > arrayValues[previous+1])) {
for (index=previous; (index<arrayLast) && (target > arrayValues[index+1]); index++) {}
found = index;
}
return found;
}
function videoPlayerCurrentTime() {
var videoPlayer = document.getElementById("videoPlayer");
var videoCurrentTime = 0;
if (videoPlayer && videoPlayer.currentTime) { videoCurrentTime = videoPlayer.currentTime; }
else if (videoPlayer && videoPlayer.getCurrentTime) { videoCurrentTime = videoPlayer.getCurrentTime(); }
document.getElementById("videoTimeInfo").innerHTML = "video time: " + (Math.round(videoCurrentTime * 1000) / 1000);
return videoCurrentTime;
}
function syncBoard() {
if (syncTimer) { clearTimeout(syncTimer); }
var videoCurrentTime = videoPlayerCurrentTime();
if (!setupVideotimes) {
var foundGame = findIndexInOrderedArray(videoCurrentTime, videotimeForGame, 0, numberOfGames-1, currentGame);
if (foundGame !== currentGame) { Init(foundGame); }
var foundPly = findIndexInOrderedArray(videoCurrentTime, videotimeAtPly, StartPly, StartPly+PlyNumber, CurrentPly);
if (foundPly != CurrentPly) { GoToMove(foundPly); }
}
syncTimer = setTimeout("syncBoard();", syncInterval);
}
var setupOutputBox = document.getElementById("setupOutput");
function writeSetupOutput(text) {
if (setupOutputBox) { setupOutputBox.value += text; }
setupOutputBox.scrollTop = setupOutputBox.scrollHeight;
}
function newGameHeader(thisGame, videotime) {
var newHeader = pgnHeader[thisGame] ? pgnHeader[thisGame] : "";
newHeader = newHeader.replace(/\[\s*VideoTime\s*"([^"]*)"\s*\]\s*/g, "");
newHeader = newHeader.replace(/(^\s*|\s*$)/g, "");
newHeader += "\n[VideoTime \"" + videotime + "\"]";
return newHeader;
}
var startedVideotimes = false;
var endedVideotimes = false;
function getVideotime() {
if (!setupVideotimes || endedVideotimes) { return; }
var storedVideotime = videoPlayerCurrentTime();
var timeCorrection = parseFloat(document.getElementById("timeCorrection").value);
if (timeCorrection) { storedVideotime += timeCorrection; }
storedVideotime = Math.round(storedVideotime * 10) / 10;
if (!startedVideotimes) {
writeSetupOutput("\n" + newGameHeader(currentGame, storedVideotime) + "\n\n");
startedVideotimes = true;
return;
}
if (CurrentPly === StartPly+PlyNumber) {
if (currentGame+1 < numberOfGames) {
Init(currentGame + 1);
writeSetupOutput("\n" + newGameHeader(currentGame, storedVideotime) + "\n\n");
}
} else {
GoToMove(CurrentPly + 1);
var moreText = "";
moreText += Math.ceil(CurrentPly/2) + ".";
if (!(CurrentPly % 2)) { moreText += ".."; }
moreText += " " + Moves[CurrentPly-1] + " {[%vt " + storedVideotime + "]";
var comment = MoveComments[CurrentPly].replace(/\s*\[%vt [\.0-9]*\]\s*/g, "");
if (comment) { moreText += " " + comment.replace(/[{}]/g, ""); }
moreText += "}\n";
writeSetupOutput(moreText);
}
if (CurrentPly === StartPly+PlyNumber) {
if (gameResult[currentGame]) { writeSetupOutput(gameResult[currentGame] + "\n"); }
if (currentGame+1 === numberOfGames) {
writeSetupOutput("\n\n% end of games and moves");
endedVideotimes = true;
}
}
}
function customShortcutKey_Shift_0() {
getVideotime();
}
function toggleVideoPlayPause() {
var videoPlayer = document.getElementById("videoPlayer");
if (videoPlayer && videoPlayer.playVideo) {
if (videoPlayer.getPlayerState() == 2) {
videoPlayer.playVideo();
} else {
videoPlayer.pauseVideo();
}
} else if (videoPlayer && videoPlayer.play) {
if (videoPlayer.paused) { videoPlayer.play(); }
else { videoPlayer.pause(); }
}
}
var gotOnload = false;
var gotYuotubeDetails = false;
function pgn4web_onload(e) {
gotOnload = true;
new_start_pgn4web();
}
function new_start_pgn4web() {
if (youtubeVideoid && !pgnFile && (!gotYuotubeDetails || !gotOnload)) { return; }
start_pgn4web();
}
</script>
</body>
</html>