Jay Borseth
Jay Borseth

Reputation: 1993

Silverlight and Flash javascript bridge compatibility

I'm developing a Silverlight4 drop-in replacement for an existing Flash client. I would like to maintain compatibility with the existing Flash HTML bridge javascript functions, but I can't figure out how to expose the javascript interface directly on the Silverlight client object instead of a contained object.

In Flash, it is possible to call Bar() directly on the client object, as in:

var flashClient = document.GetElementById(_currentFlashId);  
flashClient.Bar(); 

But in Silverlight, I haven't found a means to call an interface directly on the Silverlight object. Instead, it appears interfaces can only be exposed on contained objects, as in:

var silverlightClient = document.GetElementById(_currentSilverlightId);
silverlightClient.Foo.Bar();

Where the "Foo" object above seems to be required, since

RegisterScriptableObject("Foo", MyFooObject);

can't be called with a null first parameter.

So, in Silverlight, is there any way to just have just:

silverlightClient.Bar();

?

Upvotes: 2

Views: 216

Answers (2)

Iain Ballard
Iain Ballard

Reputation: 4818

There is a bit of a laborious way of doing this (I'm in the same situation -- trying to drop a direct Silverlight replacement of a Flash app).

For every [ScriptableMember], call the BackBind method, with number of parameters after calling HtmlPage.RegisterScriptableObject("Foo", MyFooObject);

BackBind method:

void BackBind(string methodName, int argCount) {
    var id = HtmlPage.Plugin.Id;
    var sb = new StringBuilder();
    sb.Append("var x = document.getElementById('");
    sb.Append(id);
    sb.Append("'); x.");
    sb.Append(methodName);
    sb.Append(" = function(");

    for (int i = 0; i < argCount; i++) {
        if (i > 0) sb.Append(',');
        sb.Append((char)('A' + i)); // if you have more than 26 arguments, improve this!
    }

    sb.Append("){return x.content.");
    sb.Append(ScriptRegistration);
    sb.Append(".");
    sb.Append(methodName);
    sb.Append("(");

    for (int i = 0; i < argCount; i++) {
        if (i > 0) sb.Append(',');
        sb.Append((char)('A' + i)); // if you have more than 26 arguments, improve this!
    }

    sb.Append(");};");
    HtmlPage.Window.Eval(sb.ToString());
    // calls something like:  var x = document.getElementById('my_id'); x.Bar = function(a,b){return x.content.Foo.Bar(a,b);};
}

Usage example:

public class MyFooObject {
    const string ScriptRegistration = "Foo";
    public MyFooObject () {
        HtmlPage.RegisterScriptableObject(ScriptRegistration, this);
        BackBind("Bar", 2);
        BackBind("Baz", 0);
    }

    [ScriptableMember]
    public void Bar(string a, int b) { /* stuff */ }

    [ScriptableMember]
    public string Baz() { return "stuff"; }
}

Hope that helps!

Upvotes: 0

Jacob
Jacob

Reputation: 78860

If you're just wanting an object with a compatible interface, you could just do this:

var silverlightClient = document.GetElementById(_currentSilverlightId).Foo;

Upvotes: 1

Related Questions