528 lines
18 KiB
JavaScript
528 lines
18 KiB
JavaScript
const UI = {
|
|
Row:class{
|
|
constructor(element, css_class) {
|
|
this.element = element;
|
|
this.css_class = css_class;
|
|
}
|
|
},
|
|
|
|
text(value) {
|
|
return document.createTextNode(value);
|
|
},
|
|
|
|
link(text, callback=null) {
|
|
let link = document.createElement("a");
|
|
link.innerText = text;
|
|
if(callback !== null) { link.addEventListener("click", callback); }
|
|
return link;
|
|
},
|
|
|
|
button(text, callback=null, select=false) {
|
|
let button = document.createElement("button");
|
|
button.innerText = text;
|
|
if(select) { button.setAttribute("class", "selected"); }
|
|
if(callback !== null) { button.addEventListener("click", callback); }
|
|
return button;
|
|
},
|
|
|
|
button_piece(piece, callback=null, select=false) {
|
|
let button = document.createElement("button");
|
|
let moves = document.createElement("canvas");
|
|
button.appendChild(moves);
|
|
setTimeout(UI.draw_play_icons, 10, moves, [piece]);
|
|
if(select) { button.setAttribute("class", "selected"); }
|
|
if(callback !== null) { button.addEventListener("click", callback); }
|
|
return button;
|
|
},
|
|
|
|
submit(text) {
|
|
let button = document.createElement("input");
|
|
button.setAttribute("type", "submit");
|
|
button.value = text;
|
|
return button;
|
|
},
|
|
|
|
slider(id, callback) {
|
|
let input = document.createElement("input");
|
|
if(id !== null) { input.setAttribute("id", id); }
|
|
input.setAttribute("type", "range");
|
|
input.setAttribute("value", "0");
|
|
input.setAttribute("min", "0");
|
|
input.setAttribute("max", "0");
|
|
if(callback !== null) { input.addEventListener("input", callback); }
|
|
return input;
|
|
},
|
|
|
|
checkbox(id, callback) {
|
|
let input = document.createElement("input");
|
|
if(id !== null) { input.setAttribute("id", id); }
|
|
input.setAttribute("type", "checkbox");
|
|
if(callback !== null) { input.addEventListener("change", callback); }
|
|
return input;
|
|
},
|
|
|
|
textbox(id, placeholder) {
|
|
let input = document.createElement("input");
|
|
input.setAttribute("type", "text");
|
|
if(id !== null) { input.setAttribute("id", id); }
|
|
input.setAttribute("placeholder", placeholder);
|
|
return input;
|
|
},
|
|
|
|
password(id) {
|
|
let input = document.createElement("input");
|
|
input.setAttribute("type", "password");
|
|
input.setAttribute("placeholder", "◌◌◌◌◌◌");
|
|
if(id !== null) { input.setAttribute("id", id); }
|
|
return input;
|
|
},
|
|
|
|
label(name, id) {
|
|
let label = document.createElement("label");
|
|
label.setAttribute("for", id);
|
|
label.innerText = name;
|
|
return label;
|
|
},
|
|
|
|
span(children, attr_class) {
|
|
let span = document.createElement("span");
|
|
if(attr_class !== undefined) { span.setAttribute("class", attr_class); }
|
|
for(child of children) { span.appendChild(child); }
|
|
return span;
|
|
},
|
|
|
|
div(children, attr_class) {
|
|
let div = document.createElement("div");
|
|
if(attr_class !== undefined) { div.setAttribute("class", attr_class); }
|
|
for(child of children) { div.appendChild(child); }
|
|
return div;
|
|
},
|
|
|
|
maincontent(element) {
|
|
let box = document.createElement("div");
|
|
box.setAttribute("class", "box");
|
|
box.appendChild(element);
|
|
MAIN.appendChild(box);
|
|
},
|
|
|
|
table_content(header, rows) {
|
|
let tbody = document.createElement("tbody");
|
|
|
|
if(header !== null) {
|
|
let row = document.createElement("tr");
|
|
for(head of header) {
|
|
let cell = document.createElement("th");
|
|
cell.innerText = head;
|
|
row.appendChild(cell);
|
|
}
|
|
tbody.appendChild(row);
|
|
}
|
|
|
|
for(row of rows) {
|
|
let tr = document.createElement("tr");
|
|
for(node of row) {
|
|
let cell = document.createElement("td");
|
|
if(Array.isArray(node)) { for(item of node) { cell.appendChild(item); } }
|
|
else { cell.appendChild(node); }
|
|
tr.appendChild(cell);
|
|
}
|
|
tbody.appendChild(tr);
|
|
}
|
|
|
|
return tbody;
|
|
},
|
|
|
|
table(header, rows) {
|
|
let table = document.createElement("table");
|
|
table.appendChild(this.table_content(header, rows));
|
|
return table;
|
|
},
|
|
|
|
mainnav(left_children, right_children, features={}) {
|
|
let header = document.createElement("nav");
|
|
let left = document.createElement("section");
|
|
|
|
if(sessionStorage.getItem("auth") === null) {
|
|
if(features.auth === true) {
|
|
left.appendChild(UI.button(LANG("register"), () => { SCENE.load(SCENES.Register); }));
|
|
left.appendChild(UI.button(LANG("login"), () => { SCENE.load(SCENES.Authenticate); }));
|
|
}
|
|
} else {
|
|
if(features.session === true) {
|
|
let button_challenge = UI.button(LANG("requests"), () => { SCENE.load(SCENES.Requests); });
|
|
button_challenge.setAttribute("id", "button-requests");
|
|
|
|
left.appendChild(UI.button(LANG("users"), () => { SCENE.load(SCENES.Users); }));
|
|
left.appendChild(button_challenge);
|
|
}
|
|
}
|
|
|
|
for(child of left_children) { left.appendChild(child); }
|
|
|
|
let right = document.createElement("section");
|
|
for(child of right_children) { right.appendChild(child); }
|
|
|
|
header.appendChild(left);
|
|
header.appendChild(right);
|
|
|
|
MAIN.appendChild(header);
|
|
},
|
|
|
|
nav(top, bottom) {
|
|
let section = document.createElement("section");
|
|
for(node of top) { section.appendChild(node); }
|
|
MENU.appendChild(section);
|
|
|
|
section = document.createElement("section");
|
|
for(node of bottom) { section.appendChild(node); }
|
|
MENU.appendChild(section);
|
|
},
|
|
|
|
mainmenu(page) {
|
|
if(SOCKET !== null) {
|
|
let top = [ ];
|
|
let bottom = [ ];
|
|
|
|
top.push(UI.button(LANG("browse"), () => { SCENE.load(SCENES.Browse); }, page == "browse"));
|
|
if(sessionStorage.getItem("auth") !== null) {
|
|
let button_resume = UI.button(LANG("resume"), () => { SCENE.load(SCENES.Continue); }, page == "continue");
|
|
button_resume.setAttribute("id", "button-resume");
|
|
|
|
top.push(button_resume);
|
|
//top.push(UI.button("Join", () => { SCENE.load(SCENES.Join); }, page == "join"));
|
|
}
|
|
top.push(UI.button(LANG("live"), () => { SCENE.load(SCENES.Live); }, page == "live"));
|
|
top.push(UI.button(LANG("history"), () => { SCENE.load(SCENES.History); }, page == "history"));
|
|
top.push(UI.button(LANG("practice"), () => { SCENE.load(SCENES.GamePractice); }, page == "practice"));
|
|
top.push(UI.button(LANG("guide"), () => { SCENE.load(SCENES.Guide); }, page == "guide"));
|
|
top.push(UI.button(LANG("about"), () => { SCENE.load(SCENES.About); }, page == "about"));
|
|
|
|
if(CONTEXT.Auth !== null) {
|
|
bottom.push(UI.button(LANG("account"), () => { SCENE.load(SCENES.Account); }));
|
|
}
|
|
bottom.push(UI.button(LANG("extras"), () => { SCENE.load(SCENES.Extras) }, page == "extras"));
|
|
|
|
UI.nav(top, bottom);
|
|
}
|
|
},
|
|
|
|
mainmenu_account(handle, page) {
|
|
let buttons_top = [ ];
|
|
let buttons_bottom = [ ];
|
|
|
|
// Top Buttons
|
|
buttons_top.push(UI.button("Profile", () => { SCENE.load(SCENES.Profile, { handle:CONTEXT.Auth.handle }) }, page == "profile"));
|
|
|
|
// Bottom Buttons
|
|
if(CONTEXT.Auth !== null && (handle === null || handle == CONTEXT.Auth.handle)) {
|
|
buttons_bottom.push(UI.button("Account", () => { SCENE.load(SCENES.Account) }, page == "account"));
|
|
buttons_bottom.push(UI.button("Invitations", () => { SCENE.load(SCENES.Invitations) }, page == "invitations"));
|
|
}
|
|
buttons_bottom.push(UI.button(LANG("back"), () => { SCENE.load(SCENES.Browse); }));
|
|
|
|
UI.nav(buttons_top, buttons_bottom);
|
|
},
|
|
|
|
mainmenu_guide(page, game_buttons=false) {
|
|
let buttons_top = [ ];
|
|
let buttons_bottom = [ ];
|
|
|
|
// Top Buttons
|
|
buttons_top.push(UI.button("Pieces", () => { SCENE.load(SCENES.Guide); }, page == "guide_pieces"));
|
|
buttons_top.push(UI.button("Dropping", () => { SCENE.load(SCENES.Guide, "drop"); }, page == "guide_drop"));
|
|
buttons_top.push(UI.button("Promotion", () => { SCENE.load(SCENES.Guide, "promote"); }, page == "guide_promote"));
|
|
buttons_top.push(UI.button("Check", () => { SCENE.load(SCENES.Guide, "check"); }, page == "guide_check"));
|
|
buttons_top.push(UI.button("Checkmate", () => { SCENE.load(SCENES.Guide, "checkmate"); }, page == "guide_checkmate"));
|
|
|
|
// Bottom Buttons
|
|
if(game_buttons) {
|
|
buttons_bottom.push(UI.button(LANG("undo"), () => { INTERFACE.undo(); }));
|
|
buttons_bottom.push(UI.button(LANG("reset"), () => { INTERFACE.reset(); }));
|
|
}
|
|
buttons_bottom.push(UI.button(LANG("back"), () => { SCENE.load(SCENES.Browse); }));
|
|
|
|
UI.nav(buttons_top, buttons_bottom);
|
|
},
|
|
|
|
session_table(records) {
|
|
let rows = [ ];
|
|
|
|
for(let r = 0; r < records.length; ++r) {
|
|
let record = records[r];
|
|
|
|
let buttons = [ ];
|
|
let join_callback = function() {
|
|
SCENE.load(SCENES.Game, {
|
|
token:this.token,
|
|
mode:INTERFACE.Mode.Player,
|
|
});
|
|
};
|
|
join_callback = join_callback.bind({
|
|
token: record.token,
|
|
});
|
|
|
|
let spectate_callback = function() {
|
|
SCENE.load(SCENES.Game, {
|
|
token:this.token,
|
|
mode:INTERFACE.Mode.Review,
|
|
});
|
|
};
|
|
spectate_callback = spectate_callback.bind({
|
|
token: record.token,
|
|
});
|
|
|
|
if(record.player != 0) {
|
|
let button_resume = UI.button(LANG("resume"), join_callback);
|
|
if(record.is_turn) {
|
|
button_resume.setAttribute("class", "highlight");
|
|
}
|
|
|
|
buttons.push(button_resume);
|
|
buttons.push(UI.button(LANG("review"), spectate_callback));
|
|
} else {
|
|
buttons.push(UI.button(LANG("view"), spectate_callback));
|
|
}
|
|
|
|
let callback_profile_dawn = function() { SCENE.load(SCENES.Profile, { handle: this.handle }); }
|
|
callback_profile_dawn = callback_profile_dawn.bind({ handle: record.dawn });
|
|
|
|
let callback_profile_dusk = function() { SCENE.load(SCENES.Profile, { handle: this.handle }); }
|
|
callback_profile_dusk = callback_profile_dusk.bind({ handle: record.dusk });
|
|
|
|
let dawn = UI.link(record.dawn, callback_profile_dawn);
|
|
let dusk = UI.link(record.dusk, callback_profile_dusk);
|
|
|
|
let moves = document.createElement("canvas");
|
|
setTimeout(UI.draw_play_icons, 10, moves, record.moves);
|
|
|
|
rows.push([
|
|
dawn,
|
|
dusk,
|
|
UI.text(records[r].turn),
|
|
moves,
|
|
UI.text(records[r].viewers),
|
|
buttons,
|
|
]);
|
|
}
|
|
|
|
let tbody = UI.table_content(
|
|
[ LANG("dawn"), LANG("dusk"), LANG("turns"), "", LANG("viewers"), "" ],
|
|
rows,
|
|
);
|
|
|
|
return tbody;
|
|
},
|
|
|
|
session_table_resume(records) {
|
|
let rows = [ ];
|
|
|
|
for(let r = 0; r < records.length; ++r) {
|
|
let buttons = [ ];
|
|
let join_callback = function() {
|
|
SCENE_FORWARD = SCENE;
|
|
SCENE.load(SCENES.Game, {
|
|
token:this.token,
|
|
mode:INTERFACE.Mode.Player,
|
|
});
|
|
};
|
|
join_callback = join_callback.bind({token: records[r].token});
|
|
|
|
let spectate_callback = function() {
|
|
SCENE_FORWARD = SCENE;
|
|
SCENE.load(SCENES.Game, {
|
|
token:this.token,
|
|
mode:INTERFACE.Mode.Review,
|
|
});
|
|
};
|
|
spectate_callback = spectate_callback.bind({token: records[r].token});
|
|
|
|
let button_resume = UI.button(LANG("resume"), join_callback);
|
|
if(records[r].is_turn) {
|
|
button_resume.setAttribute("class", "highlight");
|
|
}
|
|
|
|
buttons.push(button_resume);
|
|
buttons.push(UI.button(LANG("review"), spectate_callback));
|
|
|
|
let handle = records[r].dawn;
|
|
if(records[r].player == 1) { handle = records[r].dusk; }
|
|
|
|
let callback_profile = function() { SCENE.load(SCENES.Profile, { handle: this.handle }); }
|
|
callback_profile = callback_profile.bind({ handle: handle });
|
|
|
|
let link_handle = UI.link(handle, callback_profile);
|
|
|
|
rows.push([
|
|
link_handle,
|
|
UI.text(records[r].turn),
|
|
UI.text(records[r].viewers),
|
|
buttons,
|
|
]);
|
|
}
|
|
|
|
let tbody = UI.table_content(
|
|
[ LANG("handle"), LANG("turns"), LANG("viewers"), "" ],
|
|
rows,
|
|
);
|
|
|
|
return tbody;
|
|
},
|
|
|
|
session_table_history(records) {
|
|
let rows = [ ];
|
|
|
|
for(let r = 0; r < records.length; ++r) {
|
|
let record = records[r];
|
|
|
|
let buttons = [ ];
|
|
let view_callback = function() {
|
|
SCENE_FORWARD = SCENE;
|
|
SCENE.load(SCENES.Game, {
|
|
token:this.token,
|
|
mode:INTERFACE.Mode.Review,
|
|
});
|
|
MESSAGE_SESSION_VIEW(this.token, false);
|
|
};
|
|
view_callback = view_callback.bind({token: record.token});
|
|
|
|
buttons.push(UI.button(LANG("review"), view_callback));
|
|
|
|
let callback_profile_dawn = function() { SCENE.load(SCENES.Profile, { handle: this.handle }); }
|
|
callback_profile_dawn = callback_profile_dawn.bind({ handle: record.dawn });
|
|
|
|
let callback_profile_dusk = function() { SCENE.load(SCENES.Profile, { handle: this.handle }); }
|
|
callback_profile_dusk = callback_profile_dusk.bind({ handle: record.dusk });
|
|
|
|
let dawn = UI.link(record.dawn, callback_profile_dawn);
|
|
let dusk = UI.link(record.dusk, callback_profile_dusk);
|
|
|
|
switch(record.is_complete) {
|
|
case 1: dawn = UI.span([dawn], "c_dawn bold"); break;
|
|
case 2: dusk = UI.span([dusk], "c_dusk bold"); break;
|
|
}
|
|
|
|
let moves = document.createElement("canvas");
|
|
setTimeout(UI.draw_play_icons, 10, moves, record.moves);
|
|
|
|
rows.push([
|
|
dawn,
|
|
dusk,
|
|
UI.text(record.turn),
|
|
moves,
|
|
buttons,
|
|
]);
|
|
}
|
|
|
|
let tbody = UI.table_content(
|
|
[ LANG("dawn"), LANG("dusk"), LANG("turns"), "", "" ],
|
|
rows,
|
|
);
|
|
|
|
return tbody;
|
|
},
|
|
|
|
invite_table(records) {
|
|
let rows = [ ];
|
|
|
|
for(let r = 0; r < records.length; ++r) {
|
|
let record = records[r];
|
|
|
|
rows.push([
|
|
UI.span([UI.text(record)], "monospace"),
|
|
UI.text(""),
|
|
]);
|
|
}
|
|
|
|
let tbody = UI.table_content(
|
|
[ LANG("invitation"), "" ],
|
|
rows,
|
|
);
|
|
|
|
return tbody;
|
|
},
|
|
|
|
page_indicator(first, last, total) {
|
|
let ind = document.getElementById("indicator-page");
|
|
UI.clear(ind);
|
|
ind.appendChild(UI.text(LANG_PAGEOF(first, last, total)));
|
|
},
|
|
|
|
clear(dom) {
|
|
while(dom.lastChild !== null) { dom.removeChild(dom.lastChild); }
|
|
},
|
|
|
|
rebuild() {
|
|
this.clear(document.body);
|
|
|
|
MENU = document.createElement("nav");
|
|
let title = document.createElement("header");
|
|
title.innerText = "Dzura";
|
|
MENU.appendChild(title);
|
|
|
|
MAIN = document.createElement("main");
|
|
|
|
document.body.appendChild(MENU);
|
|
document.body.appendChild(MAIN);
|
|
},
|
|
|
|
update_status() {
|
|
let b_requests = document.getElementById("button-requests");
|
|
let b_resume = document.getElementById("button-resume");
|
|
|
|
if(b_requests !== null) {
|
|
let text = LANG("requests");
|
|
|
|
if(STATUS.challenge > 0) {
|
|
if(STATUS.challenge < 10) {
|
|
text += " " + String.fromCharCode("❶".charCodeAt(0) + (STATUS.challenge - 1));
|
|
} else {
|
|
text += " ❾";
|
|
}
|
|
} else {
|
|
text += " ⓿";
|
|
}
|
|
|
|
b_requests.innerText = text;
|
|
}
|
|
|
|
if(b_resume !== null) {
|
|
let text = LANG("resume");
|
|
|
|
if(STATUS.resume > 0) {
|
|
if(STATUS.resume < 10) {
|
|
text += " " + String.fromCharCode("❶".charCodeAt(0) + (STATUS.resume - 1));
|
|
} else {
|
|
text += " ❾";
|
|
}
|
|
} else {
|
|
text += " ⓿";
|
|
}
|
|
|
|
b_resume.innerText = text;
|
|
}
|
|
},
|
|
|
|
draw_play_icons(canvas, moves) {
|
|
canvas.width = canvas.clientWidth * (window.devicePixelRatio || 1);
|
|
canvas.height = canvas.clientHeight * (window.devicePixelRatio || 1);
|
|
let ctx = canvas.getContext("2d");
|
|
|
|
let size = canvas.height / 2;
|
|
|
|
for(let i = 0; i < moves.length; ++i) {
|
|
let piece = moves[i] & 0x7;
|
|
let promoted = (moves[i] & 0x8) >> 3;
|
|
let player = (moves[i] & 0x10) >> 4;
|
|
|
|
let color = null;
|
|
if(player == 0) { color = INTERFACE.Color.Dawn; } else { color = INTERFACE.Color.Dusk; }
|
|
|
|
let piece_name = GAME.Const.Piece[piece].name;
|
|
if(promoted) {
|
|
GAME_ASSET.Image.Promote.draw(ctx, canvas.height, [size * (1 + (2 * i)), size], INTERFACE.Color.Promote);
|
|
}
|
|
GAME_ASSET.Image[piece_name].draw(ctx, canvas.height, [size * (1 + (2 * i)), size], color);
|
|
}
|
|
},
|
|
};
|