// #def.{}.stuff
// generated by server
+type PieceId = string;
+type PlayerId = string;
+type Pos = [number, number];
+type ClientSeq = number;
+type Generation = number;
+
+type MessageHandler = (op: Object) => void;
+type PieceHandler = (piece: PieceId, info: Object) => void;
+interface DispatchTable<H> { [key: string]: H };
+
var general_timeout : number = 10000;
-var messages = Object();
-var pieceops = Object();
+var messages : DispatchTable<MessageHandler> = Object();
+var pieceops : DispatchTable<PieceHandler> = Object();
var our_dnd_type = "text/puvnex-game-server-dummy";
-var api_queue = [];
+var api_queue : [string, Object][] = [];
var api_posting = false;
-var us;
+var us : string;
var gen = 0;
-var cseq = 0;
+var cseq : ClientSeq = 0;
var ctoken : string;
var svg_ns : string;
var logdiv : HTMLElement;
var status_node : HTMLElement;
-var dox : number;
-var doy : number;
-var dcx : number;
-var dcy : number;
-const DRAGTHRESH = 5;
-function xhr_post_then(url,data,good) {
- var xhr = new XMLHttpRequest();
+function xhr_post_then(url : string, data: string,
+ good : (xhr: XMLHttpRequest) => void) {
+ var xhr : XMLHttpRequest = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (xhr.readyState != XMLHttpRequest.DONE) { return; }
if (xhr.status != 200) { xhr_report_error(xhr); }
xhr.send(data);
}
-function xhr_report_error(xhr) {
+function xhr_report_error(xhr: XMLHttpRequest) {
json_report_error({
statusText : xhr.statusText,
responseText : xhr.responseText,
});
}
-function json_report_error(error_json) {
- let error_message = JSON.stringify(error_json);
- let errornode = document.getElementById('error');
+function json_report_error(error_for_json: Object) {
+ let error_message = JSON.stringify(error_for_json);
+ let errornode = document.getElementById('error')!;
errornode.textContent = 'Error (reloading may help?):' + error_message;
}
-function api(meth, data) {
+function api(meth: string, data: Object) {
api_queue.push([meth, data]);
api_check();
}
-function api_delay(meth, data) {
+function api_delay(meth: string, data: Object) {
api_queue.push([meth, data]);
window.setTimeout(api_check, 10);
}
if (api_posting) { return; }
if (!api_queue.length) { return; }
do {
- var [meth, data] = api_queue.shift();
+ var [meth, data] = api_queue.shift()!;
} while (meth == 'm' &&
api_queue.length &&
api_queue[0][0] == meth);
api_check();
}
-function api_piece(f, meth, piece, uelem, op) {
+function api_piece(f: (meth: string, payload: Object) => void,
+ meth: string, piece: string,
+ uelem: SVGGraphicsElement, op: Object) {
cseq += 1;
- uelem.dataset.cseq = cseq;
+ uelem.dataset.cseq! = cseq+"";
f(meth, {
ctoken : ctoken,
piece : piece,
YES : 4,
};
-var drag_uelem;
+var drag_uelem : SVGGraphicsElement | null;
var dragging = DRAGGING.NO;
-function drag_mousedown(e) {
+var dox : number | null;
+var doy : number | null;
+var dcx : number | null;
+var dcy : number | null;
+
+const DRAGTHRESH = 5;
+
+function drag_mousedown(e : MouseEvent) {
console.log('mousedown', e);
- var piece = e.target.dataset.piece;
+ var target = e.target as SVGGraphicsElement; // we check this just now!
+ var piece = target.dataset.piece;
if (!piece) { return; }
drag_cancel();
- drag_uelem = e.target;
+ drag_uelem = target;
var gplayer = drag_uelem.dataset.gplayer;
if (gplayer != "" && gplayer != us) { return; }
dcx = e.clientX;
dcy = e.clientY;
- dox = parseFloat(drag_uelem.getAttributeNS(null,"x"));
- doy = parseFloat(drag_uelem.getAttributeNS(null,"y"));
+ dox = parseFloat(drag_uelem.getAttributeNS(null,"x")!);
+ doy = parseFloat(drag_uelem.getAttributeNS(null,"y")!);
if (gplayer == us) {
dragging = DRAGGING.MAYBE_UNGRAB;
window.addEventListener('mouseup', drag_mouseup, true);
}
-function set_grab(uelem, piece, owner) {
+function set_grab(uelem: SVGGraphicsElement, piece: PieceId, owner: PlayerId) {
uelem.dataset.gplayer = owner;
// var [p, piece] =
var pelem = piece_cleanup_grab(piece);
pelem.appendChild(nelem);
return pelem;
}
-function set_ungrab(uelem, piece) {
+function set_ungrab(uelem: SVGGraphicsElement, piece: PieceId) {
uelem.dataset.gplayer = "";
var pelem = piece_cleanup_grab(piece);
return pelem;
}
-function piece_cleanup_grab(piece) {
- var pelem = document.getElementById('piece'+piece);
+function piece_cleanup_grab(piece: PieceId) {
+ var pelem = document.getElementById('piece'+piece)!;
while (pelem.children.length > 1) {
- pelem.lastElementChild.remove();
+ pelem.lastElementChild!.remove();
}
return pelem;
}
-function drag_mousemove(e) {
- var ctm = space.getScreenCTM();
- var ddx = (e.clientX - dcx)/ctm.a;
- var ddy = (e.clientY - dcy)/ctm.d;
+function drag_mousemove(e: MouseEvent) {
+ var ctm = space.getScreenCTM()!;
+ var ddx = (e.clientX - dcx!)/ctm.a;
+ var ddy = (e.clientY - dcy!)/ctm.d;
if (!(dragging & DRAGGING.YES)) {
var ddr2 = ddx*ddx + ddy*ddy;
if (ddr2 > DRAGTHRESH) {
}
//console.log('mousemove', ddx, ddy, dragging);
if (dragging & DRAGGING.YES) {
- var x = Math.round(dox + ddx);
- var y = Math.round(doy + ddy);
- drag_uelem.setAttributeNS(null, "x", x);
- drag_uelem.setAttributeNS(null, "y", y);
- var piece = drag_uelem.dataset.piece;
+ var x = Math.round(dox! + ddx);
+ var y = Math.round(doy! + ddy);
+ drag_uelem!.setAttributeNS(null, "x", x+"");
+ drag_uelem!.setAttributeNS(null, "y", y+"");
+ var piece = drag_uelem!.dataset.piece!;
var pelem = document.getElementById('piece'+piece);
- api_piece(api_delay, 'm', piece, drag_uelem, [x, y] );
+ api_piece(api_delay, 'm', piece, drag_uelem!, [x, y] );
}
}
-function drag_mouseup(e) {
+function drag_mouseup(e: MouseEvent) {
console.log('mouseup', dragging);
drag_mousemove(e);
//console.log('mouseup ...', dragging);
if (dragging == DRAGGING.MAYBE_UNGRAB ||
dragging == (DRAGGING.MAYBE_GRAB | DRAGGING.YES)) {
- var piece = drag_uelem.dataset.piece;
- var pelem = set_ungrab(drag_uelem, piece);
- api_piece(api, 'ungrab', drag_uelem.dataset.piece, drag_uelem, { });
+ var piece = drag_uelem!.dataset.piece!;
+ var pelem = set_ungrab(drag_uelem!, piece);
+ api_piece(api, 'ungrab', drag_uelem!.dataset.piece!, drag_uelem!, { });
}
drag_cancel();
}
// ----- logs -----
-messages.Log = function(j) {
+messages.Log = <MessageHandler>function
+(j: { html: string }) {
add_log_message(j.html);
}
-function add_log_message(msg_html) {
+//interface Message_Log_Payload { html: string };
+//messages.Log = function(j: Message_Log_Payload) {
+// add_log_message(j.html);
+//}
+
+function add_log_message(msg_html: string) {
var lastent = logdiv.lastElementChild;
var in_scrollback =
// inspired by
// https://stackoverflow.com/questions/487073/how-to-check-if-element-is-visible-after-scrolling/21627295#21627295
// rejected
// https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
- lastent.getBoundingClientRect().bottom >
- logdiv.getBoundingClientRect().bottom;
+ lastent == null ||
+ lastent.getBoundingClientRect()!.bottom >
+ logdiv.getBoundingClientRect()!.bottom;
console.log('ADD LOG MESSAGE ',in_scrollback, msg_html);
var nelem = document.createElement('div');
logdiv.appendChild(nelem);
if (!in_scrollback) {
- lastent = logdiv.lastElementChild;
+ lastent = logdiv.lastElementChild!;
lastent.scrollIntoView();
}
}
// ----- test counter, startup -----
-messages.Piece = function(j) {
+messages.Piece = <MessageHandler>function
+(j: { piece: PieceId, op: Object }) {
console.log('PIECE UPDATE ',j)
var piece = j.piece;
- var m = j.op;
+ var m = j.op as { [k: string]: Object };
var k = Object.keys(m)[0];
pieceops[k](piece, m[k]);
-}
+};
-pieceops.Modify = function (piece, info) {
+pieceops.Modify = <PieceHandler>function
+(piece: PieceId, info: { svg: string, held: PlayerId, pos: Pos }) {
console.log('PIECE UPDATE MODIFY ',piece,info)
- var uelem = document.getElementById('use'+piece);
- var delem = document.getElementById('defs'+piece);
+ var uelem = document.getElementById('use'+piece) as unknown as SVGGraphicsElement;
+ var delem = document.getElementById('defs'+piece) as unknown as SVGGraphicsElement;
delem.innerHTML = info.svg;
- uelem.setAttributeNS(null, "x", info.pos[0]);
- uelem.setAttributeNS(null, "y", info.pos[1]);
+ uelem.setAttributeNS(null, "x", info.pos[0]+"");
+ uelem.setAttributeNS(null, "y", info.pos[1]+"");
uelem_checkconflict(piece, uelem);
if (info.held == null) {
set_ungrab(uelem, piece);
console.log('MODIFY DONE');
}
-pieceops.Move = function (piece, info) {
- var uelem = document.getElementById('use'+piece);
+pieceops.Move = <PieceHandler>function
+(piece, info: Pos ) {
+ var uelem = document.getElementById('use'+piece)! as unknown as SVGGraphicsElement;
uelem_checkconflict(piece, uelem);
- uelem.setAttributeNS(null, "x", info[0]);
- uelem.setAttributeNS(null, "y", info[1]);
+ uelem.setAttributeNS(null, "x", info[0]+"");
+ uelem.setAttributeNS(null, "y", info[1]+"");
}
-messages.Recorded = function(j) {
- var uelem = document.getElementById('use'+j.piece);
- if (j.cseq >= uelem.dataset.cseq) {
+messages.Recorded = <MessageHandler>function
+(j: { piece: PieceId, cseq: ClientSeq, gen: Generation } ) {
+ var uelem = document.getElementById('use'+j.piece)!;
+ if (uelem.dataset.cseq != null && j.cseq >= +uelem.dataset.cseq) {
delete uelem.dataset.cseq;
}
gen = j.gen;
}
-function uelem_checkconflict(piece, uelem) {
+function uelem_checkconflict(piece: PieceId, uelem: SVGGraphicsElement) {
if (uelem.dataset.cseq == null) { return; }
delete uelem.dataset.cseq;
add_log_message('Conflict! - simultaneous update');
}
function startup() {
- var body = document.getElementById("main-body");
- ctoken = body.dataset.ctoken;
- us = body.dataset.us;
- gen = parseInt(body.dataset.gen);
- status_node = document.getElementById('status');
+ var body = document.getElementById("main-body")!;
+ ctoken = body.dataset.ctoken!;
+ us = body.dataset.us!;
+ gen = +body.dataset.gen!;
+ status_node = document.getElementById('status')!;
status_node.innerHTML = 'js-done';
space = document.getElementById('space') as unknown as SVGGraphicsElement;
- logdiv = document.getElementById("log");
- svg_ns = space.getAttribute('xmlns');
+ logdiv = document.getElementById("log")!;
+ svg_ns = space.getAttribute('xmlns')!;
var es = new EventSource("/_/updates/"+ctoken+'/'+gen);
es.onmessage = function(event) {
function doload(){
console.log('DOLOAD');
- var elem = document.getElementById('loading_token');
+ var elem = document.getElementById('loading_token')!;
var ptoken = elem.dataset.ptoken;
xhr_post_then('/_/session',
JSON.stringify({ ptoken : ptoken }),
loaded);
}
-function loaded(xhr){
+function loaded(xhr: XMLHttpRequest){
console.log('LOADED');
- var body = document.getElementById('loading_body');
+ var body = document.getElementById('loading_body')!;
body.outerHTML = xhr.response;
startup();
}