packages feed

threepenny-gui-0.8.1.0: js/comm.js

/* *********************************************************************
  Client-server communication
  using WebSockets
  
  The function  createWebSocket(receive)  creates a client-server
  connection. The argument function `receive` is called whenever the client
  receives a message. The connection object has a single member `send`
  which can be used to send messages to the server.
  
  In Haskell types:
  
  createWebSocket :: (JSON -> IO ()) -> IO { send :: JSON -> IO () }
  
********************************************************************* */
Haskell.createWebSocket = function (url0, receive) {
  var that = {};
  var optReloadOnDisconnect = false;
  var url  = 'ws:' + url0.slice(5) + '/websocket/';
  var ws   = new WebSocket(url);
  
  // Close WebSocket when the browser window is closed.
  $(window).on('unload', function () {
    ws.close();
  });

  // Send ping message in regular intervals.
  // We expect pong messages in return to keep the connection alive.
  var ping = function () {
    // Only send a ping when it has a chance to reach the server.
    if (ws.readyState !== WebSocket.CLOSING && ws.readyState !== WebSocket.CLOSED) {
      ws.send("ping");
      window.setTimeout(ping,2000);
    }
  };
  
  // Start communication when the WebSocket is opened.
  ws.onopen = function (e) {
    ping();
    ws.onmessage = function (msg) {
      // Haskell.log("WebSocket message: %o",msg);
      if (msg.data !== "pong") {
        receive(JSON.parse(msg.data));
      }
    };
    ws.onclose = function (e) {
      Haskell.log("WebSocket closed: %o", e);
      if (optReloadOnDisconnect) { window.location.reload(true); }
    };
    ws.onerror = function (e) {
      Haskell.log("WebSocket error: %o", e);
    };
  };
  
  // Send a JSON message to the server
  that.send  = function (json) { ws.send(JSON.stringify(json)); };
  // Close the connection
  that.close = function () { ws.send("quit"); };
  // Set option: Reload window when the websocket connection is broken?
  that.setReloadOnDisconnect = function (b) { optReloadOnDisconnect = b };
  
  return that;
};


/* *********************************************************************
  Client-server communication
  using HTTP
  
  WARNING: The following code is untested legacy code.
  It's only there because there may be a chance we want to resurrect it.
  
********************************************************************* */

/* *********************************************************************
Threepenny.createHTTP = function (receive) {
  var that;
  var signal_count = 0;
  var sessionToken = {};
  
  window.setTimeout(function () {
    waitForEvents();
  });
    
  // Poll instruction from the server.
  var waitForEvents = function () {
    console.log("Polling… (%d signals so far)",signal_count);
    var data = { token: sessionToken };
    var cmd  = sessionToken != null? 'poll' : 'init';
    if (cmd === 'init') {
      data.info = window.location.href;
    }
    var req = $.ajax({
      dataType: 'json',
      url : cmd,
      data: data,
      success: function (events) {
        if (sessionToken == null) {
          sessionToken = req.getResponseHeader('Set-Token').match(/[0-9]+/)*1;
        }
        console.log("Running event" +(events.length>1?'s':'') +"…")
        if (events.length) {
          console.log('Event list:');
          runMultipleEvents(events);
        } else {
          runEvent(events, signalEvent, function(response){
            maybeReply(response, waitForEvents);
          });
        }
      },
      error: function(reply) {
        console.log("Error, waiting...");
        window.setTimeout(function(){
          waitForEvents();
        },5000);
      }
    });
  }

  var runMultipleEvents = function (events){
    if(events.length == 0) {
      return waitForEvents();
    }
    runEvent(events.shift(), signalEvent, function(response){
      maybeReply(response, function(){
        runMultipleEvents(events);
      });
    });
  }
  
  // Send an event to the server.
  var signalEvent = function (value) {
    signal({ Event: value}, function (){});
  }
  
  // Send a reply to the server if necessary.
  var maybeReply = function (response, continuation) {
    if (response != undefined) { signal(response, continuation); }
    else { continuation(); }
  }
  
  // Send response back to the server.
  var signal = function signal(signal,continuation) {
    signal_count++;
    console.log('Signal: %s',JSON.stringify(signal));
    $.ajax({
      dataType: 'json',
      url:'signal',
      data: { token: sessionToken, signal: JSON.stringify(signal) },
      success: function(){
        continuation();
      },
      error: function(reply){
        console.log("Error: %o",reply);
      }
    });
  }
  
  return that;
};
********************************************************************* */