diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-06-20 19:53:21 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-06-20 19:53:21 (GMT) |
commit | 794575f01ce5a6bf7e377eb815f3def5aded74f5 (patch) | |
tree | 9c59df64ee290f68b7b6c8698bfac4169684485e /test/samples/uscxml | |
parent | d304f85417e3175c5f2ca159dd303309c24e7b81 (diff) | |
download | uscxml-794575f01ce5a6bf7e377eb815f3def5aded74f5.zip uscxml-794575f01ce5a6bf7e377eb815f3def5aded74f5.tar.gz uscxml-794575f01ce5a6bf7e377eb815f3def5aded74f5.tar.bz2 |
New version with XHTML invoker
Diffstat (limited to 'test/samples/uscxml')
-rw-r--r-- | test/samples/uscxml/templates/mc-html.html | 455 | ||||
-rw-r--r-- | test/samples/uscxml/templates/xhtml-invoker.html | 228 | ||||
-rw-r--r-- | test/samples/uscxml/test-mmi-im.scxml | 11 | ||||
-rw-r--r-- | test/samples/uscxml/test-xhtml-invoker.scxml | 33 |
4 files changed, 591 insertions, 136 deletions
diff --git a/test/samples/uscxml/templates/mc-html.html b/test/samples/uscxml/templates/mc-html.html index 78bb34e..33eac77 100644 --- a/test/samples/uscxml/templates/mc-html.html +++ b/test/samples/uscxml/templates/mc-html.html @@ -1,159 +1,346 @@ <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> - <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dojo/dojo.js"></script> - <script type="text/javascript"> - function createUUID() { - // http://www.ietf.org/rfc/rfc4122.txt - var s = []; - var hexDigits = "0123456789abcdef"; - for (var i = 0; i < 36; i++) { - s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); + // see http://stackoverflow.com/questions/1206937/javascript-domready + var domLoaded = function(callback) { + /* Internet Explorer */ + /*@cc_on + @if (@_win32 || @_win64) + document.write('<script id="ieScriptLoad" defer src="//:"><\/script>'); + document.getElementById('ieScriptLoad').onreadystatechange = function() { + if (this.readyState == 'complete') { + callback(); + } + }; + @end @*/ + /* Mozilla, Chrome, Opera */ + if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', callback, false); + return; + } + /* Safari, iCab, Konqueror */ + if (/KHTML|WebKit|iCab/i.test(navigator.userAgent)) { + var DOMLoadTimer = setInterval(function () { + if (/loaded|complete/i.test(document.readyState)) { + callback(); + clearInterval(DOMLoadTimer); + } + }, 10); + return; + } + /* Other web browsers */ + window.onload = callback; + }; + + </script> + <script type="text/javascript"> + + function CometSession(options) { + /** + * Support for two-channel asynchronous http communication + */ + for (var key in options) { + if (options.hasOwnProperty(key)) { + this[key] = options[key]; + } + } + var self = this; + + this.xhr = (window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("MSXML2.XMLHTTP.3.0")); + this.cometPoll = (window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("MSXML2.XMLHTTP.3.0")); + + this.createUUID = function() { + // http://www.ietf.org/rfc/rfc4122.txt + var s = []; + var hexDigits = "0123456789abcdef"; + for (var i = 0; i < 36; i++) { + s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); + } + s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010 + s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01 + s[8] = s[13] = s[18] = s[23] = "-"; + var uuid = s.join(""); + return uuid; + } + + this.longpoll = function() { + self.cometPoll.onreadystatechange = function() { + if (self.cometPoll.readyState === 4) { + if (self.cometPoll.status !== 200) { + self.longpoll(); + return; + } + self.onRcvd(self.cometPoll); + self.longpoll(); + } + }; + // use token until we have a context + self.cometPoll.open("GET", self.server + (self.query ? "?" + self.query : "")); + self.cometPoll.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + self.cometPoll.send(null); + }; + + this.post = function(data) { + self.xhr.open("POST", self.server + (self.query ? "?" + self.query : "")); + self.xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + self.xhr.send(data); + } } - s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010 - s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01 - s[8] = s[13] = s[18] = s[23] = "-"; - var uuid = s.join(""); - return uuid; - } + </script> + <script type="text/javascript"> - <script type="text/javascript"> - require(["dojo/on", "dojo/mouse", "dojo/domReady!", "dojo", "dojox/json/ref"], function(on, mouse, dom, dojo, ref) { + function MMISession(element, imURL, params) { + // copy all attributes passe as params + for (var key in params) { + if (params.hasOwnProperty(key)) { + this[key] = params[key]; + } + } + var self = this; - var element = dojo.byId("foo"); - - var mmiNS = "http://www.w3.org/2008/04/mmi-arch"; - var token = createUUID(); - var contextId; - var timeout="30000"; - var imURL = "${im.url}"; - - var xhr = dojo.require("dojo/_base/xhr"); - // initial new context request - xhr.post({ - url: imURL + "?token=" + token, - postData: - '<mmi:mmi xmlns:mmi="' + mmiNS + '" version="1.0">' + - '<mmi:NewContextRequest ' + - 'mmi:Source="HTML" ' + - 'mmi:Target="' + imURL + '" '+ - 'mmi:RequestID="' + token + '" />' + - '</mmi:mmi>', - handleAs:"xml", - headers:{ - "X-Requested-With": null, - "Content-Type": "application/xml", - }, - load: function(result) { - // scxml IM replied with 204 - longpoll via get - longpoll(); - } - }); - - var longpoll = function() { - xhr.get({ - // The URL to request - url: imURL + "?token=" + token, - handleAs:"xml", - headers:{ - "X-Requested-With": null, - "Content-Type": "application/xml", - }, - load: function(result) { - // IM had some event to send to us - element.innerHTML += (new XMLSerializer()).serializeToString(result).replace(/</gi, "<") + "<br />"; - var mmiEvent = result.documentElement.firstChild; + // initialize base class with onData handler + this.__proto__ = new CometSession({ + server: imURL, + onRcvd: function(data) { + var mmiEvent = data.responseXML.documentElement.firstChild; + var handler; + var replier; switch (mmiEvent.localName) { case "NewContextResponse": - newContextResponse(mmiEvent); + self.context = mmiEvent.getAttribute("Context"); + self.comet.query = "context=" + self.context; + break; + case "PrepareRequest": + handler = self.onPrepare; + replier = function(attrs) { sendMMIEvent("DoneNotification", attrs) }; break; case "StartRequest": - startRequest(mmiEvent); + handler = self.onStart; + replier = function(attrs) { sendMMIEvent("StartResponse", attrs) }; + break; + case "CancelRequest": + handler = self.onCancel; + replier = function(attrs) { sendMMIEvent("CancelResponse", attrs) }; + break; + case "PauseRequest": + handler = self.onPause; + replier = function(attrs) { sendMMIEvent("PauseResponse", attrs) }; + break; + case "ResumeRequest": + handler = self.onResume; + replier = function(attrs) { sendMMIEvent("ResumeResponse", attrs) }; break; + case "ClearContextRequest": + handler = self.onClearContext; + replier = function(attrs) { sendMMIEvent("ClearContextResponse", attrs) }; + break; + case "StatusRequest": + handler = self.onStatus; + replier = function(attrs) { sendMMIEvent("StatusResponse", attrs) }; + break; + case "ExtensionNotification": + handler = self.onExtension; + break; + } + if (typeof handler === "function") { + var rc = handler(mmiEvent); + if (typeof replier === "function") { + if (rc === false) { + replier({ Status: "Failure"}); + } else if (typeof rc === "object") { + replier(rc); + } else { + replier({ Status: "Success"}); + } + } } - longpoll(); } }); - } - - var eventToJSON = function(event) { - var seen = []; - return JSON.stringify(event, function(key, val) { - if (isNode(val)) { - return; + this.comet = this.__proto__; + + // get element as an HTML Node + if (typeof(element) === 'string') { + element = document.getElementById(element); + } + + // assign attributes + this.mmiNS = "http://www.w3.org/2008/04/mmi-arch"; + this.comet.query = "token=" + this.createUUID(); + this.element = element; + + this.init = function() { + sendMMIEvent("NewContextRequest"); + self.longpoll(); + } + + // helper function to determine whether something is a html node + var isNode = function(o){ + return ( + typeof Node === "object" ? o instanceof Node : + o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName==="string" + ); + } + + // helper function to determine whether something is a window + var isWindow = function(o){ + return ( + typeof Window === "object" ? o instanceof Window : + o && typeof o === "object" && typeof o.menubar === "object" + ); + } + + // serialize an object to be send + this.send = function(attr) { + // see also: https://raw.github.com/douglascrockford/JSON-js/master/cycle.js + var data = attr.Data; + // dispatch over thingy type here + if (typeof data === "object") { + var seen = []; + data = JSON.stringify(attr.Data, function(key, val) { + if (isNode(val)) { + // return a selection of attributes + return { + id: val.id, + tagName: val.tagName, + localName: val.localName, + }; + +/* + // return everything that is atomic - this is a lot with all the HTML inside + var nodeAttr = {}; + for (var key in val) { + if ( + key !== "outerHTML" && + val.hasOwnProperty(key) && + typeof val[key] !== "object" && + typeof val[key] !== "function" + ) { + nodeAttr[key] = val[key]; + } + } + return nodeAttr; +*/ + } + if (isWindow(val)) { + return; + } + if (typeof val === "object") { + if (seen.indexOf(val) >= 0) + return; + seen.push(val) + } + return val + }); + } - if (isWindow(val)) { - return; + attr.Data = data; + sendMMIEvent("ExtensionNotification", attr); + } + + // register event handler if not given per constructor + if(typeof this.onStart !== "function") { + this.onStart = function(mmiEvent) { + var content = mmiEvent.firstChild; + var fromStartRequest = document.importNode(content.firstChild, true); + self.element.appendChild(fromStartRequest); } - if (typeof val == "object") { - if (seen.indexOf(val) >= 0) - return; - seen.push(val) + } + if(typeof this.onStatus !== "function") { + this.onStatus = function(mmiEvent) { + return true; } - return val - }); - } - - var isNode = function(o){ - return ( - typeof Node === "object" ? o instanceof Node : - o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName==="string" - ); - } + } + if(typeof this.onPrepare !== "function") { + this.onPrepare = function(mmiEvent) { + return true; + } + } + if(typeof this.onCancel !== "function") { + this.onCancel = function(mmiEvent) { + return true; + } + } + if(typeof this.onPause !== "function") { + this.onPause = function(mmiEvent) { + return true; + } + } + if(typeof this.onResume !== "function") { + this.onResume = function(mmiEvent) { + return true; + } + } + if(typeof this.onExtension !== "function") { + this.onExtension = function(mmiEvent) { + return true; + } + } + if(typeof this.onClearContext !== "function") { + this.onClearContext = function(mmiEvent) { + return true; + } + } - var isWindow = function(o){ - return ( - typeof Window === "object" ? o instanceof Window : - o && typeof o === "object" && typeof o.menubar === "object" - ); - } - - var newContextResponse = function(event) { - contextId = event.getAttribute("Context"); - } - var startRequest = function(event) { - var content = event.firstChild; - console.log(content); - var fromStartRequest = document.importNode(content.firstChild,true); - element.appendChild(fromStartRequest); - } - - var sendExtensionNotification = function(event) { - console.log(event); - var data = eventToJSON(event); - console.log(data); - xhr.post({ - url: imURL + "?token=" + token, - postData: - '<mmi:mmi xmlns:mmi="' + mmiNS + '" version="1.0">' + - '<mmi:ExtensionNotification ' + - 'mmi:Source="HTML" ' + - 'mmi:Target="' + imURL + '" ' + - 'mmi:Context="' + contextId + '" ' + - 'mmi:RequestID="' + token + '">' + - '<mmi:Data>' + data + '</mmi:Data>' + - '</mmi:ExtensionNotification>' + - '</mmi:mmi>', - handleAs:"xml", - headers:{ - "X-Requested-With": null, - "Content-Type": "application/xml", - }, - load: function(result) { - // scxml IM replied with 204 - } - }); + if(typeof this.onDone !== "function") { + this.onDone = function(mmiEvent) { + return true; + } + } + + window.onbeforeunload=function(){ + this.onDone(); + sendMMIEvent("DoneNotification", attrs); + }; - } - - on(element, "click", sendExtensionNotification); - on(element, mouse.enter, sendExtensionNotification); - on(element, mouse.leave, sendExtensionNotification); - - }); + var sendMMIEvent = function(type, attrs) { + if (!attrs) + attrs = {}; + if (!attrs["Source"]) // default for Source + attrs["Source"] = "HTML"; + if (!attrs["Target"]) // default for Target + attrs["Target"] = self.imURL; + if (!attrs["RequestID"]) // default for RequestID + attrs["RequestID"] = self.createUUID(); + var mmiDocument = '<mmi:mmi xmlns:mmi="' + self.mmiNS + '" version="1.0">' + + '<mmi:' + type + ' '; + if (self.context) + mmiDocument += 'mmi:Context="' + self.context + '" '; + for (attr in attrs) { + if (attr === "Data") + continue; + if (attr === "Content") + continue; + mmiDocument += 'mmi:' + attr + '="' + attrs[attr] + '" '; + } + mmiDocument += '>'; + + if (attrs["Data"]) + mmiDocument += '<mmi:Data>' + "\n<![CDATA[\n" + attrs["Data"] + "\n]]>\n" + '</mmi:Data>'; + if (attrs["Content"]) + mmiDocument += '<mmi:Content>' + "\n<![CDATA[\n" + attrs["Content"] + "\n]]>\n" + '</mmi:Content>'; + + mmiDocument += '</mmi:' + type +'></mmi:mmi>', + self.post(mmiDocument); + } + + }; + + </script> + + <script type="text/javascript"> + var mmiSession; + domLoaded(function () { + mmiSession = new MMISession("foo", "${im.url}", { + onExtension : function(mmiEvent) { + console.log(mmiEvent); + } + }); + mmiSession.init(); + }); </script> + </head> <body class="tundra"> <div id="foo"></div> diff --git a/test/samples/uscxml/templates/xhtml-invoker.html b/test/samples/uscxml/templates/xhtml-invoker.html new file mode 100644 index 0000000..7773231 --- /dev/null +++ b/test/samples/uscxml/templates/xhtml-invoker.html @@ -0,0 +1,228 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> + <script type="text/javascript"> + // see http://stackoverflow.com/questions/1206937/javascript-domready + var domLoaded = function(callback) { + /* Internet Explorer */ + /*@cc_on + @if (@_win32 || @_win64) + document.write('<script id="ieScriptLoad" defer src="//:"><\/script>'); + document.getElementById('ieScriptLoad').onreadystatechange = function() { + if (this.readyState == 'complete') { + var head= document.getElementsByTagName('head')[0]; + var script= document.createElement('script'); + script.type= 'text/javascript'; + script.src= 'http://wicked-good-xpath.googlecode.com/files/wgxpath.install.js'; + head.appendChild(script); + wgxpath.install(); + + // see http://stackoverflow.com/questions/1811116/ie-support-for-dom-importnode + document.importNode = function(node, allChildren) { + switch (node.nodeType) { + case document.ELEMENT_NODE: + var newNode = document.createElementNS(node.namespaceURI, node.nodeName); + if(node.attributes && node.attributes.length > 0) + for(var i = 0, il = node.attributes.length; i < il; i++) + newNode.setAttribute(node.attributes[i].nodeName, node.getAttribute(node.attributes[i].nodeName)); + if(allChildren && node.childNodes && node.childNodes.length > 0) + for(var i = 0, il = node.childNodes.length; i < il; i++) + newNode.appendChild(document.importNode(node.childNodes[i], allChildren)); + return newNode; + break; + case document.TEXT_NODE: + case document.CDATA_SECTION_NODE: + case document.COMMENT_NODE: + return document.createTextNode(node.nodeValue); + break; + } + } + + callback(); + } + }; + @end @*/ + /* Mozilla, Chrome, Opera */ + if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', callback, false); + return; + } + /* Safari, iCab, Konqueror */ + if (/KHTML|WebKit|iCab/i.test(navigator.userAgent)) { + var DOMLoadTimer = setInterval(function () { + if (/loaded|complete/i.test(document.readyState)) { + callback(); + clearInterval(DOMLoadTimer); + } + }, 10); + return; + } + /* Other web browsers */ + window.onload = callback; + }; + + </script> + <script type="text/javascript"> + + function CometSession(options) { + /** + * Support for two-channel asynchronous http communication + */ + for (var key in options) { + if (options.hasOwnProperty(key)) { + this[key] = options[key]; + } + } + var self = this; + + this.xhr = (window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("MSXML2.XMLHTTP.3.0")); + this.cometPoll = (window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("MSXML2.XMLHTTP.3.0")); + + this.createUUID = function() { + // http://www.ietf.org/rfc/rfc4122.txt + var s = []; + var hexDigits = "0123456789abcdef"; + for (var i = 0; i < 36; i++) { + s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); + } + s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010 + s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01 + s[8] = s[13] = s[18] = s[23] = "-"; + var uuid = s.join(""); + return uuid; + } + + this.longpoll = function() { + self.cometPoll.onreadystatechange = function() { + if (self.cometPoll.readyState === 4) { + if (self.cometPoll.status !== 200) { + self.longpoll(); + return; + } + self.onRcvd(self.cometPoll); + self.longpoll(); + } + }; + // use token until we have a context + self.cometPoll.open("GET", self.server + (self.query ? "?" + self.query : "")); + self.cometPoll.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + self.cometPoll.setRequestHeader("Connection", "close"); + self.cometPoll.send(null); + }; + + this.post = function(name, data) { + self.xhr.open("POST", self.server + (self.query ? "?" + self.query : "")); + self.xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + self.xhr.setRequestHeader('X-SCXML-Name', name); + self.xhr.send(data); + } + + // serialize an object to be send + this.send = function(name, thing) { + var data; + // see also: https://raw.github.com/douglascrockford/JSON-js/master/cycle.js + // dispatch over thingy type here + if (typeof thing === "object") { + var seen = []; + // will not work on opera as thing is checked for cycles first + data = JSON.stringify(thing, function(key, val) { + if (isNode(val)) { + // return a selection of attributes + return { + id: val.id, + tagName: val.tagName, + localName: val.localName + }; + } + if (isWindow(val)) { + return; + } + if (typeof val === "object") { + if (seen.indexOf(val) >= 0) + return; + seen.push(val) + } + return val + }); + } else { + data = thing; + } + this.post(name, data); + } + + // helper function to determine whether something is a html node + var isNode = function(o){ + return ( + typeof Node === "object" ? o instanceof Node : + o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName==="string" + ); + } + + // helper function to determine whether something is a window + var isWindow = function(o){ + return ( + typeof Window === "object" ? o instanceof Window : + o && typeof o === "object" && typeof o.menubar === "object" + ); + } + + } + + </script> + + <script type="text/javascript"> + domLoaded(function () { + scxml = new CometSession({ + element: document.getElementById("${scxml.invokeId}"), + server: "${scxml.server}", + onRcvd : function(data) { + if (data.responseXML) { + var type = data.getResponseHeader("X-SCXML-Type") || "replacechildren"; + var domTarget = data.getResponseHeader("X-SCXML-XPath") || "/html/body"; + var domAttr = data.getResponseHeader("X-SCXML-Attr"); + var result = document.evaluate(domTarget, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + + for (var i = 0, l = result.snapshotLength; i < l; i++) { + var item = result.snapshotItem(i); + var node = document.importNode(data.responseXML.firstChild, true); + switch (type) { + case "firstchild": + item.insertBefore(node, item.firstChild); + break; + case "lastchild": + item.appendChild(node); + break; + case "previoussibling": + item.parentNode.insertBefore(node, item); + break; + case "nextsibling": + item.parentNode.insertBefore(node, item.nextSibling); + break; + case "replace": + item.parentNode.replaceChild(node, item); + break; + case "delete": + item.parentNode.removeChild(item); + break; + case "addattribute": + item.setAttribute(domAttr, node); + break; + case "replacechildren": + while(item.hasChildNodes()) { + item.removeChild(item.firstChild); + } + item.appendChild(node); + default: + break; + } + } + } + } + }); + scxml.longpoll(); + }); + </script> + + </head> + <body></body> +</html> diff --git a/test/samples/uscxml/test-mmi-im.scxml b/test/samples/uscxml/test-mmi-im.scxml index 4b130bd..70cb3b8 100644 --- a/test/samples/uscxml/test-mmi-im.scxml +++ b/test/samples/uscxml/test-mmi-im.scxml @@ -35,6 +35,7 @@ <state id="startmc"> <!-- invoke type="vxml" id="mc.vxml" / --> + <!-- invoke type="xhtml" id="mc.xhtml" / --> <!-- Idle here and wait for events --> <state id="idle"> @@ -52,7 +53,13 @@ <content> <mmi:StartRequest> <mmi:Content> - <html:button>Click Me</html:button> + <html:form onmouseover ="mmiSession.send({ Name: 'onmouseover', Data: arguments[0] })"> + First name: <html:input type="text" name="firstname" /><html:br /> + Last name: <html:input type="text" name="lastname" /> + <html:input + onclick="mmiSession.send({ Name: 'onsubmit', Data: arguments[0] })" + type="button" value="Submit" /> + </html:form> </mmi:Content> </mmi:StartRequest> </content> @@ -60,7 +67,7 @@ </transition> <transition event="mmi.extensionnotification" target="idle"> - <script>dump(_event)</script> + <!--script>dump(_event)</script --> </transition> </state> diff --git a/test/samples/uscxml/test-xhtml-invoker.scxml b/test/samples/uscxml/test-xhtml-invoker.scxml new file mode 100644 index 0000000..aec4db3 --- /dev/null +++ b/test/samples/uscxml/test-xhtml-invoker.scxml @@ -0,0 +1,33 @@ +<scxml datamodel="ecmascript" name="comet-test" + xmlns:html="http://www.w3.org/1999/xhtml" + xmlns="http://www.w3.org/2005/07/scxml"> + + <script src="http://uscxml.tk.informatik.tu-darmstadt.de/scripts/dump.js" /> + + <state id="start"> + <invoke type="xhtml" id="xhtml1"> + <!-- replacechildren (default), firstchild, lastchild, previoussibling, nextsibling, replace, delete, addattribute --> + <content type="replacechildren" xpath="/html/body"> + <html:form onmouseover="scxml.send('onmouseover', arguments[0])"> + First name1: <html:input type="text" name="firstname" /><html:br /> + Last name1: <html:input type="text" name="lastname" /> + <html:input onclick="scxml.send('onclick', arguments[0])" type="button" value="Submit" /> + </html:form> + </content> + </invoke> + + <state id="idle"> + <transition target="idle" event="onmouseover"> + <log expr="dump(_event)" /> + </transition> + <transition target="idle" event="onclick" cond="_event.origin=='xhtml1'"> + <send target="#_xhtml1"> + <content type="lastchild" xpath="/html/body"> + <html:p>Thank you!</html:p> + </content> + </send> + </transition> + </state> + + </state> +</scxml>
\ No newline at end of file |