myid: "", //our ID, always set
oppid: "", //opponent ID in case of HH game
gameId: "", //useful if opponent started other human games after we disconnected
- myname: getCookie("username","anonymous"),
+ myname: localStorage["username"] || "anonymous",
oppName: "anonymous", //opponent name, revealed after a game (if provided)
chats: [], //chat messages after human game
oppConnected: false,
fenStart: "",
incheck: [],
pgnTxt: "",
- hints: (getCookie("hints") === "1" ? true : false),
- color: getCookie("color", "lichess"), //lichess, chesscom or chesstempo
+ hints: (!localStorage["hints"] ? true : localStorage["hints"] === "1"),
+ color: localStorage["color"] || "lichess", //lichess, chesscom or chesstempo
// sound level: 0 = no sound, 1 = sound only on newgame, 2 = always
- sound: parseInt(getCookie("sound", "2")),
+ sound: parseInt(localStorage["sound"] || "2"),
// Web worker to play computer moves without freezing interface:
compWorker: new Worker('/javascripts/playCompMove.js'),
timeStart: undefined, //time when computer starts thinking
},
render(h) {
const [sizeX,sizeY] = [V.size.x,V.size.y];
- const smallScreen = (window.innerWidth <= 420);
// Precompute hints squares to facilitate rendering
let hintSquares = doubleArray(sizeX, sizeY, false);
this.possibleMoves.forEach(m => { hintSquares[m.end.x][m.end.y] = true; });
h('button',
{
on: { click: this.clickGameSeek },
- attrs: { "aria-label": 'New online game' },
+ attrs: { "aria-label": translations['New online game'] },
'class': {
"tooltip": true,
- "bottom": true, //display below
+ "play": true,
"seek": this.seek,
"playing": this.mode == "human",
- "small": smallScreen,
+ "spaceright": true,
},
},
[h('i', { 'class': { "material-icons": true } }, "accessibility")])
h('button',
{
on: { click: this.clickComputerGame },
- attrs: { "aria-label": 'New game VS computer' },
+ attrs: { "aria-label": translations['New game versus computer'] },
'class': {
"tooltip":true,
- "bottom": true,
+ "play": true,
"playing": this.mode == "computer",
- "small": smallScreen,
+ "spaceright": true,
},
},
[h('i', { 'class': { "material-icons": true } }, "computer")])
h('button',
{
on: { click: this.clickFriendGame },
- attrs: { "aria-label": 'New IRL game' },
+ attrs: { "aria-label": translations['Analysis mode'] },
'class': {
"tooltip":true,
- "bottom": true,
+ "play": true,
"playing": this.mode == "friend",
- "small": smallScreen,
+ "spaceright": true,
},
},
[h('i', { 'class': { "material-icons": true } }, "people")])
? parseFloat(window.getComputedStyle(square00).width.slice(0,-2))
: 0;
const settingsBtnElt = document.getElementById("settingsBtn");
- const indicWidth = !!settingsBtnElt //-2 for border:
- ? parseFloat(window.getComputedStyle(settingsBtnElt).height.slice(0,-2)) - 2
- : (smallScreen ? 31 : 37);
+ const settingsStyle = !!settingsBtnElt
+ ? window.getComputedStyle(settingsBtnElt)
+ : {width:"46px", height:"26px"};
+ const [indicWidth,indicHeight] = //[44,24];
+ [
+ // NOTE: -2 for border
+ parseFloat(settingsStyle.width.slice(0,-2)) - 2,
+ parseFloat(settingsStyle.height.slice(0,-2)) - 2
+ ];
+ let aboveBoardElts = [];
if (["chat","human"].includes(this.mode))
{
const connectedIndic = h(
'div',
{
"class": {
- "topindicator": true,
"indic-left": true,
"connected": this.oppConnected,
"disconnected": !this.oppConnected,
},
style: {
"width": indicWidth + "px",
- "height": indicWidth + "px",
+ "height": indicHeight + "px",
},
}
);
- elementArray.push(connectedIndic);
+ aboveBoardElts.push(connectedIndic);
}
if (this.mode == "chat")
{
{
on: { click: this.startChat },
attrs: {
- "aria-label": 'Start chat',
+ "aria-label": translations['Start chat'],
"id": "chatBtn",
},
'class': {
"tooltip": true,
- "topindicator": true,
+ "play": true,
+ "above-board": true,
"indic-left": true,
- "settings-btn": !smallScreen,
- "settings-btn-small": smallScreen,
},
},
[h('i', { 'class': { "material-icons": true } }, "chat")]
);
- elementArray.push(chatButton);
+ aboveBoardElts.push(chatButton);
}
else if (this.mode == "computer")
{
{
on: { click: this.clearComputerGame },
attrs: {
- "aria-label": 'Clear computer game',
+ "aria-label": translations['Clear game versus computer'],
"id": "clearBtn",
},
'class': {
"tooltip": true,
- "topindicator": true,
+ "play": true,
+ "above-board": true,
"indic-left": true,
- "settings-btn": !smallScreen,
- "settings-btn-small": smallScreen,
},
},
[h('i', { 'class': { "material-icons": true } }, "clear")]
);
- elementArray.push(clearButton);
+ aboveBoardElts.push(clearButton);
}
const turnIndic = h(
'div',
{
"class": {
- "topindicator": true,
"indic-right": true,
"white-turn": this.vr.turn=="w",
"black-turn": this.vr.turn=="b",
},
style: {
"width": indicWidth + "px",
- "height": indicWidth + "px",
+ "height": indicHeight + "px",
},
}
);
- elementArray.push(turnIndic);
+ aboveBoardElts.push(turnIndic);
const settingsBtn = h(
'button',
{
on: { click: this.showSettings },
attrs: {
- "aria-label": 'Settings',
+ "aria-label": translations['Settings'],
"id": "settingsBtn",
},
'class': {
"tooltip": true,
- "topindicator": true,
+ "play": true,
+ "above-board": true,
"indic-right": true,
- "settings-btn": !smallScreen,
- "settings-btn-small": smallScreen,
},
},
[h('i', { 'class': { "material-icons": true } }, "settings")]
);
- elementArray.push(settingsBtn);
+ aboveBoardElts.push(settingsBtn);
+ elementArray.push(
+ h('div',
+ { "class": { "aboveboard-wrapper": true } },
+ aboveBoardElts
+ )
+ );
if (this.mode == "problem")
{
// Show problem instructions
(!["idle","chat"].includes(this.mode) || this.cursor==this.vr.moves.length);
const gameDiv = h('div',
{
- 'class': { 'game': true },
+ 'class': {
+ 'game': true,
+ 'clearer': true,
+ },
},
[_.range(sizeX).map(i => {
let ci = (this.mycolor=='w' ? i : sizeX-i-1);
h('button',
{
on: { click: this.resign },
- attrs: { "aria-label": 'Resign' },
+ attrs: { "aria-label": translations['Resign'] },
'class': {
"tooltip":true,
- "bottom": true,
- "small": smallScreen,
+ "play": true,
},
},
[h('i', { 'class': { "material-icons": true } }, "flag")])
h('button',
{
on: { click: e => this.undo() },
- attrs: { "aria-label": 'Undo' },
+ attrs: { "aria-label": translations['Undo'] },
"class": {
- "small": smallScreen,
+ "play": true,
"spaceleft": true,
},
},
h('button',
{
on: { click: e => this.play() },
- attrs: { "aria-label": 'Play' },
- "class": { "small": smallScreen },
+ attrs: { "aria-label": translations['Play'] },
+ "class": {
+ "play": true,
+ "spaceleft": true,
+ },
},
[h('i', { 'class': { "material-icons": true } }, "fast_forward")]),
]
h('button',
{
on: { click: this.undoInGame },
- attrs: { "aria-label": 'Undo' },
+ attrs: { "aria-label": trnaslations['Undo'] },
"class": {
- "small": smallScreen,
+ "play": true,
"spaceleft": true,
},
},
h('button',
{
on: { click: () => { this.mycolor = this.vr.getOppCol(this.mycolor) } },
- attrs: { "aria-label": 'Flip' },
- "class": { "small": smallScreen },
+ attrs: { "aria-label": translations['Flip'] },
+ "class": {
+ "play": true,
+ "spaceleft": true,
+ },
},
[h('i', { 'class': { "material-icons": true } }, "cached")]
),
{
myReservePiecesArray.push(h('div',
{
- 'class': {'board':true, ['board'+sizeY]:true},
+ 'class': {'board':true, ['board'+sizeY+'-reserve']:true},
attrs: { id: this.getSquareId({x:sizeX+shiftIdx,y:i}) }
},
[
h('img',
{
- 'class': {"piece":true},
+ 'class': {"piece":true, "reserve":true},
attrs: {
"src": "/images/pieces/" +
this.vr.getReservePpath(this.mycolor,i) + ".svg",
{
oppReservePiecesArray.push(h('div',
{
- 'class': {'board':true, ['board'+sizeY]:true},
+ 'class': {'board':true, ['board'+sizeY+'-reserve']:true},
attrs: { id: this.getSquareId({x:sizeX+(1-shiftIdx),y:i}) }
},
[
h('img',
{
- 'class': {"piece":true},
+ 'class': {"piece":true, "reserve":true},
attrs: {
"src": "/images/pieces/" +
this.vr.getReservePpath(oppCol,i) + ".svg",
[
h('div',
{
- "class": { "card": true, "smallpad": true },
+ "class": {
+ "card": true,
+ "smallpad": true,
+ "small-modal": true,
+ "text-center": true,
+ },
},
[
h('label',
];
elementArray = elementArray.concat(modalEog);
}
- // NOTE: this modal could be in Pug view (no usage of Vue functions or variables)
- const modalNewgame = [
- h('input',
- {
- attrs: { "id": "modal-newgame", type: "checkbox" },
- "class": { "modal": true },
- }),
- h('div',
- {
- attrs: { "role": "dialog", "aria-labelledby": "newGameTxt" },
- },
- [
- h('div',
- {
- "class": { "card": true, "smallpad": true },
- },
- [
- h('label',
- {
- attrs: { "id": "close-newgame", "for": "modal-newgame" },
- "class": { "modal-close": true },
- }
- ),
- h('h3',
- {
- attrs: { "id": "newGameTxt" },
- "class": { "section": true },
- domProps: { innerHTML: "New game" },
- }
- ),
- h('p',
- {
- "class": { "section": true },
- domProps: { innerHTML: "Waiting for opponent..." },
- }
- )
- ]
- )
- ]
- )
- ];
- elementArray = elementArray.concat(modalNewgame);
const modalFenEdit = [
h('input',
{
{
attrs: { "id": "titleFenedit" },
"class": { "section": true },
- domProps: { innerHTML: "Position + flags (FEN):" },
+ domProps: { innerHTML: translations["Position + flags (FEN):"] },
}
),
h('input',
this.newGame("friend", fen);
}
},
- domProps: { innerHTML: "Ok" },
+ domProps: { innerHTML: translations["Ok"] },
}
),
h('button',
VariantRules.GenRandInitFen();
}
},
- domProps: { innerHTML: "Random" },
+ domProps: { innerHTML: translations["Random"] },
}
),
]
{
attrs: { "id": "settingsTitle" },
"class": { "section": true },
- domProps: { innerHTML: "Preferences" },
+ domProps: { innerHTML: translations["Preferences"] },
}
),
h('fieldset',
h('label',
{
attrs: { for: "nameSetter" },
- domProps: { innerHTML: "My name is..." },
+ domProps: { innerHTML: translations["My name is..."] },
},
),
h('input',
h('label',
{
attrs: { for: "setHints" },
- domProps: { innerHTML: "Show hints?" },
+ domProps: { innerHTML: translations["Show hints?"] },
},
),
h('input',
h('label',
{
attrs: { for: "selectColor" },
- domProps: { innerHTML: "Board colors" },
+ domProps: { innerHTML: translations["Board colors"] },
},
),
h("select",
{
domProps: {
"value": "lichess",
- innerHTML: "brown"
+ innerHTML: translations["brown"]
},
attrs: { "selected": this.color=="lichess" },
}
{
domProps: {
"value": "chesscom",
- innerHTML: "green"
+ innerHTML: translations["green"]
},
attrs: { "selected": this.color=="chesscom" },
}
{
domProps: {
"value": "chesstempo",
- innerHTML: "blue"
+ innerHTML: translations["blue"]
},
attrs: { "selected": this.color=="chesstempo" },
}
h('label',
{
attrs: { for: "selectSound" },
- domProps: { innerHTML: "Play sounds?" },
+ domProps: { innerHTML: translations["Play sounds?"] },
},
),
h("select",
{
domProps: {
"value": "0",
- innerHTML: "None"
+ innerHTML: translations["None"]
},
attrs: { "selected": this.sound==0 },
}
{
domProps: {
"value": "1",
- innerHTML: "Newgame"
+ innerHTML: translations["New game"]
},
attrs: { "selected": this.sound==1 },
}
{
domProps: {
"value": "2",
- innerHTML: "All"
+ innerHTML: translations["All"]
},
attrs: { "selected": this.sound==2 },
}
{
attrs: { "id": "titleChat" },
"class": { "section": true },
- domProps: { innerHTML: "Chat with " + this.oppName },
+ domProps: { innerHTML: translations["Chat with "] + this.oppName },
}
)
];
attrs: {
"id": "input-chat",
type: "text",
- placeholder: "Type here",
+ placeholder: translations["Type here"],
},
on: { keyup: this.trySendChat }, //if key is 'enter'
}
),
h('button',
{
+ attrs: { id: "sendChatBtn"},
on: { click: this.sendChat },
- domProps: { innerHTML: "Send" },
+ domProps: { innerHTML: translations["Send"] },
}
)
]);
{
attrs: { "id": "downloadBtn" },
on: { click: this.download },
- domProps: { innerHTML: "Download game" },
+ domProps: { innerHTML: translations["Download game"] },
}
),
]
[
h('h3',
{
- domProps: { innerHTML: "Show solution" },
+ "class": { clickable: true },
+ domProps: { innerHTML: translations["Show solution"] },
on: { click: this.toggleShowSolution },
}
),
h('p',
{
attrs: { id: "fen-string" },
- domProps: { innerHTML: this.vr.getBaseFen() }
+ domProps: { innerHTML: this.vr.getBaseFen() },
+ "class": { "text-center": true },
}
)
]
{
'class': {
"col-sm-12":true,
- "col-md-8":true,
- "col-md-offset-2":true,
- "col-lg-6":true,
- "col-lg-offset-3":true,
+ "col-md-10":true,
+ "col-md-offset-1":true,
+ "col-lg-8":true,
+ "col-lg-offset-2":true,
},
// NOTE: click = mousedown + mouseup
on: {
switch (this.score)
{
case "1-0":
- eogMessage = "White win";
+ eogMessage = translations["White win"];
break;
case "0-1":
- eogMessage = "Black win";
+ eogMessage = translations["Black win"];
break;
case "1/2":
- eogMessage = "Draw";
+ eogMessage = translations["Draw"];
break;
}
return eogMessage;
methods: {
setMyname: function(e) {
this.myname = e.target.value;
- setCookie("username",this.myname);
+ localStorage["username"] = this.myname;
},
trySendChat: function(e) {
if (e.keyCode == 13) //'enter' key
},
toggleHints: function() {
this.hints = !this.hints;
- setCookie("hints", this.hints ? "1" : "0");
+ localStorage["hints"] = (this.hints ? "1" : "0");
},
setColor: function(e) {
this.color = e.target.options[e.target.selectedIndex].value;
- setCookie("color", this.color);
+ localStorage["color"] = this.color;
},
setSound: function(e) {
this.sound = parseInt(e.target.options[e.target.selectedIndex].value);
- setCookie("sound", this.sound);
+ localStorage["sound"] = this.sound;
},
clickGameSeek: function(e) {
this.getRidOfTooltip(e.currentTarget);
// Not programmatic, or animation is over
if (this.mode == "human" && this.vr.turn == this.mycolor)
this.conn.send(JSON.stringify({code:"newmove", move:move, oppid:this.oppid}));
- if (this.sound == 2)
- new Audio("/sounds/chessmove1.mp3").play().catch(err => {});
if (!["idle","chat"].includes(this.mode))
{
// Emergency check, if human game started "at the same time"
return;
this.incheck = this.vr.getCheckSquares(move); //is opponent in check?
this.vr.play(move, "ingame");
+ if (this.sound == 2)
+ new Audio("/sounds/move.mp3").play().catch(err => {});
if (this.mode == "computer")
{
// Send the move to web worker (TODO: including his own moves?!)
if (!!lm)
{
this.vr.undo(lm);
+ if (this.sound == 2)
+ new Audio("/sounds/undo.mp3").play().catch(err => {});
const lmBefore = this.vr.lastMove;
if (!!lmBefore)
{