1<!DOCTYPE HTML>
2<html>
3
4<!--
5  pgn4web javascript chessboard
6  copyright (C) 2009-2015 Paolo Casaschi
7  see README file and http://pgn4web.casaschi.net
8  for credits, license and more details
9-->
10
11<head>
12
13<title>chess games</title>
14
15<!-- use viewport settings when body.onresize adapts the chessboard to the available space -->
16<meta name="viewport" content="initial-scale=1, maximum-scale=1">
17
18<!-- AppCheck: meta -->
19
20<link rel="icon" sizes="16x16" href="pawn.ico" />
21
22<style type="text/css">
23
24</style>
25
26<style id="dynamicStyle" type="text/css"></style>
27
28<!-- AppCheck: fonts -->
29
30<script src="pgn4web.js" type="text/javascript"></script>
31<script src="engine.js" type="text/javascript"></script>
32
33<script src="fide-lookup.js" type="text/javascript"></script>
34
35<script type="text/javascript">
36"use strict";
37
38SetHighlightOption(true);
39SetGameSelectorOptions("&middot;&middot;&middot;", true, 30, 0, 8, 15, 15, 3, 0); // (head, num, chEvent, chSite, chRound, chWhite, chBlack, chResult, chDate);
40SetAutoplayDelay(2000); // milliseconds
41SetAutostartAutoplay(false);
42SetAutoplayNextGame(false);
43SetShortcutKeysEnabled(true);
44
45var pgnData_default = "";
46var refreshMinutes_default = 0;
47var initialGame_default = "first";
48var pieceBaseSize_default = 96;
49var pieceFont_default = "uscf";
50var theme = new Array();         //        font    background  light     dark    highlight
51theme[theme.length] = new Array("black",  "FFFFFF", "000000", "999999", "777777", "000000");
52theme[theme.length] = new Array("blue",   "000000", "80B0E0", "E6EDF3", "A0BED8", "596978");
53theme[theme.length] = new Array("braun",  "221100", "FFCE9E", "FFCE9E", "D18B47", "663300");
54theme[theme.length] = new Array("dark",   "FFFFFF", "000000", "FFCE9E", "D18B47", "663300");
55theme[theme.length] = new Array("gray",   "666666", "F4F4F4", "F4F4F4", "E0E0E0", "AAAAAA");
56theme[theme.length] = new Array("green",  "333333", "EFF4EC", "EFF4EC", "C6CEC3", "999999");
57theme[theme.length] = new Array("light",  "000000", "FFFFFF", "FFCE9E", "D18B47", "663300");
58theme[theme.length] = new Array("pink",   "615F54", "EDE8D5", "EDE8D5", "CFCBB3", "F8CCA0");
59theme[theme.length] = new Array("white",  "000000", "FFFFFF", "FFFFFF", "E4E4E4", "000000");
60theme[theme.length] = new Array("wood",   "663300", "FFFFFF", "FFCC99", "CC9966", "663300");
61theme[theme.length] = new Array("yellow", "54110C", "F2D798", "F2D798", "C9AD6F", "54110C");
62var colorTheme_indexDefault = 2;
63var colorThemeOptions = "";
64for (var ii = 0; ii < theme.length; ii++) { colorThemeOptions += "'" + theme[ii][0] + "' | "; }
65colorThemeOptions += "'random' ";
66
67var fontSizeRatio_default = 0.8;
68var pieceSizeRatio_default = 0.8;
69var sizeRatio_min = 0.3;
70var sizeRatio_max = 1;
71var framePaddingRatio_default = 0;
72
73var thisParamString = window.location.search;
74
75var thisRegExp;
76
77thisRegExp = /(&|\?)(help|h)=(true|t)(&|$)/i;
78if (thisParamString.match(thisRegExp) !== null) {
79  document.write("<pre style='font-size: smaller;'>pgn4web dynamic-frame.html parameters" + "\n" +
80    " - pgnData = file.pgn (no default)" + "\n" +
81    " - initialGame = initial game (default " + initialGame_default + ")" + "\n" +
82    " - live = if set true enables live broadcast with default values (default false)" + "\n" +
83    " - refreshMinutes = live broadcast delay (default " + refreshMinutes_default + ")" + "\n" +
84    " - refreshDemo = if set true sets live demo mode (default false)" + "\n" +
85//    " - pieceBaseSize = size of baseline piece bitmap (default " + pieceBaseSize_default + ")" + "\n" +
86    " - pieceFont = 'alpha' | 'merida' | 'uscf' | 'random' (default " + pieceFont_default + ")" + "\n" +
87    " - colorTheme = " + colorThemeOptions + "(default '" + theme[colorTheme_indexDefault][0] + "')" + "\n" +
88    " - fontColorHex = font color hex code, like FF0000 (default according to the selected color theme)" + "\n" +
89    " - backgroundColorHex = page background color hex code, like FF0000 (default according to the selected color theme)" + "\n" +
90    " - lightColorHex = light square color hex code, like FF0000 (default according to the selected color theme)" + "\n" +
91    " - darkColorHex = dark square color hex code, like FF0000 (default according to the selected color theme)" + "\n" +
92    " - highlightColorHex = highlight square color hex code, like FF0000, or 'transparent' for no highlight (default according to the selected color theme)" + "\n" +
93    " - showColorFlag = if set true shows a color flag for the side to move (default false)" + "\n" +
94    " - showEco = if set true shows the ECO code if available (default false)" + "\n" +
95//    " - fontSizeRatio = font size ratio, from " + sizeRatio_min + " to " + sizeRatio_max + " (default " + fontSizeRatio_default + ")" + "\n" +
96//    " - pieceSizeRatio = piece size ratio, from " + sizeRatio_min + " to " + sizeRatio_max + " (default " + pieceSizeRatio_default + ")" + "\n" +
97//    " - framePaddingRatio = frame padding as a square ratio (default " + framePaddingRatio_default + ")" + "\n" +
98//    " - horizontalCentered = if set true centers vertically the chessboard when in horizontal layout (default false)" + "\n" +
99    " - bare = if set true shows chessboard only (default false)" + "\n" +
100//    " - engineWinPrepareIdle = if set true preloads the analysis board with an empty board; use only for embedded analysis boards
101//    " - debug = true | false (default false)" + "\n" +
102    " - help = true" + "\n" +
103    "</pre>");
104}
105
106// undocumented feature
107thisRegExp = /(&|\?)(engineWinPrepareIdle|ewpi)=(true|t)(&|$)/i;
108var engineWinPrepareIdle = (thisParamString.match(thisRegExp) !== null);
109
110// undocumented feature
111thisRegExp = /(&|\?)(debug|d)=(true|t)(&|$)/i;
112var debug = (thisParamString.match(thisRegExp) !== null);
113var dynamicFrameDebugString = "";
114
115var liveString = "";
116thisRegExp = /(&|\?)(live|l)=([^&]*)(&|$)/i;
117if (thisParamString.match(thisRegExp) !== null) {
118  liveString = unescape(thisParamString.match(thisRegExp)[3]);
119}
120if ((liveString == "true") || (liveString == "t")) {
121  refreshMinutes_default = 1;
122}
123
124var alertFlag = false;
125var demoFlag = false;
126thisRegExp = /(&|\?)(refreshDemo|rd)=([^&]*)(&|$)/i;
127if (thisParamString.match(thisRegExp) !== null) {
128  var refreshDemo = unescape(thisParamString.match(thisRegExp)[3]);
129  if ((refreshDemo == "true") || (refreshDemo == "t")) { alertFlag = demoFlag = true; }
130}
131
132var refreshMinutes = refreshMinutes_default;
133var stepFlag = true;
134thisRegExp = /(&|\?)(refreshMinutes|rm)=([^&]*)(&|$)/i;
135if (thisParamString.match(thisRegExp) !== null) {
136  refreshMinutes = parseFloat(unescape(thisParamString.match(thisRegExp)[3]));
137  if (isNaN(refreshMinutes)) { refreshMinutes = refreshMinutes_default; }
138  if (refreshMinutes <= 0) { refreshMinutes = refreshMinutes_default; }
139}
140if (refreshMinutes) {
141  pgnData_default = "live/live.pgn";
142  initialGame_default = "\\[\\s*Result\\s*\"\\*\"\\s*\\]";
143}
144
145SetInitialHalfmove(refreshMinutes ? "end" : "start", true);
146
147SetLiveBroadcast(refreshMinutes, alertFlag, demoFlag, stepFlag);
148
149var pgnData = pgnData_default;
150thisRegExp = /(&|\?)(pgnData|pd)=([^&]*)(&|$)/i;
151if (thisParamString.match(thisRegExp) !== null) {
152  pgnData = unescape(thisParamString.match(thisRegExp)[3]);
153}
154SetPgnUrl(pgnData);
155
156var iniGame = initialGame_default;
157thisRegExp = /(&|\?)(initialGame|ig)=([^&]*)(&|$)/i;
158if (thisParamString.match(thisRegExp) !== null) {
159  iniGame = unescape(thisParamString.match(thisRegExp)[3]);
160}
161SetInitialGame(iniGame);
162
163// undocumented feature
164var allowedPieceBaseSize = new Array(20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 52, 56, 60, 64, 72, 80, 88, 96, 112, 128, 144, 300);
165var pieceBaseSize = pieceBaseSize_default;
166thisRegExp = /(&|\?)(pieceBaseSize|pbs)=([^&]*)(&|$)/i;
167if (thisParamString.match(thisRegExp) !== null) {
168  var pieceBaseSize_input = unescape(thisParamString.match(thisRegExp)[3]);
169  pieceBaseSize = parseInt(pieceBaseSize_input, 10);
170  var validPieceBaseSize = false;
171  for (var pieceBaseIndex in allowedPieceBaseSize) {
172    if (pieceBaseSize === allowedPieceBaseSize[pieceBaseIndex]) {
173      validPieceBaseSize = true;
174      break;
175    }
176  }
177  if (!validPieceBaseSize) {
178    myAlert("warning: invalid pieceBaseSize=" + pieceBaseSize_input + ", reverting to " + pieceBaseSize_default + " as default");
179    pieceBaseSize = pieceBaseSize_default;
180  }
181}
182
183var pieceFont = pieceFont_default;
184thisRegExp = /(&|\?)(pieceFont|pf)=([^&]*)(&|$)/i;
185if (thisParamString.match(thisRegExp) !== null) {
186  pieceFont = unescape(thisParamString.match(thisRegExp)[3]);
187}
188if (pieceFont == "a") { pieceFont = "alpha"; }
189if (pieceFont == "m") { pieceFont = "merida"; }
190if (pieceFont == "u") { pieceFont = "uscf"; }
191if (pieceFont == "i") { pieceFont = "igorsvg"; }
192if (pieceFont == "s") { pieceFont = "svgchess"; }
193if (pieceFont == "t") { pieceFont = "tilesvg"; }
194if ((pieceFont == "random") || (pieceFont == "r")) {
195  pieceFont = ["alpha", "merida", "uscf"][Math.floor(3 * Math.random())];
196}
197if ((pieceFont != "alpha") && (pieceFont != "merida") && (pieceFont != "uscf") && (pieceFont != "igorsvg") && (pieceFont != "svgchess") && (pieceFont != "tilesvg")) { pieceFont = pieceFont_default; }
198if ((pieceFont == "igorsvg") || (pieceFont == "svgchess") || (pieceFont == "tilesvg")) {
199  SetImagePath("images/" + pieceFont);
200  SetImageType("svg");
201} else {
202  SetImagePath("images/" + pieceFont + "/" + pieceBaseSize);
203  SetImageType("png");
204}
205
206var colorTheme = theme[colorTheme_indexDefault][0];
207thisRegExp = /(&|\?)(colorTheme|ct)=([\w]*|[\d]+)(&|$)/i;
208if (thisParamString.match(thisRegExp) !== null) {
209  colorTheme = unescape(thisParamString.match(thisRegExp)[3]);
210}
211var colorTheme_index = colorTheme_indexDefault;
212if (colorTheme == "random") { colorTheme_index = Math.floor(theme.length * Math.random()); }
213else if (colorTheme.match(/^\d+$/)) { colorTheme_index = parseInt(colorTheme, 10) % theme.length; colorTheme = theme[colorTheme_index][0]; }
214else { for (ii = 0; ii < theme.length; ii++) { if (theme[ii][0] === colorTheme) { colorTheme_index = ii; break; } } }
215
216var fontColorHex_default = theme[colorTheme_index][1];
217var backgroundColorHex_default = theme[colorTheme_index][2];
218var lightColorHex_default = theme[colorTheme_index][3];
219var darkColorHex_default = theme[colorTheme_index][4];
220var highlightColorHex_default = theme[colorTheme_index][5];
221
222var fontColorHex = fontColorHex_default;
223thisRegExp = /(&|\?)(fontColorHex|fch)=([A-F0-9]*)(&|$)/i;
224if (thisParamString.match(thisRegExp) !== null) {
225  fontColorHex = unescape(thisParamString.match(thisRegExp)[3]);
226}
227
228var backgroundColorHex = backgroundColorHex_default;
229thisRegExp = /(&|\?)(backgroundColorHex|bch)=([A-F0-9]*)(&|$)/i;
230if (thisParamString.match(thisRegExp) !== null) {
231  backgroundColorHex = unescape(thisParamString.match(thisRegExp)[3]);
232}
233
234var lightColorHex = lightColorHex_default;
235thisRegExp = /(&|\?)(lightColorHex|lch)=([A-F0-9]*)(&|$)/i;
236if (thisParamString.match(thisRegExp) !== null) {
237  lightColorHex = unescape(thisParamString.match(thisRegExp)[3]);
238}
239
240var darkColorHex = darkColorHex_default;
241thisRegExp = /(&|\?)(darkColorHex|dch)=([A-F0-9]*)(&|$)/i;
242if (thisParamString.match(thisRegExp) !== null) {
243  darkColorHex = unescape(thisParamString.match(thisRegExp)[3]);
244}
245
246var highlightColorHex = highlightColorHex_default;
247thisRegExp = /(&|\?)(highlightColorHex|hch)=(t|transparent)(&|$)/i;
248if (thisParamString.match(thisRegExp) !== null) {
249  highlightColorHex = "";
250  clearShortcutSquares("D", "7");
251} else {
252  thisRegExp = /(&|\?)(highlightColorHex|hch)=([A-F0-9]*)(&|$)/i;
253  if (thisParamString.match(thisRegExp) !== null) {
254    highlightColorHex = unescape(thisParamString.match(thisRegExp)[3]);
255  }
256}
257
258var showColorFlagString = "false";
259thisRegExp = /(&|\?)(showColorFlag|scf)=([^&]*)(&|$)/i;
260if (thisParamString.match(thisRegExp) !== null) {
261  showColorFlagString = unescape(thisParamString.match(thisRegExp)[3]);
262}
263var showColorFlag = ((showColorFlagString == "true") || (showColorFlagString == "t"));
264
265var showEcoString = "false";
266thisRegExp = /(&|\?)(showEco|se)=([^&]*)(&|$)/i;
267if (thisParamString.match(thisRegExp) !== null) {
268  showEcoString = unescape(thisParamString.match(thisRegExp)[3]);
269}
270var showEco = ((showEcoString == "true") || (showEcoString == "t"));
271
272// undocumented feature
273var fontSizeRatio = fontSizeRatio_default;
274thisRegExp = /(&|\?)(fontSizeRatio|fsr)=([0-9.]*)(&|$)/i;
275if (thisParamString.match(thisRegExp) !== null) {
276  fontSizeRatio = parseFloat(unescape(thisParamString.match(thisRegExp)[3]));
277  if (isNaN(fontSizeRatio) || (fontSizeRatio < sizeRatio_min) || (fontSizeRatio > sizeRatio_max)) { fontSizeRatio = fontSizeRatio_default; }
278}
279
280// undocumented feature
281var pieceSizeRatio = pieceSizeRatio_default;
282thisRegExp = /(&|\?)(pieceSizeRatio|psr)=([0-9.]*)(&|$)/i;
283if (thisParamString.match(thisRegExp) !== null) {
284  pieceSizeRatio = parseFloat(unescape(thisParamString.match(thisRegExp)[3]));
285  if (isNaN(pieceSizeRatio) || (pieceSizeRatio < sizeRatio_min) || (pieceSizeRatio > sizeRatio_max)) { pieceSizeRatio = pieceSizeRatio_default; }
286}
287
288// undocumented feature
289var framePaddingRatio = framePaddingRatio_default;
290thisRegExp = /(&|\?)(framePaddingRatio|fpr)=([0-9.]*)(&|$)/i;
291if (thisParamString.match(thisRegExp) !== null) {
292  framePaddingRatio = parseFloat(unescape(thisParamString.match(thisRegExp)[3]));
293  if (isNaN(framePaddingRatio)) { framePaddingRatio = framePaddingRatio_default; }
294}
295
296// undocumented feature
297var horizontalCenteredString = "";
298thisRegExp = /(&|\?)(horizontalCentered|hc)=([^&]*)(&|$)/i;
299if (thisParamString.match(thisRegExp) !== null) {
300  horizontalCenteredString = unescape(thisParamString.match(thisRegExp)[3]);
301}
302var horizontalCentered = ((horizontalCenteredString == "true") || (horizontalCenteredString == "t"));
303
304var bareString = "";
305thisRegExp = /(&|\?)(bare|b)=([^&]*)(&|$)/i;
306if (thisParamString.match(thisRegExp) !== null) {
307  bareString = unescape(thisParamString.match(thisRegExp)[3]);
308}
309var bare = ((bareString == "true") || (bareString == "t"));
310
311
312function myRulesLength(sheet) {
313  if (sheet.cssRules) { return sheet.cssRules.length; }
314  if (sheet.rules) { return sheet.rules.length; }
315  return null;
316}
317
318function myInsertRule(sheet, selector, declaration) {
319  if (sheet.insertRule) { sheet.insertRule(selector + "{ " + declaration + " }", myRulesLength(sheet)); }
320  else if (sheet.addRule) { sheet.addRule(selector, declaration); }
321}
322
323function myDeleteRule(sheet, index) {
324  if (sheet.deleteRule) { sheet.deleteRule(index); }
325  else if (sheet.removeRule) { sheet.removeRule(index); }
326}
327
328function toggleColorFlag() {
329  var theObj;
330  showColorFlag = !showColorFlag;
331  if (!showColorFlag) {
332    if (theObj = document.getElementById("whiteColorFlag")) { theObj.style.display = "none"; }
333    if (theObj = document.getElementById("whiteColorFlagFiller")) { theObj.style.display = "none"; }
334    if (theObj = document.getElementById("blackColorFlag")) { theObj.style.display = "none"; }
335    if (theObj = document.getElementById("blackColorFlagFiller")) { theObj.style.display = "none"; }
336  }
337  myOnResize();
338}
339
340function toggleShowEco() {
341  if (showEco = !showEco) {
342    fixHeaderItem("ECO", "GameECO", "ECO");
343    fixHeaderItem("ECO", "GameECOFiller", "ECO");
344  } else {
345    var theObj;
346    if (theObj = document.getElementById("GameECO")) { theObj.innerHTML = theObj.title = ""; }
347    if (theObj = document.getElementById("GameECOFiller")) { theObj.innerHTML = theObj.title = ""; }
348  }
349}
350
351var horizontalLayout;
352function myOnResize() {
353  var ww, wh;
354  if (window.innerWidth && window.innerHeight) { ww = window.innerWidth; wh = window.innerHeight; }
355  else if (document.documentElement && document.documentElement.clientWidth) { ww = document.documentElement.clientWidth; wh = document.documentElement.clientHeight; }
356  else if (document.body && document.body.clientWidth) { ww = document.body.clientWidth; wh = document.body.clientHeight; }
357  else { return false; }
358
359  var squareSize;
360  if (bare) {
361    horizontalLayout = (ww >= wh);
362    squareSize = Math.min(ww / (8 + 2 * framePaddingRatio), wh / (8 + 2 * framePaddingRatio));
363  } else {
364    var squareSize_H = Math.min(ww / (16 / 9), wh) / (8 + 2 * framePaddingRatio);
365    var squareSize_V = Math.min(ww, wh / (16 / 9)) / (8 + 2 * framePaddingRatio);
366    horizontalLayout = (squareSize_H >= squareSize_V);
367    squareSize = horizontalLayout ? squareSize_H : squareSize_V;
368  }
369  var framePadding = Math.floor(framePaddingRatio * squareSize);
370  squareSize = Math.floor(squareSize);
371  var bodyHeight = wh - 2 * framePadding;
372  var lineHeight;
373  if (horizontalLayout) {
374    lineHeight = Math.floor(squareSize * 8 / 16.5);
375  } else {
376    lineHeight = Math.floor(Math.min((wh - framePadding * 2 - squareSize * 8) / (11 + 6/2), squareSize * 8 / 16.5));
377  }
378  var fontSize = Math.floor(lineHeight * fontSizeRatio);
379  if (fontSize > lineHeight) { fontSize = lineHeight; }
380  var squareBorderWidth = Math.min(Math.ceil(squareSize / 50), 3);
381  var bareSquareSize = squareSize - 2 * squareBorderWidth;
382  var pieceSize = Math.floor(squareSize * pieceSizeRatio);
383  if (pieceSize > bareSquareSize) { pieceSize = Math.floor(bareSquareSize); }
384  var headerContainerWidth = horizontalLayout ? ww - 2 * framePadding - 9 * squareSize + Math.floor(3 * lineHeight / 4) : ww - 2 * framePadding;
385
386  if (document.styleSheets.length === 0) { return false; }
387
388  var sheet = document.styleSheets[0];
389  var oldRules = myRulesLength(sheet);
390
391  myInsertRule(sheet, "html", "overflow: hidden;");
392  myInsertRule(sheet, "body", "-webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; -o-user-select: none; user-select: none; -webkit-text-size-adjust: none; -moz-text-size-adjust: none; -ms-text-size-adjust: none; -o-text-size-adjust: none; text-size-adjust: none; -webkit-touch-callout: none; height: " + bodyHeight + "px; padding: 0px; margin: " + framePadding + "px; white-space: nowrap; overflow: hidden; color: #" + fontColorHex + "; background-color: #" + backgroundColorHex + "; font-family: sans-serif; line-height: " + lineHeight + "px; font-size: " + fontSize + "px;");
393  myInsertRule(sheet, "a", "text-decoration: none; color: #" + fontColorHex + ";");
394  if (bare) {
395    myInsertRule(sheet, ".boardTable", "margin-left: " + Math.floor((ww - 2 * framePadding - 8 * squareSize) / 2) + "px; margin-top: " + Math.floor((wh - 2 * framePadding - 8 * squareSize) / 2) + "px;");
396  } else {
397    if (horizontalLayout) { myInsertRule(sheet, ".boardTable", "float: left;" + (horizontalCentered ? " margin-top: " + Math.floor((wh - 2 * framePadding - 8 * squareSize) / 2) + "px;" : "")); }
398    else { myInsertRule(sheet, ".boardTable", "margin-left: " + Math.floor((ww - 2 * framePadding - 8 * squareSize) / 2) + "px;"); }
399  }
400  myInsertRule(sheet, ".pieceImage", "cursor: pointer; width: " + pieceSize + "px; height: " + pieceSize + "px;");
401  myInsertRule(sheet, ".whiteSquare", "width: " + bareSquareSize + "px; height: " + bareSquareSize + "px; border-style: solid; border-width: " + squareBorderWidth + "px;" + "background-color: #" + lightColorHex + "; border-color: #" + lightColorHex + ";");
402  myInsertRule(sheet, ".blackSquare", "width: " + bareSquareSize + "px; height: " + bareSquareSize + "px; border-style: solid; border-width: " + squareBorderWidth + "px;" + "background-color: #" + darkColorHex + "; border-color: #" + darkColorHex + ";");
403  myInsertRule(sheet, ".highlightWhiteSquare", "width: " + bareSquareSize + "px; height: " + bareSquareSize + "px; border-style: solid; border-width: " + squareBorderWidth + "px;" + "background-color: #" + lightColorHex + "; border-color: #" + (highlightColorHex ? highlightColorHex : lightColorHex) + ";");
404  myInsertRule(sheet, ".highlightBlackSquare", "width: " + bareSquareSize + "px; height: " + bareSquareSize + "px; border-style: solid; border-width: " + squareBorderWidth + "px;" + "background-color: #" + darkColorHex + "; border-color: #" + (highlightColorHex ? highlightColorHex : darkColorHex) + ";");
405  myInsertRule(sheet, ".headerContainer", "width: " + headerContainerWidth + "px; white-space: nowrap; overflow: hidden;" + (horizontalLayout ? " float: right; text-align: left;" + (horizontalCentered ? " margin-top: " + Math.floor((wh - 2 * framePadding - 8 * squareSize) / 2) + "px;" : "") : " text-align: center;"));
406  if (LiveBroadcastDelay > 0) {
407    myInsertRule(sheet, ".gameButtons", "display: none;");
408  } else {
409    myInsertRule(sheet, ".liveStatusLine", "display: none;");
410    if (horizontalLayout) { myInsertRule(sheet, ".gameButtons", "width: " + (headerContainerWidth - lineHeight) + "px; " + "text-align: left;"); }
411    var buttonCss = "cursor: pointer; margin: 0px; padding: 0px; width: " + Math.floor(3 * lineHeight / 2) + "px !important; height: " + lineHeight + "px; color: #" + fontColorHex + "; border-style: none; -moz-appearance: none; -webkit-appearance: none; background-color: #" + backgroundColorHex + "; font-family: sans-serif; line-height: " + lineHeight + "px; font-size: " + fontSize + "px;";
412    myInsertRule(sheet, ".buttonControl", buttonCss);
413    myInsertRule(sheet, ".buttonControlPlay", buttonCss);
414    myInsertRule(sheet, ".buttonControlStop", buttonCss);
415    myInsertRule(sheet, ".buttonControlSpace", "margin: 0px; padding: 0px; width: " + Math.floor(lineHeight / 4) + "px !important;");
416  }
417  myInsertRule(sheet, ".colorFlag", "height: " + Math.floor(0.45 * fontSize) + "px; width: " + Math.floor(0.45 * fontSize) + "px; border-width: 1px; border-color: #" + fontColorHex + "; border-style: solid; margin-bottom: " + Math.floor(0.1 * fontSize) + "px; margin-left: " + Math.floor(5 * lineHeight / 9) + "px; margin-right: " + Math.floor(5 * lineHeight / 9) + "px;");
418  myInsertRule(sheet, ".leftRightSpacing", "margin-left: " + Math.floor(lineHeight / 2) + "px; margin-right: " + Math.floor(lineHeight / 2) + "px;");
419  if (!horizontalLayout) {
420    var variableSpacerLineHeight = Math.floor(Math.min((wh - framePadding * 2 - squareSize * 8 - lineHeight * 11) / 6, lineHeight / 2));
421    var variableSpacerFontSize = Math.floor(variableSpacerLineHeight * 0.8);
422    myInsertRule(sheet, ".variableSpacer", "line-height: " + variableSpacerLineHeight + "px; font-size: " + variableSpacerFontSize + "px;");
423  }
424  myInsertRule(sheet, ".gameLiveStatusExtraInfoLeft", horizontalLayout ? "display: none;" : "");
425  myInsertRule(sheet, ".showGameListLink", "padding-right: " + squareSize + "px; padding-left: " + (horizontalLayout ? 0 : squareSize) + "px;");
426  var gameListFontHorizontalRatio = 28;
427  var gameListFontVerticalRatio = 24;
428  var gameListFontSize = Math.floor(Math.min((ww - framePadding * 2) / gameListFontHorizontalRatio, (wh - framePadding * 2) / gameListFontVerticalRatio));
429  gameListLineHeight = Math.floor(1.9 * gameListFontSize);
430  var gameListPadding = Math.floor(gameListLineHeight / 2);
431  gameListBodyHeight = gameListLineHeight * Math.floor((wh - 2 * framePadding - gameListLineHeight - 2.5 * gameListPadding) / gameListLineHeight);
432  gameListNumGames = Math.round(gameListBodyHeight / gameListLineHeight);
433  myInsertRule(sheet, ".gameList", "display: none; position: absolute; overflow: hidden; font-size: " + gameListFontSize + "px; line-height: " + gameListLineHeight + "px;");
434  myInsertRule(sheet, ".gameListHeader", "overflow: hidden; height: " + gameListLineHeight + "px; width: " + (ww - 2 * framePadding) + "px; padding-top: " + gameListPadding + "px; padding-bottom: " + gameListPadding + "px;");
435  myInsertRule(sheet, ".gameListHeaderItem", "display: inline-block; overflow: hidden; text-align: center; width: " + ((ww - 2 * framePadding) / 7) + "px;");
436  myInsertRule(sheet, ".gameListHeaderButton", "cursor: pointer; display: inline-block; min-width: " + ((ww - 2 * framePadding) / 14) + "px;");
437  myInsertRule(sheet, ".gameListBody", "height: " + gameListBodyHeight + "px; width: " + (ww - 2 * framePadding) + "px; overflow-x: hidden; overflow-y: auto; scrollbar-base-color: #" + backgroundColorHex + "; -webkit-overflow-scrolling: touch; overflow-scrolling: touch;");
438  myInsertRule(sheet, ".gameListBodyItems", "");
439  var gameListMarginSpacing = Math.floor((gameListFontSize * gameListFontHorizontalRatio) * (6 / 32) / 5);
440  var gameListPlayerSpacing = Math.floor((gameListFontSize * gameListFontHorizontalRatio) * (9 / 32));
441  myInsertRule(sheet, ".gameListRow", "cursor: pointer;");
442  myInsertRule(sheet, ".gameListRowSelected", "color: #" + backgroundColorHex + "; background-color: #" + fontColorHex + ";");
443  myInsertRule(sheet, ".gameListBodyItemsPlayer", "overflow: hidden; width: " + gameListPlayerSpacing + "px; margin-left: " + gameListMarginSpacing + "px; margin-right: " + gameListMarginSpacing + "px;");
444  myInsertRule(sheet, ".gameListBodyItemsPlayerWhite", "text-align: right; margin-left: " + (2 * gameListMarginSpacing) + "px;");
445  myInsertRule(sheet, ".gameListBodyItemsPlayerBlack", "");
446  myInsertRule(sheet, ".gameListBodyItemsResult", "text-align: center; min-width: 5ex; margin-left: 0px; margin-right: 0px;");
447  myInsertRule(sheet, ".gameListBodyItemsEventRound", "margin-left: " + (2 * gameListMarginSpacing) + "px; margin-right: " + (2 * gameListMarginSpacing) + "px;");
448
449  for (var ii = 0; ii < oldRules; ii++) { myDeleteRule(sheet, 0); }
450
451  var theObj;
452
453  if (theObj = document.getElementById("boardTable")) {
454    theObj.style.height = (squareSize * 8) + "px";
455    theObj.style.width = (squareSize * 8) + "px";
456  }
457
458  if (theObj = document.getElementById("HeaderContainer")) { theObj.style.display = bare ? "none" : document.getElementById("GameBoard").style.display; }
459
460  if (!firstStart) {
461    fixColorFlag();
462    fixECO();
463  }
464
465  dynamicFrameDebugString = "fw=" + ww + " fh=" + wh + " fp=" + framePadding + " fs=" + fontSize + " ss=" + squareSize + " sb=" + squareBorderWidth + " ps=" + pieceSize + " pbs=" + pieceBaseSize;
466
467  return pieceSize;
468}
469
470
471function customFunctionOnCheckLiveBroadcastStatus() {
472  updateBareShortcut();
473}
474
475function customDebugInfo() {
476  var dbg = "";
477  if (highlightColorHex) { dbg += "highlightOption=" + highlightOption + " "; }
478  if (LiveBroadcastDelay === 0) { dbg += "initialHalfmove=" + initialHalfmove + " "; }
479  dbg += "showColorFlag=" + showColorFlag + " " + "showEco=" + showEco;
480  if (debug) { dbg += " " + dynamicFrameDebugString; }
481  return dbg;
482}
483
484var textSelectOptionsLast = "none";
485var currentGameLast = -1;
486var gameListBodyHeight = -1;
487var gameListLineHeight = -1;
488var gameListNumGames = -1;
489function fillGameList(force) {
490  var theObj;
491  if (theObj = document.getElementById("GameSelSelect")) { textSelectOptions = theObj.innerHTML; }
492  if ((currentGame !== currentGameLast) || (textSelectOptions !== textSelectOptionsLast) || (numberOfGames == 1)) { // textSelectOptions not updated when there's only one game
493    currentGameLast = currentGame;
494    textSelectOptionsLast = textSelectOptions;
495    force = true;
496    if (theObj = document.getElementById("GameListBodyItems")) {
497      var thisNum, thisResult, thisGameTitle1, thisGameTitle2;
498      var text = "<table width='100%' cellspacing='0' cellpadding='0' border='0'>";
499      for (thisNum = 0; thisNum < numberOfGames; thisNum++) {
500        thisGameTitle1 = gameWhite[thisNum] || "";
501        thisGameTitle1 += (thisGameTitle1 && gameBlack[thisNum]) ? "   " : "";
502        thisGameTitle1 += gameBlack[thisNum] || "";
503        thisGameTitle1 += (thisGameTitle1 && gameResult[thisNum]) ? "   " : "";
504        thisGameTitle1 += gameResult[thisNum] || "";
505        thisGameTitle2 =  gameEvent[thisNum] || "";
506        thisGameTitle2 += (thisGameTitle2 && gameRound[thisNum]) ? "   " : "";
507        thisGameTitle2 += gameRound[thisNum] || "";
508        text += "<tr class='gameListRow" + (currentGame === thisNum ? " gameListRowSelected" : "") + "' onclick='selectGameList(" + thisNum + ");' title='" + thisGameTitle1 + (thisGameTitle1 && thisGameTitle2 ? "\n" : "") + thisGameTitle2 + "'>";
509        text += "<td><div class='gameListBodyItemsPlayer gameListBodyItemsPlayerWhite'>" + gameWhite[thisNum] + "</div></td>";
510        if ((gameWhite[thisNum] !== "") || (gameBlack[thisNum] !== "") || (gameResult[thisNum] != "*")) {
511          thisResult = gameResult[thisNum];
512          if (thisResult == "1/2-1/2") { thisResult = "1/2"; }
513          else if (thisResult.length > 3) { thisResult = "?"; }
514          else if (thisResult == "*") { thisResult = "&lowast;"; }
515        } else {
516          thisResult = "";
517        }
518        text += "<td><div class='gameListBodyItemsResult'>" + thisResult + "</div></td>";
519        text += "<td><div class='gameListBodyItemsPlayer gameListBodyItemsPlayerBlack'>" + gameBlack[thisNum] + "</div></td>";
520        text += "<td width='100%'>";
521        if (gameEvent[thisNum] || gameRound[thisNum]) {
522          text += "<div class='gameListBodyItemsEventRound'>" + gameEvent[thisNum] + ((gameEvent[thisNum] && gameRound[thisNum]) ? " &nbsp;&nbsp;&nbsp;&nbsp; " : "") + gameRound[thisNum] + "</div>";
523        }
524        text += "</td></tr>";
525      }
526      text += "</table>";
527      theObj.innerHTML = text;
528    }
529  }
530  if (force) {
531    setTimeout("autoscrollGameListBody(-1);", 111);
532  }
533}
534
535function autoscrollGameListBody(thisGame) {
536  var theObj = document.getElementById("GameListBody");
537  if (theObj) {
538    if (thisGame == -1) {
539      thisGame = currentGame + 1 - Math.ceil(gameListNumGames / 2);
540    }
541    theObj.scrollLeft = 0;
542    theObj.scrollTop = thisGame * gameListLineHeight;
543  }
544}
545
546var oldHeaderContainerDisplay;
547function showGameList() {
548  if (numberOfGames < 2) { return; }
549  var theObj = document.getElementById("GameList");
550  if ((theObj) && (theObj.style.display == "block")) { return; }
551  disableShortcutKeysAndStoreStatus();
552  fillGameList(true);
553  if (theObj = document.getElementById("HeaderContainer")) {
554    oldHeaderContainerDisplay = theObj.style.display;
555    theObj.style.display = "none";
556  }
557  if (theObj = document.getElementById("GameBoard")) { theObj.style.display = "none"; }
558  if (theObj = document.getElementById("GameList")) { theObj.style.display = "block"; }
559}
560
561function selectGameList(gameNum) {
562  var theObj = document.getElementById("GameList");
563  if ((theObj) && (theObj.style.display === "")) { return; }
564  if (gameNum != -1) { Init(gameNum); }
565  if (theObj = document.getElementById("GameList")) { theObj.style.display = ""; }
566  if (theObj = document.getElementById("GameBoard")) { theObj.style.display = ""; }
567  if (theObj = document.getElementById("HeaderContainer")) { theObj.style.display = oldHeaderContainerDisplay; }
568  restoreShortcutKeysStatus();
569}
570
571function toggleGameListHorizontalScroll() {
572  var theObj = document.getElementById("GameListBody");
573  if (theObj) { theObj.scrollLeft = theObj.scrollLeft ? 0 : theObj.offsetWidth; }
574}
575
576var liveBroadcastUpdateTicker = 0;
577var previousPlyNumber = -1;
578function customFunctionOnPgnTextLoad() {
579  var noGamesLoaded = (numberOfGames == 1) && (PlyNumber === 0) && (StartPly === 0) && (!gameWhite[0]) && (!gameBlack[0]) && (!gameResult[0]) && (!gameFEN[0]);
580  if (LiveBroadcastDelay > 0) {
581    if (previousPlyNumber !== PlyNumber) {
582      previousPlyNumber = PlyNumber;
583      liveBroadcastUpdateTicker++;
584    }
585    document.title = liveBroadcastUpdateTicker + "." + LiveBroadcastGamesRunning + "." + numberOfGames + " live broadcast" + (demoFlag ? " demo" : "");
586  } else {
587    if (noGamesLoaded) { document.title = alertNum ? "PGN data error" : "chess games"; }
588    else { document.title = numberOfGames + " game" + (numberOfGames == 1 ? "" : "s"); }
589  }
590
591  fillGameList(false);
592  if (theObj = document.getElementById("ShowGameListLink")) {
593    theObj.title = "select from " + numberOfGames + " games";
594    var text = "", ii;
595    for (ii = 0; ii <= 4 + Math.log(numberOfGames)/Math.LN2; ii++) { text += "&middot; "; }
596    text += "&middot;";
597    theObj.innerHTML = text;
598  }
599  if (theObj = document.getElementById("ShowGameList")) {
600    theObj.style.visibility = numberOfGames > 1 ? "visible" : "hidden";
601  }
602  if (numberOfGames > 1) {
603    boardShortcut("F5", "show games list", function(t,e){ showGameList(); });
604  } else {
605    boardShortcut("F5", "", function(t,e){});
606  }
607  if (engineWinPrepareIdle) {
608    showEngineAnalysisBoard(true, true);
609    engineWinPrepareIdle = false;
610  }
611
612<!-- AppCheck: customFunctionOnPgnTextLoad -->
613
614}
615
616function fixHeaderItem(tag, objectId, label) {
617  var theObj = document.getElementById(objectId);
618  if (theObj) {
619    var tagValue = simpleHtmlentitiesDecode(tag ? customPgnHeaderTag(tag, objectId) : theObj.innerHTML);
620    if (tagValue) {
621      theObj.title = label + ": " + tagValue;
622      theObj.className = "leftRightSpacing";
623    } else {
624      theObj.title = label;
625      theObj.className = "";
626    }
627  }
628}
629
630function customFunctionOnPgnGameLoad() {
631  myOnResize();
632  fixHeaderItem(null, "GameEvent", "event");
633  fixHeaderItem(null, "GameSite", "site");
634  fixHeaderItem(null, "GameDate", "date");
635  fixHeaderItem(null, "GameRound", "round");
636  fixHeaderItem(null, "GameWhite", "white player");
637  fixHeaderItem(null, "GameBlack", "black player");
638  fixHeaderItem(null, "GameResult", "result");
639  fixHeaderItem("Section", "GameSection", "section");
640  fixHeaderItem("Stage", "GameStage", "stage");
641  fixHeaderItem("WhiteTitle", "GameWhiteTitle", "white title");
642  fixHeaderItem("WhiteElo", "GameWhiteElo", "white elo");
643  fixHeaderItem("WhiteTeam", "GameWhiteTeam", "white team");
644  fixHeaderItem("BlackTitle", "GameBlackTitle", "black title");
645  fixHeaderItem("BlackElo", "GameBlackElo", "black elo");
646  fixHeaderItem("BlackTeam", "GameBlackTeam", "black team");
647  if (showEco) {
648    fixHeaderItem("ECO", "GameECO", "ECO");
649    fixHeaderItem("ECO", "GameECOFiller", "ECO");
650  }
651  updateBareShortcut();
652  var theObj = document.getElementById("GameResult");
653  if (theObj) { theObj.innerHTML = theObj.innerHTML.replace(/\*/g, "&lowast;").replace(/(\d)-(\d)/g, "$1<span style='font-weight:normal;'>&nbsp;-&nbsp</span>$2"); }
654
655  var livePlaceholderDetected = (LiveBroadcastDelay > 0) && (PlyNumber === 0) && (StartPly === 0) && (!gameWhite[currentGame]) && (!gameBlack[currentGame]) && (!gameFEN[currentGame]);
656  if (theObj = document.getElementById("GameResultLine")) { theObj.style.display = livePlaceholderDetected ? "none" : ""; }
657  if (theObj = document.getElementById("GameWhiteClockLine")) { theObj.style.display = livePlaceholderDetected ? "none" : ""; }
658  if (theObj = document.getElementById("GameBlackClockLine")) { theObj.style.display = livePlaceholderDetected ? "none" : ""; }
659
660<!-- AppCheck: customFunctionOnPgnGameLoad -->
661
662}
663
664function customFunctionOnMove() {
665  var extraMoves = 2;
666
667  document.getElementById("GamePrevMoves").innerHTML = "";
668  document.getElementById("GameCurrMove").innerHTML = "";
669  document.getElementById("GameNextMoves").innerHTML = "";
670  var theObj = document.getElementById("GamePrevMoves");
671  var thisPly = Math.max(CurrentPly - extraMoves - 1, StartPly);
672  if (thisPly > StartPly) { theObj.innerHTML += "... "; }
673  for (; thisPly < Math.min(CurrentPly + extraMoves, StartPly + PlyNumber); thisPly++) {
674    if (thisPly == CurrentPly) {
675      theObj = document.getElementById("GameNextMoves");
676    }
677    if (thisPly % 2 === 0) { theObj.innerHTML += Math.floor(1 + thisPly / 2) + ". "; }
678    if (thisPly == CurrentPly - 1) {
679      theObj = document.getElementById("GameCurrMove");
680    }
681    theObj.innerHTML += Moves[thisPly] + " ";
682  }
683  if (thisPly < StartPly + PlyNumber) { theObj.innerHTML += "..."; }
684
685  fixHeaderItem(null, "GameWhiteClock", "white clock");
686  fixHeaderItem(null, "GameBlackClock", "black clock");
687  fixColorFlag();
688  fixECO();
689
690<!-- AppCheck: customFunctionOnMove -->
691
692}
693
694
695function fixColorFlag() {
696  var theObj;
697
698  if (showColorFlag) {
699    var whiteFlagPadding = (horizontalLayout || ((theObj = document.getElementById("GameWhiteClock")) && (theObj.innerHTML)));
700    if (theObj = document.getElementById("whiteColorFlag")) {
701      theObj.style.display = "inline-block";
702      theObj.style.visibility = CurrentPly % 2 ? "hidden" : "visible";
703    }
704    if (theObj = document.getElementById("whiteColorFlagFiller")) {
705      theObj.style.display = whiteFlagPadding ? "inline-block" : "none";
706      theObj.style.visibility = "hidden";
707    }
708    var blackFlagPadding = (horizontalLayout || ((theObj = document.getElementById("GameBlackClock")) && (theObj.innerHTML)));
709    if (theObj = document.getElementById("blackColorFlag")) {
710      theObj.style.display = "inline-block";
711      theObj.style.visibility = CurrentPly % 2 ? "visible" : "hidden";
712    }
713    if (theObj = document.getElementById("blackColorFlagFiller")) {
714      theObj.style.display = blackFlagPadding ? "inline-block" : "none";
715      theObj.style.visibility = "hidden";
716    }
717  }
718}
719
720function fixECO() {
721  var theObj = document.getElementById("GameECOFiller");
722  if (theObj) {
723    theObj.style.display = horizontalLayout ? "none" : "";
724  }
725}
726
727function searchPlayer(name, FideId) {
728  if (typeof(openFidePlayerUrl) == "function") { openFidePlayerUrl(name, FideId); }
729}
730
731function customShortcutKey_Shift_1() {
732  searchPlayer(gameWhite[currentGame], customPgnHeaderTag('WhiteFideId'));
733}
734
735function customShortcutKey_Shift_2() {
736  searchPlayer(gameBlack[currentGame], customPgnHeaderTag('BlackFideId'));
737}
738
739function customShortcutKey_Shift_3() {
740  toggleBareChessboard();
741}
742
743var showFullscreenChessboardTimeout = null;
744function customShortcutKey_Shift_4() {
745  if (showFullscreenChessboardTimeout) {
746    clearTimeout(showFullscreenChessboardTimeout);
747    showFullscreenChessboardTimeout = null;
748    showFullscreenChessboard(true);
749  } else {
750    showFullscreenChessboardTimeout = setTimeout("showFullscreenChessboardTimeout = false; showFullscreenChessboard(false);", 333);
751  }
752}
753
754function customShortcutKey_Shift_5() {
755  SetHighlight(!highlightOption);
756}
757
758function customShortcutKey_Shift_6() {
759  toggleShowEco();
760}
761
762function customShortcutKey_Shift_7() {
763  toggleColorFlag();
764}
765
766// customShortcutKey_Shift_8 defined by engine.js
767// customShortcutKey_Shift_9 defined by engine.js
768// customShortcutKey_Shift_0 defined by engine.js
769
770function toggleBareChessboard() {
771  bare = !bare;
772  myOnResize();
773  updateBareShortcut();
774}
775
776function showFullscreenChessboard(newWin) {
777  var win = window;
778  if (newWin) { win.open(location.href.replace(/(pieceBaseSize|pbs)=[^&]*/gi, ""), "_blank"); }
779  else {
780    while (win.parent !== win) { win = win.parent; }
781    win.location.href = location.href.replace(/(pieceBaseSize|pbs)=[^&]*/gi, "");
782  }
783}
784
785function toggleInitialHalfmove(reset2default) {
786  SetInitialHalfmove(reset2default ? 'start' : (initialHalfmove == 'end' ? 'start' : 'end'), true);
787  GoToMove(initialHalfmove == 'end' ? StartPlyVar[0] + PlyNumberVar[0] : StartPlyVar[0], 0);
788}
789
790
791boardShortcut("E7", "toggle ECO code", function(t,e){ toggleShowEco(); });
792
793// disable FlipBoard functionality, otherwise remember to redefine FlipBoard() to include myOnResize()
794var warnedFlipBoard = false;
795function FlipBoard() { if (!warnedFlipBoard) { myAlert("warning: flip board functionality disabled", false, true); warnedFlipBoard = true; } }
796
797
798boardShortcut("F7", "toggle side to move flag", function(t,e){ toggleColorFlag(); });
799
800if (LiveBroadcastDelay === 0) {
801  boardShortcut("G6", "toggle initial halfmove", function(t,e){ toggleInitialHalfmove(e.shiftKey); });
802}
803
804if ((window.parent !== window) && (!engineWinPrepareIdle)) {
805  boardShortcut("H5", "show fullscreen chessboard", function(t,e){ showFullscreenChessboard(e.shiftKey); });
806}
807
808function updateBareShortcut() {
809  boardShortcut("G5", bare ? "unhide game info\n\n" + gameTooltipInfo() : "maximize chessboard and hide game info", function(t,e){ toggleBareChessboard(); });
810}
811
812function meaningfulHeader(tagValue) {
813  return ((typeof(tagValue) == "string") && (tagValue.match(/[^\s?.-]/)));
814}
815
816function gameTooltipInfo() {
817  var headerValue;
818  var str = "game " + (currentGame+1) + " of " + numberOfGames;
819  if (LiveBroadcastDelay > 0) { str += ",  " + LiveBroadcastGamesRunning + " live"; }
820  if (meaningfulHeader(gameEvent[currentGame])) { str+= "\nevent:  " + gameEvent[currentGame];
821    if (meaningfulHeader(headerValue = customPgnHeaderTag("Section"))) { str+= "  " + headerValue; }
822    if (meaningfulHeader(headerValue = customPgnHeaderTag("Stage"))) { str+= "  " + headerValue; }
823  }
824  if (meaningfulHeader(gameSite[currentGame])) { str+= "\nsite:  " + gameSite[currentGame]; }
825  if (meaningfulHeader(gameDate[currentGame])) { str+= "\ndate:  " + gameDate[currentGame]; }
826  if (meaningfulHeader(gameRound[currentGame])) { str+= "\nround:  " + gameRound[currentGame]; }
827  if (meaningfulHeader(gameWhite[currentGame])) { str+= "\nwhite:  " + gameWhite[currentGame];
828    if (meaningfulHeader(headerValue = customPgnHeaderTag("WhiteTitle"))) { str+= "  " + headerValue; }
829    if (meaningfulHeader(headerValue = customPgnHeaderTag("WhiteElo"))) { str+= "  " + headerValue; }
830    if (meaningfulHeader(headerValue = customPgnHeaderTag("WhiteTeam"))) { str+= "  " + headerValue; }
831  }
832  if (meaningfulHeader(gameBlack[currentGame])) { str+= "\nblack:  " + gameBlack[currentGame];
833    if (meaningfulHeader(headerValue = customPgnHeaderTag("BlackTitle"))) { str+= "  " + headerValue; }
834    if (meaningfulHeader(headerValue = customPgnHeaderTag("BlackElo"))) { str+= "  " + headerValue; }
835    if (meaningfulHeader(headerValue = customPgnHeaderTag("BlackTeam"))) { str+= "  " + headerValue; }
836  }
837  if (meaningfulHeader(gameResult[currentGame])) { str+= "\nresult:  " + gameResult[currentGame]; }
838  return str;
839}
840
841function searchNextEventRound(backward) {
842  searchPgnGame('\\[\\s*Event\\s*"(?!' + fixRegExp(gameEvent[currentGame]) + '"\\s*\\])|\\[\\s*Section\\s*"(?!' + fixRegExp(customPgnHeaderTag("Section")) + '"\\s*\\])|\\[\\s*Stage\\s*"(?!' + fixRegExp(customPgnHeaderTag("Stage")) + '"\\s*\\])|\\[\\s*Round\\s*"(?!' + fixRegExp(gameRound[currentGame]) + '"\\s*\\])', backward);
843}
844
845var lastOrientation;
846var lastOrientationTimeout = null;
847simpleAddEvent(window, "orientationchange", function() {
848  var theObj;
849  if (typeof(window.orientation) == "undefined") { return; }
850  if (window.orientation === lastOrientation) { return; }
851  var lastOrientationTimeoutString = "lastOrientationTimeout = null;";
852  if (lastOrientationTimeout) {
853    clearTimeout(lastOrientationTimeout);
854    if ((theObj = document.getElementById("GameList")) && (theObj.style.display)) { selectGameList(-1); }
855    lastOrientationTimeoutString += " refreshPgnSource();";
856  } else {
857    setTimeout("autoscrollGameListBody(-1);", 111);
858  }
859  lastOrientationTimeout = setTimeout(lastOrientationTimeoutString, 1800);
860  lastOrientation = window.orientation;
861});
862
863</script>
864
865</head>
866
867<body onResize="myOnResize();" onLoad="myOnResize();">
868
869<!-- paste your PGN below and make sure you dont specify an external source with SetPgnUrl() -->
870<form style="display:none;"><textarea style="display:none;" id="pgnText">
871
872</textarea></form>
873<!-- paste your PGN above and make sure you dont specify an external source with SetPgnUrl() -->
874
875<div style="display:none;" id="GameSelector"></div>
876
877<div class="gameList" style="display:none;" id="GameList">
878<div class="gameListHeader" id="GameListHeader"><div class="gameListHeaderItem"><span class="gameListHeaderButton" onclick="selectGameList(-1);" title="back to chessboard">&lt;=</span></div><div class="gameListHeaderItem"><span class="gameListHeaderButton" onclick="autoscrollGameListBody(0); this.blur();" title="scroll to first page">&lt;&lt;</span></div><div class="gameListHeaderItem"><span class="gameListHeaderButton" onclick="if (theObj = document.getElementById('GameListBody')) { autoscrollGameListBody(Math.floor(theObj.scrollTop / gameListLineHeight) - gameListNumGames); } this.blur();" title="scroll to previous page">&lt;</span></div><div class="gameListHeaderItem"><span class="gameListHeaderButton" onclick="autoscrollGameListBody(-1); this.blur();" title="scroll to current game">&gt;&lt;</span></div><div class="gameListHeaderItem"><span class="gameListHeaderButton" onclick="if (theObj = document.getElementById('GameListBody')) { autoscrollGameListBody(Math.floor(theObj.scrollTop / gameListLineHeight) + gameListNumGames); } this.blur();" title="scroll to next page">&gt;</span></div><div class="gameListHeaderItem"><span class="gameListHeaderButton" onclick="autoscrollGameListBody(numberOfGames); this.blur();" title="scroll to last page">&gt;&gt;</span></div><div class="gameListHeaderItem"><span class="gameListHeaderButton" onclick="toggleGameListHorizontalScroll(); this.blur();" title="horizontal scroll">&lt;&gt;</span></div></div>
879<div class="gameListBody" id="GameListBody"><div class="gameListBodyItems" id="GameListBodyItems"></div></div>
880</div>
881
882<div id="GameBoard"></div>
883
884<div id="HeaderContainer" class="headerContainer">
885<div class="firstVariableSpacer">&nbsp;</div>
886<div>&nbsp;<span id="GameSite" title="site"></span><span id="GameDate" title="date"></span>&nbsp;</div>
887<div>&nbsp;<span style="cursor:pointer;" onclick="searchNextEventRound(event.shiftKey); this.blur();"><span id="GameEvent" title="event"></span><span id="GameSection" title="section"></span><span id="GameStage" title="stage"></span><span id="GameRound" title="round"></span></span>&nbsp;</div>
888<div class="variableSpacer">&nbsp;</div>
889<div>&nbsp;<span id="GameWhiteClockLine"><span style="display:inline-block;" title="white to move"><span class="colorFlag" style="background:white; display:none;" id="whiteColorFlag"></span></span><span id="GameWhiteClock" style="cursor:pointer;" onclick="if (!showColorFlag) { toggleColorFlag(); setTimeout('if (showColorFlag) { toggleColorFlag(); }', 1111); } this.blur();" title="white clock"></span><span style="display:inline-block;"><span class="colorFlag" style="background:white; display:none;" id="whiteColorFlagFiller"></span></span></span>&nbsp;</div>
890<div>&nbsp;<span id="GameWhite" style="font-weight:bold; cursor:pointer;" onclick="searchPlayer(this.innerHTML, customPgnHeaderTag('WhiteFideId')); this.blur();" title="white player"></span><span id="GameWhiteTitle" title="white title"></span><span id="GameWhiteElo" title="white elo"></span><span id="GameWhiteTeam" title="white team"></span><span style="font-weight:bold;">&nbsp;</span></div>
891<div>&nbsp;<span id="GameBlack" style="font-weight:bold; cursor:pointer;" onclick="searchPlayer(this.innerHTML, customPgnHeaderTag('BlackFideId')); this.blur();" title="black player"></span><span id="GameBlackTitle" title="black title"></span><span id="GameBlackElo" title="black elo"></span><span id="GameBlackTeam" title="black team"></span><span style="font-weight:bold;">&nbsp;</span></div>
892<div>&nbsp;<span id="GameBlackClockLine"><span style="display:inline-block;" title="black to move"><span class="colorFlag" style="background:black; display:none;" id="blackColorFlag"></span></span><span id="GameBlackClock" style="cursor:pointer;" onclick="if (!showColorFlag) { toggleColorFlag(); setTimeout('if (showColorFlag) { toggleColorFlag(); }', 1111); } this.blur();" title="black clock"></span><span style="display:inline-block;"><span class="colorFlag" style="background:black; display:none;" id="blackColorFlagFiller"></span></span></span>&nbsp;</div>
893<div class="variableSpacer">&nbsp;</div>
894<div>&nbsp;<span id="GameResultLine"><span id="GameECOFiller" style="visibility:hidden; padding-right:2.5em;"></span><span id="GameResult" style="font-weight:bold; cursor:pointer;" onclick="if (!showEco) { toggleShowEco(); setTimeout('if (showEco) { toggleShowEco(); }', 1111); } this.blur();" title="result"></span><span style="padding-left:2.5em;" id="GameECO"></span></span><span style="font-weight:bold;">&nbsp;</span></div>
895<div class="variableSpacer">&nbsp;</div>
896<div class="leftRightSpacing">&nbsp;<span id="GamePrevMoves" style="cursor:pointer;" onclick="GoToMove(CurrentPly - 1); this.blur();" title="previous moves"></span><span id="GameCurrMove" style="font-weight:bold; cursor:pointer;" onclick="if (!highlightOption) { SetHighlight(!highlightOption); setTimeout('if (highlightOption) { SetHighlight(!highlightOption); }', 1111); } this.blur();" title="current move as shown on chessboard"></span><span id="GameNextMoves" style="cursor:pointer;" onclick="GoToMove(CurrentPly + 1); this.blur();" title="next moves"></span><span style="font-weight:bold;">&nbsp;</span></div>
897<div class="variableSpacer">&nbsp;</div>
898<center><div id="GameButtons" class="leftRightSpacing gameButtons"></div></center>
899<div class="liveStatusLine">&nbsp;<span id="GameLiveStatusExtraInfoLeft" class="leftRightSpacing gameLiveStatusExtraInfoLeft" style="visibility:hidden;"></span><span id="GameLiveStatus" class="leftRightSpacing" style="cursor:pointer;"></span><span id="GameLiveStatusExtraInfoRight" class="leftRightSpacing" style="visibility:hidden;"></span>&nbsp;</div>
900<div class="variableSpacer">&nbsp;</div>
901<div id="ShowGameList" class="leftRightSpacing" style="visibility:hidden;">&nbsp;<span id="ShowGameListLink" class="showGameListLink" style="cursor:pointer;" onclick="showGameList();"></span>&nbsp;</div>
902</div>
903
904<script type="text/javascript">
905"use strict";
906
907var theObj;
908
909if (LiveBroadcastDelay && LiveBroadcastDemo) {
910  if (theObj = document.getElementById("GameLiveStatusExtraInfoRight")) {
911    theObj.innerHTML = "demo";
912    theObj.title = "this is a broadcast simulation";
913    theObj.style.visibility = "visible";
914  }
915  if (theObj = document.getElementById("GameLiveStatusExtraInfoLeft")) {
916    theObj.innerHTML = "demo";
917  }
918}
919
920<!-- AppCheck: footer -->
921
922</script>
923
924</body>
925
926</html>
927