diff options
Diffstat (limited to 'apps/samples')
-rwxr-xr-x | apps/samples/miles/emptyface.jpg | bin | 0 -> 1603 bytes | |||
-rw-r--r-- | apps/samples/miles/miles.html | 26 | ||||
-rw-r--r-- | apps/samples/miles/miles.js | 369 | ||||
-rw-r--r-- | apps/samples/miles/miles.scxml | 155 | ||||
-rw-r--r-- | apps/samples/miles/test1.jpeg | bin | 10996 -> 7350 bytes | |||
-rw-r--r-- | apps/samples/miles/test2.jpeg | bin | 40332 -> 7871 bytes | |||
-rw-r--r-- | apps/samples/miles/test3.jpeg | bin | 0 -> 7939 bytes | |||
-rw-r--r-- | apps/samples/miles/test4.jpeg | bin | 0 -> 7780 bytes | |||
-rw-r--r-- | apps/samples/websockets/websockets.html | 77 | ||||
-rw-r--r-- | apps/samples/websockets/websockets.scxml | 16 |
10 files changed, 571 insertions, 72 deletions
diff --git a/apps/samples/miles/emptyface.jpg b/apps/samples/miles/emptyface.jpg Binary files differnew file mode 100755 index 0000000..a1b2f32 --- /dev/null +++ b/apps/samples/miles/emptyface.jpg diff --git a/apps/samples/miles/miles.html b/apps/samples/miles/miles.html index 9cee058..08cfeca 100644 --- a/apps/samples/miles/miles.html +++ b/apps/samples/miles/miles.html @@ -15,13 +15,31 @@ <script type="text/javascript"> require(["dojo/domReady!"], function(dom) { - var milesSession = new Miles("miles1"); + var milesSession1 = new Miles("miles1"); + var milesSession2 = new Miles("miles2"); + var milesSession3 = new Miles("miles3"); + var milesSession4 = new Miles("miles4"); }); </script> </head> <body class="tundra"> - <div style="width: 600px; height: 400px"> - <div id="miles1"></div> - </div> + <table> + <tr> + <td> + <div id="miles1"></div> + </td> + <td> + <div id="miles2"></div> + </td> + </tr> + <tr> + <td> + <div id="miles3"></div> + </td> + <td> + <div id="miles4"></div> + </td> + </tr> + </table> </body> </html> diff --git a/apps/samples/miles/miles.js b/apps/samples/miles/miles.js index 1b2d0b6..a1d4422 100644 --- a/apps/samples/miles/miles.js +++ b/apps/samples/miles/miles.js @@ -12,11 +12,45 @@ function Miles(element, params) { this.connected = false; this.imageIteration = 0; + this.width = 300; + this.height = 200; + // private attributes var scxmlURL = "localhost:8080" - var reflectorIp = "localhost" - var email = "me@somehost.de"; - var problemName = "some really hard problem"; + var reflectorIp = "88.131.107.12" + var email = "user@smartvortex.eu"; + var problemName = "webconfero"; + var remoteEmail = "other@smartvortex.eu"; + + var participants = []; // empty array + var videoCompressions = [ + { value: 'jpeg', label: "JPEG" }, + { value: 'h263', label: "H.263" }, + { value: 'h264', label: "H.264" }, + ]; + var videoCompression = ""; + + var audioEncodings = [ + { value: 'pcm', label: "PCM" }, + { value: 'ulaw', label: "uLaw" }, + { value: 'ogg', label: "Ogg Theora" }, + ]; + var audioEncoding = ""; + + var repollInterval = { + image: 50, + chat: 500, + participants: 1000 + }; + + var showVideo = true; + var enableAudio = true; + var stopChatScrolling = false; + var activateCamera = true; + var openMicrophone = true; + var videoFramerate = 25; + var videoHeight = self.height; + var videoWidth = self.width; // override with parameters if given this.params = params; @@ -27,68 +61,140 @@ function Miles(element, params) { // called when dojo loaded all requirements below this.connect = function() { - self.xhr.post({ + var query = ""; + query += "?reflector=" + encodeURIComponent(reflectorIp); + query += "&userid=" + encodeURIComponent(email); + query += "&session=" + encodeURIComponent(problemName); + + self.xhr.get({ // The URL to request - url: "http://" + scxmlURL + "/miles/connect", + url: "http://" + scxmlURL + "/miles/start" + query, // handleAs:"text", - contentType: 'application/json', - postData: dojo.toJson({ - reflectorIp: reflectorIp, - email: email, - problemName: problemName - }), - headers:{ - "X-Requested-With": null, - }, error: function(err) { console.log(err); }, load: function(result) { - // we expect nothing in return self.connected = true; - // trigger continuously loading the image + + // toggle connect button to disconnect + self.connectDropDown.dropDown.onCancel(true); + self.controlElem.replaceChild(self.controlDropDown.domNode, self.connectDropDown.domNode); + + // trigger continuous updates refreshImage(); + getChatText(); + getParticipants(); } }); } + this.disconnect = function() { + self.connected = false; + self.controlDropDown.dropDown.onCancel(true); + self.controlElem.replaceChild(self.connectDropDown.domNode, self.controlDropDown.domNode); + } + + var getParticipants = function() { + var query = ""; + self.xhr.get({ + // The URL to request + url: "http://" + scxmlURL + "/miles/participants" + query, + handleAs:"json", + error: function(err) { + console.log(err); + if (self.connected) { + setTimeout(getParticipants, repollInterval.participants); + } + }, + load: function(result) { + if (result.participants) { + participants = result.participants; + } + if (self.connected) { + console.log(participants); + setTimeout(getParticipants, repollInterval.participants); + } + } + }); + } + // fetch a base64 encoded image and set it as the src attribute var refreshImage = function() { + var query = ""; + query += "?userid=" + encodeURIComponent(email); self.xhr.get({ // The URL to request - url: "http://" + scxmlURL + "/miles/image", + url: "http://" + scxmlURL + "/miles/thumbnail" + query, + handleAs:"text", headers:{ - "X-Requested-With":null + "X-Content-Encoding": "base64" }, error: function(err) { console.log(err); if (self.connected) { - self.messageElem.innerHTML = self.imageIteration++; - refreshImage(); + setTimeout(refreshImage, repollInterval.image); } }, load: function(result) { self.pictureElem.src = "data:image/jpeg;base64," + result; if (self.connected) { self.messageElem.innerHTML = self.imageIteration++; - refreshImage(); + setTimeout(refreshImage, repollInterval.image); } } }); - }; + var getChatText = function() { + self.xhr.get({ + // The URL to request + url: "http://" + scxmlURL + "/miles/gettext", + handleAs:"json", + error: function(err) { + console.log(err); + if (self.connected) { + setTimeout(getChatText, repollInterval.chat); + } + }, + load: function(result) { + if (result.message) { + self.chatOutputElem.innerHTML += stopChatScrolling + " " + Math.random() + ": " + result.message + '<br />'; + if (!stopChatScrolling) + self.chatOutputElem.scrollTop = self.chatOutputElem.scrollHeight; + } + if (self.connected) { + setTimeout(getChatText, repollInterval.chat); + } + } + }); + }; + + require(["dojo/dom-construct", "dojo/_base/xhr", "dojo/dom", + "dojo/on", + "dojo/_base/unload", "dijit/form/DropDownButton", "dijit/TooltipDialog", + "dijit/form/TextBox", + "dijit/form/Button", + "dijit/form/CheckBox", + "dijit/form/Select", + "dijit/form/NumberSpinner", "dojo/ready"], function(domConst, xhr, dom, + on, + baseUnload, DropDownButton, TooltipDialog, + TextBox, + Button, + CheckBox, + Select, + NumberSpinner, ready) { ready(function() { self.xhr = xhr; @@ -97,14 +203,19 @@ function Miles(element, params) { if (typeof(element) === 'string') { element = dom.byId(element); } + element.style.width = self.width + "px"; + + baseUnload.addOnWindowUnload(function(){ +// alert("unloading..."); + }); // dynamically assemble the DOM we need element.appendChild(domConst.toDom('\ <table>\ <tr>\ - <td valign="top">\ + <td valign="top" colspan="2" >\ <div style="position: relative; padding: 0px">\ - <img class="picture" src="test1.jpeg"></img>\ + <img class="picture" src="emptyface.jpg"></img>\ <div style="position: absolute; left: 10px; top: 10px">\ <table></tr>\ <td class="control" style="vertical-align: middle"></td>\ @@ -113,9 +224,18 @@ function Miles(element, params) { </div>\ </td>\ </tr>\ + <tr><td valign="top" colspan="2" >\ + <div class="chatOutput" style="max-height:120px; overflow: auto">\ + </td></tr>\ + <tr>\ + <td valign="top" style="vertical-align: middle">\ + <div class="chatInput">\ + </td>\ + <td valign="top"><div class="chatSendButton"></td>\ + </tr>\ <tr>\ - <td valign="top">\ - <div class="messages" style="position: relative; padding: 0px">\ + <td valign="top" colspan="2" >\ + <div class="messages">\ </td>\ </tr>\ </table>\ @@ -123,19 +243,202 @@ function Miles(element, params) { // from the above DOM, fetch some nodes to put dojo widgets in self.pictureElem = dojo.query("img.picture", element)[0]; + self.pictureElem.width = self.width; + self.pictureElem.height = self.height; self.controlElem = dojo.query("td.control", element)[0]; self.messageElem = dojo.query("div.messages", element)[0]; + self.chatOutputElem = dojo.query("div.chatOutput", element)[0]; + self.chatOutputElem.style.fontSize = "0.8em"; + on(self.chatOutputElem, "mouseover", function(evt) { + stopChatScrolling = true; + }); + on(self.chatOutputElem, "mouseout", function(evt) { + stopChatScrolling = false; + }); + + self.chatInputElem = dojo.query("div.chatInput", element)[0]; + + self.chatSendButton = new Button({ + label: "Send", + onClick: function(){ + self.xhr.post({ + // The URL to request + url: "http://" + scxmlURL + "/miles/chat", + contentType: 'text/plain', + postData: dojo.toJson({ + message: chatInputElem.value + }), + error: function(err) { + console.log(err); + }, + load: function(result) {} + }); + + } + }, dojo.query("div.chatSendButton", element)[0]); + + // the chat interface + self.chatInput = new TextBox({ + name: "chatInput", + style: "width: 100%", + }, self.chatInputElem); - // the control dropdown button - self.controlDropDownContent = domConst.toDom('<div />'); + + // the connect dropdown button + self.connectDropDownContent = domConst.toDom('\ + <div>\ + <table>\ + <tr><td>Problem Name:</td><td><div class="problemName" /></td></tr>\ + <tr><td>Your Email:</td><td><div class="email" /></td></tr>\ + <!-- tr><td>Other Email:</td><td><div class="remoteEmail" /></td></tr -->\ + <tr><td>Reflector Host:</td><td><div class="reflectorIp" /></td></tr>\ + <tr><td>Video Server:</td><td><div class="scxmlURL" /></td></tr>\ + <tr><td></td><td align="right"><div class="connectButton" /></td></tr>\ + </div>\ + '); + self.connectToolTip = new TooltipDialog({ content:self.connectDropDownContent, style:"max-height:320px"}); + self.connectDropDown = new DropDownButton({ label: "Connect", dropDown: self.connectToolTip }); + + // Connect parameters + self.problemNameBox = new TextBox({ + name: "problemName", + value: problemName, + style: "width: 100%", + }); + dojo.query("div.problemName", self.connectToolTip.domNode)[0].appendChild(self.problemNameBox.domNode); + + self.emailBox = new TextBox({ + name: "email", + value: email, + style: "width: 100%", + }); + dojo.query("div.email", self.connectToolTip.domNode)[0].appendChild(self.emailBox.domNode); + + // self.remoteEmailBox = new TextBox({ + // name: "remoteEmail", + // value: remoteEmail, + // style: "width: 100%", + // }); + // dojo.query("div.remoteEmail", self.connectToolTip.domNode)[0].appendChild(self.remoteEmailBox.domNode); + + self.reflectorIpBox = new TextBox({ + name: "reflectorIp", + value: reflectorIp, + style: "width: 100%", + }); + dojo.query("div.reflectorIp", self.connectToolTip.domNode)[0].appendChild(self.reflectorIpBox.domNode); + + self.scxmlURLBox = new TextBox({ + name: "scxmlURL", + value: scxmlURL, + style: "width: 100%", + }); + dojo.query("div.scxmlURL", self.connectToolTip.domNode)[0].appendChild(self.scxmlURLBox.domNode); + + self.connectButton = new Button({ + label: "Connect", + onClick: function(){ + self.connect(); + } + }); + dojo.query("div.connectButton", self.connectToolTip.domNode)[0].appendChild(self.connectButton.domNode); + + // Control parameters + self.controlDropDownContent = domConst.toDom('\ + <div>\ + <table>\ + <tr><td>Activate Camera:</td><td><div class="activateCamera" /></td></tr>\ + <tr><td style="padding-left: 1em">Compression:</td><td><div class="videoCompression" /></td></tr>\ + <tr><td style="padding-left: 1em">Framerate:</td><td><div class="videoFramerate" /></td></tr>\ + <tr><td style="padding-left: 1em">Width:</td><td><div class="videoWidth" /></td></tr>\ + <tr><td style="padding-left: 1em">Height:</td><td><div class="videoHeight" /></td></tr>\ + <tr><td>Open Microphone:</td><td><div class="openMicrophone" /></td></tr>\ + <tr><td style="padding-left: 1em">Encoding:</td><td><div class="audioEncoding" /></td></tr>\ + <tr><td colspan="2"><hr /></td></tr>\ + <tr><td>Enable Audio:</td><td><div class="enableAudio" /></td></tr>\ + <tr><td>Show Video:</td><td><div class="showVideo" /></td></tr>\ + <tr><td colspan="2"><hr /></td></tr>\ + <tr><td></td><td align="right"><div class="disconnectButton" /></td></tr>\ + </div>\ + '); self.controlToolTip = new TooltipDialog({ content:self.controlDropDownContent, style:"max-height:320px"}); - self.controlDropDown = new DropDownButton({ label: "Connect", dropDown: self.controlToolTip }); - self.controlElem.appendChild(self.controlDropDown.domNode); + self.controlDropDown = new DropDownButton({ label: "Session", dropDown: self.controlToolTip }); - // many more control widgets to be instantiated here + // Control parameters + self.activateCameraCheckbox = new CheckBox({ + name: "activateCamera", + value: activateCamera, + checked: activateCamera, + }); + dojo.query("div.activateCamera", self.controlToolTip.domNode)[0].appendChild(self.activateCameraCheckbox.domNode); - // connect and start to fetch images from the server - self.connect(); + self.videoCompressionSelect = new Select({ + name: "videoCompression", + value: videoCompression, + options: videoCompressions, + }); + dojo.query("div.videoCompression", self.controlToolTip.domNode)[0].appendChild(self.videoCompressionSelect.domNode); + + self.videoFramerateSpinner = new NumberSpinner({ + name: "videoFramerate", + value: videoFramerate, + style: "width: 50px" + }); + dojo.query("div.videoFramerate", self.controlToolTip.domNode)[0].appendChild(self.videoFramerateSpinner.domNode); + + self.videoWidthSpinner = new NumberSpinner({ + name: "videoWidth", + value: videoWidth, + style: "width: 50px" + }); + dojo.query("div.videoWidth", self.controlToolTip.domNode)[0].appendChild(self.videoWidthSpinner.domNode); + + self.videoHeightSpinner = new NumberSpinner({ + name: "videoHeight", + value: videoHeight, + style: "width: 50px" + }); + dojo.query("div.videoHeight", self.controlToolTip.domNode)[0].appendChild(self.videoHeightSpinner.domNode); + + self.openMicrophoneCheckbox = new CheckBox({ + name: "openMicrophone", + value: openMicrophone, + checked: openMicrophone, + }); + dojo.query("div.openMicrophone", self.controlToolTip.domNode)[0].appendChild(self.openMicrophoneCheckbox.domNode); + + self.audioEncodingSelect = new Select({ + name: "audioEncoding", + value: audioEncoding, + options: audioEncodings, + }); + dojo.query("div.audioEncoding", self.controlToolTip.domNode)[0].appendChild(self.audioEncodingSelect.domNode); + + // session scoped parameters + self.enableAudioCheckbox = new CheckBox({ + name: "enableAudio", + value: enableAudio, + checked: enableAudio, + }); + dojo.query("div.enableAudio", self.controlToolTip.domNode)[0].appendChild(self.enableAudioCheckbox.domNode); + + self.showVideo = new CheckBox({ + name: "showVideo", + value: showVideo, + checked: showVideo, + }); + dojo.query("div.showVideo", self.controlToolTip.domNode)[0].appendChild(self.showVideo.domNode); + + self.disconnectButton = new Button({ + label: "Disconnect", + onClick: function(){ + self.disconnect(); + } + }); + dojo.query("div.disconnectButton", self.controlToolTip.domNode)[0].appendChild(self.disconnectButton.domNode); + + // intially append the connect dropdown + self.controlElem.appendChild(self.connectDropDown.domNode); }) }); diff --git a/apps/samples/miles/miles.scxml b/apps/samples/miles/miles.scxml index 0ecca05..9b1426a 100644 --- a/apps/samples/miles/miles.scxml +++ b/apps/samples/miles/miles.scxml @@ -2,16 +2,25 @@ <script src="http://uscxml.tk.informatik.tu-darmstadt.de/scripts/dump.js" /> <state id="main"> <invoke type="miles" id="miles"> - <param name="foo" expr="'asdf'" /> <finalize> + <script>//dump(_event);</script> <if cond="_event.data.origin"> <!-- <log label="Reply-length" expr="_event.data.base64.length" /> --> - <respond status="200" to="_event.data.origin"> - <header name="Cache-Control" value="no-cache" /> <!-- force IE to actually reload --> - <header name="Content-Type" value="text/plain" /> - <header name="Access-Control-Allow-Origin" value="*" /> - <content expr="_event.data.base64" /> - </respond> + <if cond="_event.name === 'thumbnail.reply'"> + <respond status="200" to="_event.data.origin"> + <header name="Cache-Control" value="no-cache" /> <!-- force IE to actually reload --> + <header name="Content-Type" value="text/plain" /> + <content expr="_event.data.image.base64()" /> + </respond> + <else /> + <respond status="200" to="_event.data.origin"> + <header name="Cache-Control" value="no-cache" /> <!-- force IE to actually reload --> + <!-- respond element will add content-type header --> + <content expr="_event.data" /> + </respond> + </if> + <else /> + <log label="Error" expr="'Event returned from invoker did not specify its origin for a reply'" /> </if> </finalize> </invoke> @@ -19,49 +28,125 @@ <state id="idle"> <!-- XHR CORS preflight respond --> <transition event="http.options" target="idle"> - <script>//dump(_event);</script> <respond status="200" to="_event.origin"> - <header name="Access-Control-Allow-Origin" value="*" /> - <header name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS" /> - <header name="Access-Control-Allow-Headers" value="X-Requested-With, Content-Type" /> + <header name="Access-Control-Allow-Origin" value="*" /> <!-- request origins we allow --> + <header name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS" /> <!-- http methods we allow --> + <header name="Access-Control-Allow-Headers" + value="X-Requested-With, X-Content-Encoding, Content-Type" /> <!-- headers we allow --> </respond> </transition> - <transition event="http.*" target="idle"> + <transition event="http.get" target="idle"> <script>//dump(_event);</script> - <if cond="_event.data.pathComponent[1] === 'session'"> - <respond status="200" to="_event.origin" /> - - <elseif cond="_event.data.pathComponent[1] === 'connect'" /> - <script>dump(_event);</script> - <send target="#_miles" event="connect"> - <param name="reflectorIp" expr="_event.data.content.reflectorIp" /> - <param name="email" expr="_event.data.content.email" /> - <param name="problemName" expr="_event.data.content.problemName" /> + <if cond="false"> + + <!-- START ############### --> + <elseif cond="_event.data.pathComponent[1] === 'start'" /> + <send target="#_miles" event="start"> + <param name="origin" expr="_event.origin" /> + <param name="reflector" expr="_event.data.query.reflector" /> + <param name="userId" expr="_event.data.query.userid" /> + <param name="session" expr="_event.data.query.session" /> </send> - <respond status="200" to="_event.origin"> - <header name="Connection" value="close" /> - <header name="Content-Type" value="application/json" /> - <header name="Access-Control-Allow-Origin" value="*" /> - </respond> - - <elseif cond="_event.data.pathComponent[1] === 'disconnect'" /> - <send target="#_miles" event="disconnect"> - <param name="reflectorIp" expr="_event.data.content.reflectorIp" /> - <param name="problemName" expr="_event.data.content.problemName" /> + + <!-- PARTICIPANTS ############### --> + <elseif cond="_event.data.pathComponent[1] === 'participants'" /> + <send target="#_miles" event="participants"> + <param name="origin" expr="_event.origin" /> + </send> + + <!-- THUMBNAIL ############### --> + <elseif cond="_event.data.pathComponent[1] === 'thumbnail'" /> + <send target="#_miles" event="thumbnail"> + <param name="origin" expr="_event.origin" /> + <param name="userId" expr="_event.data.query.userid" /> + </send> + + <!-- VIDEO ON ############### --> + <elseif cond="_event.data.pathComponent[1] === 'videoon'" /> + <send target="#_miles" event="videoon"> + <param name="origin" expr="_event.origin" /> + <param name="userid" expr="_event.data.query.userid" /> + </send> + + <!-- VIDEO OFF ############### --> + <elseif cond="_event.data.pathComponent[1] === 'videooff'" /> + <send target="#_miles" event="videooff"> + <param name="origin" expr="_event.origin" /> + <param name="userid" expr="_event.data.query.userid" /> + </send> + + <!-- AUDIO ON ############### --> + <elseif cond="_event.data.pathComponent[1] === 'audioon'" /> + <send target="#_miles" event="audioon"> + <param name="origin" expr="_event.origin" /> + <param name="userid" expr="_event.data.query.userid" /> + </send> + + <!-- AUDIO OFF ############### --> + <elseif cond="_event.data.pathComponent[1] === 'videooff'" /> + <send target="#_miles" event="audiooff"> + <param name="origin" expr="_event.origin" /> + <param name="userid" expr="_event.data.query.userid" /> </send> - <respond status="200" to="_event.origin" /> - <elseif cond="_event.data.pathComponent[1] === 'image'" /> - <send target="#_miles" event="image"> + <!-- SEND VIDEO ############### --> + <elseif cond="_event.data.pathComponent[1] === 'sendvideo'" /> + <send target="#_miles" event="sendvideo"> <param name="origin" expr="_event.origin" /> + <param name="width" expr="_event.data.query.width" /> + <param name="height" expr="_event.data.query.height" /> + <param name="framerate" expr="_event.data.query.framerate" /> + <param name="compression" expr="_event.data.query.compression" /> + </send> + + <!-- SEND VIDEO OFF ############### --> + <elseif cond="_event.data.pathComponent[1] === 'sendvideooff'" /> + <send target="#_miles" event="sendvideooff"> + <param name="origin" expr="_event.origin" /> + </send> + + <!-- SEND AUDIO ############### --> + <elseif cond="_event.data.pathComponent[1] === 'sendaudio'" /> + <send target="#_miles" event="sendaudio"> + <param name="origin" expr="_event.origin" /> + <param name="encoding" expr="_event.data.query.encoding" /> + </send> + + <!-- SEND AUDIO OFF ############### --> + <elseif cond="_event.data.pathComponent[1] === 'sendaudiooff'" /> + <send target="#_miles" event="sendaudiooff"> + </send> + + <!-- GET TEXT ############### --> + <elseif cond="_event.data.pathComponent[1] === 'gettext'" /> + <send target="#_miles" event="gettext"> + <param name="origin" expr="_event.origin" /> + </send> + + <else /> + <respond status="404" to="_event.origin" /> + </if> + </transition> + + <transition event="http.post" target="idle"> + <script>//dump(_event);</script> + <if cond="false"> + + <!-- POST TEXT ############### --> + <elseif cond="_event.data.pathComponent[1] === 'text'" /> + <send target="#_miles" event="posttext"> + <param name="origin" expr="_event.origin" /> + <param name="userid" expr="_event.data.query.userid" /> + <param name="message" expr="_event.data.content" /> </send> <else /> <respond status="404" to="_event.origin" /> - </if> + </transition> + </state> </state> </scxml>
\ No newline at end of file diff --git a/apps/samples/miles/test1.jpeg b/apps/samples/miles/test1.jpeg Binary files differindex e174f89..18c9517 100644 --- a/apps/samples/miles/test1.jpeg +++ b/apps/samples/miles/test1.jpeg diff --git a/apps/samples/miles/test2.jpeg b/apps/samples/miles/test2.jpeg Binary files differindex aca2300..7fb9cc0 100644 --- a/apps/samples/miles/test2.jpeg +++ b/apps/samples/miles/test2.jpeg diff --git a/apps/samples/miles/test3.jpeg b/apps/samples/miles/test3.jpeg Binary files differnew file mode 100644 index 0000000..6ed85b0 --- /dev/null +++ b/apps/samples/miles/test3.jpeg diff --git a/apps/samples/miles/test4.jpeg b/apps/samples/miles/test4.jpeg Binary files differnew file mode 100644 index 0000000..8a623f0 --- /dev/null +++ b/apps/samples/miles/test4.jpeg diff --git a/apps/samples/websockets/websockets.html b/apps/samples/websockets/websockets.html new file mode 100644 index 0000000..9a21f46 --- /dev/null +++ b/apps/samples/websockets/websockets.html @@ -0,0 +1,77 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> + + <style type="text/css"> + </style> + + <script type="text/javascript"> + </script> + + <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.9.1/dojo/dojo.js"></script> + + <script type="text/javascript"> + require([ + "dojo/domReady!", + "dojox/socket", + ], function( + dom, + Socket + ) { + var socket = new Socket("ws://localhost:8080/websockets"); + + function send(data){ + return socket.send(json.stringify(data)); + } + + socket.on("connect", function(){ + // send a handshake + send([ + { + "channel": "/meta/handshake", + "version": "1.0", + "minimumVersion": "1.0beta", + "supportedConnectionTypes": ["long-polling"] // or ["callback-polling"] for x-domain + } + ]) + socket.on("message", function(data){ + // wait for the response so we can connect with the provided client id + data = json.parse(data); + if(data.error){ + throw new Error(error); + } + // get the client id for all future messages + clientId = data.clientId; + // send a connect message + send([ + { + "channel": "/meta/connect", + "clientId": clientId, + "connectionType": "long-polling" + }, + { // also send a subscription message + "channel": "/meta/subscribe", + "clientId": clientId, + "subscription": "/foo/**" + } + ]); + socket.on("message", function(data){ + console.log(data); + }); + }); + }); + }); + </script> + </head> + <body class="tundra"> + <table> + <tr> + <td> + <div id="websockets"></div> + </td> + <td> + </tr> + </table> + </body> +</html> diff --git a/apps/samples/websockets/websockets.scxml b/apps/samples/websockets/websockets.scxml new file mode 100644 index 0000000..0050091 --- /dev/null +++ b/apps/samples/websockets/websockets.scxml @@ -0,0 +1,16 @@ +<scxml datamodel="ecmascript" name="websockets"> + <script src="http://uscxml.tk.informatik.tu-darmstadt.de/scripts/dump.js" /> + <state id="main"> + <transition target="main" event="http.get" cond="_event.data.header['Upgrade'] === 'websocket'"> + <respond status="101"> + + </respond> + </transition> + + <transition target="main" event="*"> + <script> + dump(_event); + </script> + </transition> + </state> +</scxml>
\ No newline at end of file |