Solved: Using ExternalInterface With Swiffy and AS2

I’ve been thankful for Swiffy as a tool for migrating Flash content to HTML5/SVG. It really does an amazing job and its drawbacks are few, but recently I discovered that it does not support using ExternalInterface with ActionScript 2 projects. In layman’s terms this means that the converted application cannot communicate with JavaScript on the page it resides on.

The problem:

Our application needed to support keyboard input on touch-screen devices, and the keyboard is only summoned when a real text input box receives focus. Swiffy uses SVG, which has no form text fields. Therefore we needed to use a JavaScript prompt for entering text, which then returned its data back to the Swiffy application. Remember, we can’t use ExternalInterface.

The solution: NOT using ExternalInterface

Fortunately LoadVars is supported with Swiffy’s AS2, so I came up with the idea of tricking the application into thinking it was communicating with a server. Fortunately I found EWSJS, which is a JavaScript for doing just that. It intercepts AJAX calls and returns whatever data you like.

I have posted my code in case anybody wants it, but seriously—if you don’t need this problem solved save yourself and stop reading now.

The Actionscript needed to have these functions:


grabTextLabelFromJavascript();
var result_thing:LoadVars = new LoadVars();
var t:Number;
result_thing.onLoad = function(success:Boolean) {
if (success) {
trace ("got it:"+result_thing.newTextValue);
if(result_thing.newTextValue==""){
//keep going
trace("keep going");
} else {
if( result_thing.newTextValue=="CANCEL"){
trace("cancel");
} else {
trace("making a new label:"+result_thing.newTextValue);
makeTextLabel(result_thing.newTextValue);
}
clearInterval(t);
getURL("javascript:enableServer(false);"); //disables the fake server
}
} else {
trace("nothing");
}
};
function grabTextLabelFromJavascript(){
t=setInterval(this,"loadIt",500);
getURL("javascript:summonPrompt();");
}
function loadIt():Void{
var send_lv:LoadVars = new LoadVars();
send_lv.sendAndLoad("/labelValue", result_thing, "GET");
}


The Swiffy resides in an iframe on another page so there is code on both HTML documents. First the iframe code:
// remember you will need to embed ewsjs.js and JQuery on this page
<script type="text/javascript">// <!&#91;CDATA&#91; var newLabel=""; var theResponse=""; (function($&;) { var route, router; router = { "/labelValue": { "GET": function(config) { // return the new text label if (newLabel!="") { console.log("newLabel ok:"+newLabel); theResponse="newTextValue="+newLabel; newLabel=""; }else{ console.log("nope"); theResponse="newTextValue="; } return({status: 200, response: theResponse, headers: {"Content-Type":"text/plain"}}); } } }; // simple to wrap around the actual handler, makes it easier to handle GET/PUT/POST/DELETE var handlerFn = function(r) { return function(config){ if (r&#91;config.method&#93;) { return(r&#91;config.method&#93;(config)); } }; }; for (route in router) { if (router.hasOwnProperty(route)) { EWS.registerHandler(route,handlerFn(router&#91;route&#93;)); } } }(jQuery)); function saveLabel(l){ console.log("saving label:"+l); newLabel=l; } // &#93;&#93;></script>

Now the iframe’s containing page:

<script type="text/javascript">// <!&#91;CDATA&#91; var newText=""; function summonPrompt(){ enableServer(true); //newText=""; var lt = prompt("Please enter text for the label:","Label text"); if (lt!=null) { document.getElementById("swiffyFrame").contentWindow.saveLabel(lt); //newText=lt; } else { document.getElementById("swiffyFrame").contentWindow.saveLabel("CANCEL"); } } function enableServer(bool){ console.log("enabling server:"+bool); document.getElementById('swiffyFrame').contentWindow.EWS.enable(bool); } // &#93;&#93;></script>

I hope this helps someone out there in cyberspace.