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.

My Flash Navigation Experiments

I spent a lot of time experimenting before I finally published the current version of my website.

I was excited about using interactive 3D worlds as a basis of information discovery. I experimented with simple scenes in Papervision3D like below, where the user can drag objects around. As you can see, the performance was really bad even with low-res images. Since that time Flash 3D engines such as Away3D have started using Stage3D to their advantage, so I imagine they would perform better than this one.

[swfobject]120[/swfobject]

Another idea I had was using face tracking as a navigation method. Again, this didn’t perform as well as I wanted and the file size was too large to get a nicely detailed tree. Allow Flash to access your camera to see how it works.

[swfobject]116[/swfobject]

Here is the interface I almost used in the end, but then abandoned when I decided to retrofit the site to use my branded-wood-disc logo. I like that no actual buttons are used, but it maybe wasn’t 100% intuitive.

[swfobject]118[/swfobject]

These are already a few years old now (c. 2009) and I’m still not certain that HTML5 could do face tracking or shape tweening the same way I’ve done here, and have it useable in the majority of browsers. Some day it will, but kudos to Flash to giving this to us so early on.