I have a Javascript API, which should be usable with GWT and Flex. Using the FABridge it is really easy to call Javascript methods from AS3 and vice versa. But when I try to register a callback to an AS3 method in my Javascript API I get stuck. Here is a short code sample:
public function initApp():void {
if (ExternalInterface.available) {
ExternalInterface.addCallback("foobar", foobar);
}
}
public function foobar():void {
//the callback function
Alert.show("Callback from API works!");
}
private function btnCallbackClicked():void {
ExternalInterface.call("testAPICallbackFromJS", Application.application.foobar);
}
And the simple JS method:
function testAPICallbackFromGWT(callback){
$clinit_26(); //added by the GWT piler
alert('callback to be launched 3 2 1');
callback();
}
But this version does not work, because I always receive an empty function in my JS code. It seems that the FABridge is cutting the rest. Then I tried a different approach. I wrote a little JS method, which takes the name of the function and creates the callback from the JS side.
registerFlexCallback = function(registerMethod, callback, id) {
/*
workaround to create a callback for an AS method, which can be called by Javascript
* registerMethod - Javascript method which shall be called for registration with the created callback as parameter
* callback - AS method that shall be called by Javascript (available over the FABridge interface)
* id - ID of the flash object (use Application.application.id in AS)
*/
var swf = document.getElementById(id);
eval(registerMethod + "(swf." + callback + ");");
};
This one works well with the Internet Explorer, but with no other browser. For example in Firefox I get the following error message:
NPMethod called on non-NPObject wrapped JSObject!
Can somebody tell me, what this error is about (maybe some kind of security issue)? Or does anyone have a better idea how to create callbacks for my AS3 methods which can be called by JS?
I have a Javascript API, which should be usable with GWT and Flex. Using the FABridge it is really easy to call Javascript methods from AS3 and vice versa. But when I try to register a callback to an AS3 method in my Javascript API I get stuck. Here is a short code sample:
public function initApp():void {
if (ExternalInterface.available) {
ExternalInterface.addCallback("foobar", foobar);
}
}
public function foobar():void {
//the callback function
Alert.show("Callback from API works!");
}
private function btnCallbackClicked():void {
ExternalInterface.call("testAPICallbackFromJS", Application.application.foobar);
}
And the simple JS method:
function testAPICallbackFromGWT(callback){
$clinit_26(); //added by the GWT piler
alert('callback to be launched 3 2 1');
callback();
}
But this version does not work, because I always receive an empty function in my JS code. It seems that the FABridge is cutting the rest. Then I tried a different approach. I wrote a little JS method, which takes the name of the function and creates the callback from the JS side.
registerFlexCallback = function(registerMethod, callback, id) {
/*
workaround to create a callback for an AS method, which can be called by Javascript
* registerMethod - Javascript method which shall be called for registration with the created callback as parameter
* callback - AS method that shall be called by Javascript (available over the FABridge interface)
* id - ID of the flash object (use Application.application.id in AS)
*/
var swf = document.getElementById(id);
eval(registerMethod + "(swf." + callback + ");");
};
This one works well with the Internet Explorer, but with no other browser. For example in Firefox I get the following error message:
NPMethod called on non-NPObject wrapped JSObject!
Can somebody tell me, what this error is about (maybe some kind of security issue)? Or does anyone have a better idea how to create callbacks for my AS3 methods which can be called by JS?
Share Improve this question asked Sep 28, 2009 at 0:08 SilentGertSilentGert 532 silver badges4 bronze badges2 Answers
Reset to default 2This is because functions don't serialize across the FABridge. Meaning in your
ExternalInterface.call("testAPICallbackFromJS", Application.application.foobar);
the second parameter will always be null. What I do is add a wrapper method on the HTML page via eval that points at my embed and therefore the added callback. So you have to add an extra, while annoying step:
ExternalInterface.addCallback("foobar", foobar);
var callBack:String = "";
var functionName:String = UIDUtil.createUUID;
callBack = "function " + functionName + "( ){ " +
"document.getElementById('applicationName').foobar(arguments);"+
"}";
ExternalInterface.call("eval", callback);
ExternalInterface.call("testAPICallbackFromJS", functionName);
The NPObject error you're seeing I'm pretty sure is a security error ( based on where it es from in the FF code ) probably preventing you from dynamically injecting methods that can be eval'ed without the JS interpreter getting in the way.
I haven't even tried to pile the above so, hopefully you get the gist.
I notice two things right away
firstly it appears your ExternalInterface will die if the ExternalInterface is not ready.
public function initApp():void {
if (ExternalInterface.available) {
ExternalInterface.addCallback("foobar", foobar);
}
}
I would add a timout and then try again so that it tries again until Externalinterface is ready.
Also I don't see the function "foobar" in your javascript code. I see callback passed in as a variable but without varifying that it is in fact 'foobar' this is hte kind of thing that can make testing a misserable event.
function testAPICallbackFromGWT(callback){
$clinit_26(); //added by the GWT piler
alert('callback to be launched 3 2 1');
callback();
}
I would simplify your testing example so that there are less moving parts.
// e.g. run just flash to javascript only
ExternalInterface.call("alert", "hello out there");
if that works
// establish the call from flash
ExternalInterface.addCallback("hello_out_there", foobar);
// and in javascript
alert(typeof('hello_out_there')); // will be 'function' if exists or undefined if ExternalInterface did not work
This way you can get a handle bit for bit what is working and where it breaks down.
Pay atention to the timing, if you can tigger your flash from button actions and your javascript from links you can illiminate a number of loading issues as well. of course you'll need to solve an autoload version for your launch but for testing manually triggered events can simplify things significantly.
also because it's javascript the browser is relevant.
I've seen consistent results in Firefox and Internet explorer that break down in safari and sometimes IE is the odd browser out.
Sometimes Firefox is the only one that breaks.
you just have to test them all.