[0001]
[0002]
[0003]
[0004]
[0005]
[0006]
[0007]
[0008]
[0009]
[0010]
[0011]
[0012]
[0013]
[0014]
[0015]
[0016]
[0017]
[0018]
[0019]
[0020]
[0021]
[0022]
[0023]
[0024]
[0025]
[0026]
[0027]
[0028]
[0029]
[0030]
[0031]
[0032]
[0033]
[0034]
[0035]
[0036]
[0037]
[0038]
[0039]
[0040]
[0041]
[0042]
[0043]
[0044]
[0045]
[0046]
[0047]
[0048]
[0049]
[0050]
[0051]
[0052]
[0053]
[0054]
[0055]
[0056]
[0057]
[0058]
[0059]
[0060]
[0061]
[0062]
[0063]
[0064]
[0065]
[0066]
[0067]
[0068]
[0069]
[0070]
[0071]
[0072]
[0073]
[0074]
[0075]
[0076]
[0077]
[0078]
[0079]
[0080]
[0081]
[0082]
[0083]
[0084]
[0085]
[0086]
[0087]
[0088]
[0089]
[0090]
[0091]
[0092]
[0093]
[0094]
[0095]
[0096]
[0097]
[0098]
[0099]
[0100]
[0101]
[0102]
[0103]
[0104]
[0105]
[0106]
[0107]
[0108]
[0109]
[0110]
[0111]
[0112]
[0113]
[0114]
[0115]
[0116]
[0117]
[0118]
[0119]
[0120]
[0121]
[0122]
[0123]
[0124]
[0125]
[0126]
[0127]
[0128]
[0129]
[0130]
[0131]
[0132]
[0133]
[0134]
[0135]
[0136]
[0137]
[0138]
[0139]
[0140]
[0141]
[0142]
[0143]
[0144]
[0145]
[0146]
[0147]
[0148]
[0149]
[0150]
[0151]
[0152]
[0153]
[0154]
[0155]
[0156]
[0157]
[0158]
[0159]
[0160]
[0161]
[0162]
[0163]
[0164]
[0165]
[0166]
[0167]
[0168]
[0169]
[0170]
[0171]
[0172]
[0173]
[0174]
[0175]
[0176]
[0177]
[0178]
[0179]
[0180]
[0181]
[0182]
[0183]
[0184]
[0185]
[0186]
[0187]
[0188]
[0189]
[0190]
[0191]
[0192]
[0193]
[0194]
[0195]
[0196]
[0197]
[0198]
[0199]
[0200]
[0201]
[0202]
[0203]
[0204]
[0205]
[0206]
[0207]
[0208]
[0209]
[0210]
[0211]
[0212]
[0213]
[0214]
[0215]
[0216]
[0217]
[0218]
[0219]
[0220]
[0221]
[0222]
[0223]
[0224]
[0225]
[0226]
[0227]
[0228]
[0229]
[0230]
[0231]
[0232]
[0233]
[0234]
[0235]
[0236]
[0237]
[0238]
[0239]
[0240]
[0241]
[0242]
[0243]
[0244]
[0245]
[0246]
[0247]
[0248]
[0249]
[0250]
<!DOCTYPE html>
<html>
<head>
<!--
Copyright (C) 2010-2013 Mark G.Daniel
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it under the
conditions of the GNU GENERAL PUBLIC LICENSE, version 3, or any later version.
http://www.gnu.org/licenses/gpl.txt
-->
<title>WebSocket Scripting - Mouse Demonstration</title>

<style type="text/css">
body { font-family: sans-serif, arial, helvetica; font-size:11pt; }
.demo { font-size:130%; font-weight:bold; text-decoration:underline; text-align:center; }
.application th { text-align:right; vertical-align:top; }
.clientab th { padding:0.2em 0 0.2em 1em; text-align:right; }
.clientab td { padding:0.2em 0 0.2em 1em; text-align:right; font-family:monospace; }
.clients { width:99%; margin:1em; background-color:whiteSmoke; }
.revealhide { font-weight:bold; }
.documentation { display:none; padding:0 2em 0 2em; }
</style>

<script language="JavaScript">
function testWebSocketSupport()
{
   return ('WebSocket' in window && window.WebSocket.CLOSING === 2);
}
function reportWebSocketSupport()
{
   var level = testWebSocketSupport();
   if (level != 1)
      document.getElementById("nowebsocket").innerHTML =
'<span style="background-color:#ff0000;padding:1px;font-size:120%;">\
This browser does not support WebSocket!\
</span><br /><i>' + navigator.userAgent + '</i>';
}
if (window.addEventListener)
   window.addEventListener("load", reportWebSocketSupport, false);
else
if (window.attachEvent)
   window.attachEvent("onload", reportWebSocketSupport);
</script>

</head>
<body onmousemove="mouseMove(event)" on__mouseout="mouseMove(event)">

<div id="dbug"></div>
<table class="application" cellpadding="5" cellspacing="5" border="0">
<tr><td colspan="3" class="demo">WebSocket Scripting &nbsp;&mdash;&nbsp; 
Mouse Demonstration</td></tr>
<tr><td id="OnNext" colspan="3" style="text-align:center;"></td></tr>
<tr><td id="nowebsocket" colspan="3" style="text-align:center;"></td></tr>
<tr>
<th align="left">Clients:</th>
<td id="clients" class="clients" onMouseOver="webSocketOpen()">[closed]</td>
</tr>
</table>

<br>
<div class="revealhide">Description&nbsp;<tt>[<a name="descrip" href="javascript:revealHide('descrip')">+</a>]</tt></div>

<div name="descrip" class="documentation">

<p>This example illustrates the fine granularity of the <b>asynchronous,
bi-directional</b> network channel provided by a WebSocket.</p>

<p>To begin, move the mouse over the [closed] indicator.  A WebSocket
connection will be established with the server-side application (script).  This
application <b>handles multiple, concurrent clients</b>.  Your connection has
the <i>host:port</i> underlined.  The mouse position of all connected  clients
is displayed to each client.  With each mouse movement on the page the cursor
position is sent to the application where it updates that client's status. 
With each client update <b>all connected clients</b> have the revised mouse
position display updated.  To help manage potential bandwidth consumption the
update rate is explicitly limited at both client and server.</p>

<p>If left unused the WebSocket is disconnected by the server-side application
and can be restarted by moving the mouse over the [disconnected] indicator.

<p>This demonstration is JavaScript-driven at the browser end</p>

<p style="margin-left:2em;"><tt>WASD_ROOT:[SRC.WEBSOCKET]<a target="_blank"
href="ws_mouse.html?httpd=content&type=text/plain">WS_MOUSE.HTML</a></tt></p>

<p>and uses a WebSocket protocol application (script) at the WASD server end</p>

<p style="margin-left:2em;"><tt>WASD_ROOT:[SRC.WEBSOCKET]<a target="_blank"
href="ws_mouse.c">WS_MOUSE.C</a></tt></p>

<p>All of these interactions can be observed using the WASD WATCH facility;
[x]CGI, [x]DCL and [x]Network Data items.</p>

</div>

<div class="revealhide">Configuration&nbsp;<tt>[<a name="config" href="javascript:revealHide('config')">+</a>]</tt></div>

<div name="config" class="documentation">

<p>The script is a native WebSocket protocol application and so the executable
should only need placing in the script directory.</p>

<p> To effectively display multiple clients the script must rely on there being
only a single instance of it executing (a particular issue when employing
multiple WASD instances).  Generally the server will only need to instantiate a
single WS_MOUSE script to handle multiple clients, however there is a
small window when the client request is being accepted by the script where it
is unavailable.

<p> Suppress host name lookup by defining the logical name WS_MOUSE_NO_LOOKUP.
</div>

<script language="JavaScript">

if (window.location.protocol == "http:")
   var URL = "ws://";
else
   var URL = "wss://";
URL += window.location.host + "/cgiplus-bin/ws_mouse"

var ws = null;
var meIdent = null;
var sendMsg = null;
var sendTimer = null;
var updateRate = 200;
var webSocketConnected = false;
var webSocketNotSupported = false;
var clientsObj = document.getElementById("clients");
var dbugObj = document.getElementById("dbug");

function dbugOut (text) { dbugObj.innerHTML = text; }

function mouseMove (event) {

   if (!webSocketConnected) return;

   if (event.type == "mousemove")
      sendMsg = event.clientX + "," + event.clientY;
   else
      sendMsg = "";

   if (!updateRate)
      sendMove ();
   else
   if (!sendTimer)
      sendTimer = setTimeout ("sendMove()",updateRate);
}

function sendMove () {
   if (!webSocketConnected) return;
   if (!sendMsg) return;
   if (ws) ws.send(sendMsg);
   sendMsg = sendTimer = 0;
}

function displayData (data) {

   // data comes one line per client as bar-separated items
   // turn these into a an HTML table formatting the client data

   var table = "<table class=\"clientab\">";
   table += "<tr><th></th><th>Connect</th><th>Client</th>";
   table += "<th>Update</th><th style=\"width:6em;\">Mouse</th></tr>\n";

   data = data.split("\n");
   var  cnt = 0;
   while (cnt < data.length) {
      var one = data[cnt].split("|");
      if (one.length == 6) {
         table += "<tr>";
         table += "<th>" + one[1] + "</th>";
         table += "<td>" + one[2] + "</td>";
         if (one[0] == meIdent)
            table += "<td style=\"text-decoration:underline;\">";
         else
            table += "<td>";
         table += one[3] + "</td>";
         table += "<td>" + one[4] + "</td>";
         table += "<td>" + one[5] + "</td>";
         table += "</tr>";
      }
      cnt++;
   }
   table += "</table>";
   clientsObj.innerHTML = table;
}

function webSocketOpen () {

   if ("WebSocket" in window) {

      if (ws) return false;

      ws = new WebSocket(URL);

      ws.onopen = function(evt) {
         clientsObj.innerHTML = "[open]";
         webSocketConnected = true;
      };

      ws.onclose = function(evt) {
         clientsObj.innerHTML = "[disconnected]";
         ws = null;
         webSocketConnected = false;
      };

      ws.onmessage = function (evt) { 
         if (evt.data == "update=max")
            updateRate = 0;
         else
         if (evt.data.substr(0,4) == "you=")
            meIdent = evt.data.substr(4);
         else
         if (evt.data.substr(0,6) == "OnNext")
            document.getElementById("OnNext").innerHTML =
               "WsLibOnNextRequest()";
         else
            displayData (evt.data);
      };

      updateRate = 200;
      clientsObj.innerHTML = "[connecting...]";

   } else {
     if (!webSocketNotSupported) {
        clientsObj.innerHTML = "WebSocket not supported!";
        webSocketNotSupported = true;
     }
   }

   return false;
}

function revealHide (name) {
   var nameAry = document.getElementsByName(name);
   var ancObj = nameAry[0];
   var divObj = nameAry[1];
   if (divObj.style.display == "block") {
      ancObj.innerHTML = "+";
      divObj.style.display = "none";
   }
   else {
      ancObj.innerHTML = "-";
      divObj.style.display = "block";
   }
}

</script>
</body>
</html>