const UI = { text(value) { return document.createTextNode(value); }, button(text, callback, 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; }, 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"); 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; }, 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"), () => { LOAD(SCENES.Register); })); left.appendChild(UI.button(LANG("login"), () => { LOAD(SCENES.Authenticate); })); } } else { if(features.session === true) { //left.appendChild(UI.button("Await", () => { })); left.appendChild(UI.button(LANG("challenge"), () => { LOAD(SCENES.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"), () => { LOAD(SCENES.Browse); }, page == "browse")); if(sessionStorage.getItem("auth") !== null) { top.push(UI.button(LANG("resume"), () => { LOAD(SCENES.Continue); }, page == "continue")); //top.push(UI.button("Join", () => { LOAD(SCENES.Join); }, page == "join")); } top.push(UI.button(LANG("live"), () => { LOAD(SCENES.Live); }, page == "live")); top.push(UI.button(LANG("history"), () => { LOAD(SCENES.History); }, page == "history")); top.push(UI.button(LANG("practice"), () => { LOAD(SCENES.GamePractice); }, page == "practice")); top.push(UI.button(LANG("guide"), () => { LOAD(SCENES.Guide); }, page == "guide")); top.push(UI.button(LANG("about"), () => { LOAD(SCENES.About); }, page == "about")); if(sessionStorage.getItem("auth") !== null) { bottom.push(UI.button("Logout", () => { MESSAGE_COMPOSE([ PACK.u16(OpCode.Deauthenticate), ]); sessionStorage.clear(); LOAD_URL(); })); } UI.nav(top, bottom); } }, session_table(records) { let rows = [ ]; for(let r = 0; r < records.length; ++r) { let buttons = [ ]; let join_callback = function() { LOAD(SCENES.Game, { token:this.token, mode:INTERFACE.Mode.Player, }); MESSAGE_SESSION_VIEW(this.token, true); }; join_callback = join_callback.bind({token: records[r].token}); let spectate_callback = function() { LOAD(SCENES.Game, { token:this.token, mode:INTERFACE.Mode.Review, }); MESSAGE_SESSION_VIEW(this.token, false); }; spectate_callback = spectate_callback.bind({token: records[r].token}); if(records[r].player != 0) { 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)); } else { buttons.push(UI.button(LANG("view"), spectate_callback)); } let dawn = UI.text(records[r].dawn); let dusk = UI.text(records[r].dusk); rows.push([ dawn, dusk, UI.text(records[r].turn), UI.text(records[r].viewers), buttons, ]); } let tbody = UI.table_content( [ LANG("dawn"), LANG("dusk"), LANG("turn"), 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; LOAD(SCENES.Game, { token:this.token, mode:INTERFACE.Mode.Player, }); MESSAGE_SESSION_VIEW(this.token, true); }; join_callback = join_callback.bind({token: records[r].token}); let spectate_callback = function() { SCENE_FORWARD = SCENE; LOAD(SCENES.Game, { token:this.token, mode:INTERFACE.Mode.Review, }); MESSAGE_SESSION_VIEW(this.token, false); }; 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; } rows.push([ UI.text(handle), UI.text(records[r].turn), UI.text(records[r].viewers), buttons, ]); } let tbody = UI.table_content( [ LANG("handle"), LANG("turn"), LANG("viewers"), "" ], rows, ); return tbody; }, /*session_table_join(records) { let rows = [ ]; for(let r = 0; r < records.length; ++r) { let buttons = [ ]; let join_callback = function() { LOAD(SCENES.Game, { token:this.token, mode:INTERFACE.Mode.Player, }); MESSAGE_SESSION_VIEW(this.token, true); }; join_callback = join_callback.bind({token: records[r].token}); if(records[r].player) { buttons.push(UI.button("View", join_callback)); } else { buttons.push(UI.button("Join", join_callback)); } let host = UI.text(records[r].dawn); if(records[r].dawn == "") { dawn = UI.span([UI.text("Vacant")], "text-system"); } rows.push([ host, buttons, ]); } let tbody = UI.table_content( [ "Host", "" ], rows, ); return tbody; },*/ session_table_history(records) { let rows = [ ]; for(let r = 0; r < records.length; ++r) { let buttons = [ ]; let view_callback = function() { SCENE_FORWARD = SCENE; LOAD(SCENES.Game, { token:this.token, mode:INTERFACE.Mode.Review, }); MESSAGE_SESSION_VIEW(this.token, false); }; view_callback = view_callback.bind({token: records[r].token}); buttons.push(UI.button(LANG("review"), view_callback)); let dawn = UI.text(records[r].dawn); let dusk = UI.text(records[r].dusk); rows.push([ dawn, dusk, UI.text(records[r].turn), buttons, ]); } let tbody = UI.table_content( [ LANG("dawn"), LANG("dusk"), LANG("turns"), "" ], 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 = "Omen"; MENU.appendChild(title); MAIN = document.createElement("main"); document.body.appendChild(MENU); document.body.appendChild(MAIN); }, };