views:

1642

answers:

3

What I have:

  1. A swf exports a function via ExternalInterface
  2. Javascript creates new embed object and adds it to the document
  3. Calling flash functions works fine in other browsers
  4. Calling flash functions will fail in IE 8

Example of exporting functions in swf:

flash.external.ExternalInterface.addCallback("isActive", ...

Example of creating the embed object:

var b = document.createElement('embed');

    b.type = 'application\u002fx-shockwave-flash';
    b.setAttribute('allowFullScreen', 'true');
    b.setAttribute('allowNetworking', 'all');
    b.setAttribute('allowScriptAccess', 'always');
    b.width = 500;
    b.height = 400;
    b.src = 'assets\u002fUltra4.UltraApplication\u002fUltra4.UltraApplication+UltraSprite.swf';

Example of calling flash external interface in javascript:

   try
    {
      e = b.isActive();
    }
    catch (__exc){ }

In IE it will catch with message "Object doesn't support this property or method"

How to fix it?

  1. Related: http://bojolais.livejournal.com/251383.html
  2. Related: http://stackoverflow.com/questions/1166079/externalinterface-not-working-in-ie
  3. Related: http://swfupload.org/forum/generaldiscussion/985
  4. Related: http://code.google.com/p/doctype/wiki/ArticleFixingFlashExternalInterface
  5. Related: http://www.dangerouslyawesome.com/2006/10/20/another-swfobject-problem-deproblemed/
  6. Related: http://www.airtightinteractive.com/news/?p=71

In script debugger I can see a third party script which is supposed to be the bridge:

function __flash__arrayToXML(obj) {
    var s = "<array>";
    for (var i=0; i<obj.length; i++) {
        s += "<property id=\"" + i + "\">" + __flash__toXML(obj[i]) + "</property>";
    }
    return s+"</array>";
}
function __flash__argumentsToXML(obj,index) {
    var s = "<arguments>";
    for (var i=index; i<obj.length; i++) {
        s += __flash__toXML(obj[i]);
    }
    return s+"</arguments>";
}
function __flash__objectToXML(obj) {
    var s = "<object>";
    for (var prop in obj) {
        s += "<property id=\"" + prop + "\">" + __flash__toXML(obj[prop]) + "</property>";
    }
    return s+"</object>";
}
function __flash__escapeXML(s) {
    return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
}
function __flash__toXML(value) {
   var type = typeof(value);
    if (type == "string") {
        return "<string>" + __flash__escapeXML(value) + "</string>";
    } else if (type == "undefined") {
        return "<undefined/>";
    } else if (type == "number") {
        return "<number>" + value + "</number>";
    } else if (value == null) {
        return "<null/>";
    } else if (type == "boolean") {
        return value ? "<true/>" : "<false/>";
    } else if (value instanceof Date) {
        return "<date>" + value.getTime() + "</date>";
   } else if (value instanceof Array) {
       return __flash__arrayToXML(value);
   } else if (type == "object") {
       return __flash__objectToXML(value);
   } else {
        return "<null/>"; //???
    }
}
function __flash__addCallback(instance, name) {
  instance[name] = function () { 
    return eval(instance.CallFunction("<invoke name=\""+name+"\" returntype=\"javascript\">" + __flash__argumentsToXML(arguments,0) + "</invoke>"));
  }
}
function __flash__removeCallback(instance, name) {
  instance[name] = null;
}
A: 

Could this be to do with the fact your creating an Embed tag instead of an Object tag? IE traditionally uses Object tags to embed Flash content

See the Adobe tech not for discussion: http://kb2.adobe.com/cps/415/tn_4150.html

David Burrows
+1  A: 

I'm not sure if I understand your question correctly. But I think you are missing a couple of things:

1) Your embed tag needs a name attribute. Let's name it "NewFlashMovie" for the subsequent code:

b.name = "NewFlashMovie";

2) You need to call the "isActive" function differently using an external function. First add this function

 function thisMovie(movieName) {
     if (navigator.appName.indexOf("Microsoft") != -1) {
         return window[movieName];
     } else {
         return document[movieName];
     }
 }

Then you can call the function like this

thisMovie("NewFlashMovie").isActive();

From my experience, this "thisMovie" is essential to bridge the IE-Flash calls. This is also documented in the ExternalInterface documentation

3) I also recommend using swfobject instead of creating your own "embed" object.

Hope these helps.

JONYC
for some reason I now got this to work:x.CallFunction('<invoke name=\"AddShape1\" returntype=\"javascript\"><arguments></arguments></invoke>
zproxy
A: 

I've found that, for IE, calling Javascript from ActionScript, I've needed to supply an "id" attribute to the object tag. The IE way of handling ExternalInterface.call(...) is to call a method on the object. IE issues the code

document.getElementById("...").SetReturnValue(...)

Without an id attribute on your object tag, this reduces to

document.getElementById("").SetReturnValue(...)

which tries to call SetReturnValue on a null object.

Note that the "id" attribute isn't required for other browsers but doesn't really hurt either.

Something similar may be happening in your case: Perhaps a "name" attribute on the embed may help.

Mark Judd