chiark / gitweb /
now just run tsc in toplevel
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 7 Jul 2020 23:15:04 +0000 (00:15 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 7 Jul 2020 23:15:04 +0000 (00:15 +0100)
templates/script.ts

index e8bfc1813a1098dbe131cea3eb459192138508d7..b4fbaa2388c96b9e3a3fd3384a45bdf91da39928 100644 (file)
 //   #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;
@@ -52,14 +62,10 @@ var space : SVGGraphicsElement;
 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); }
@@ -71,24 +77,24 @@ function xhr_post_then(url,data,good) {
   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);
 }
@@ -96,7 +102,7 @@ function api_check() {
   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);
@@ -108,9 +114,11 @@ function api_posted() {
   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,
@@ -129,21 +137,29 @@ const DRAGGING = { // bitmask
   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;
@@ -157,7 +173,7 @@ function drag_mousedown(e) {
   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);
@@ -168,23 +184,23 @@ function set_grab(uelem, piece, owner) {
   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) {
@@ -193,25 +209,25 @@ function drag_mousemove(e) {
   }
   //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();
 }
@@ -225,19 +241,26 @@ function 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');
@@ -245,28 +268,30 @@ function add_log_message(msg_html) {
   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);
@@ -276,37 +301,39 @@ pieceops.Modify = function (piece, info) {
   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) {
@@ -336,16 +363,16 @@ function startup() {
 
 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();
 }