I'm trying to wrap a javascript library (Cytoscape Web:
http://cytoscapeweb.cytoscape.org/documentation ) that exposes methods
for interacting with a Flash object built with Flex. The library is
designed very well, consisting of a single javascript Visualisation
object and several member functions. These functions usually take
JSON-like objects as arguments, and I'm encountering an error when I
construct the object within a JSNI method. The Flash player error is
"Error #1034: Type Coercion failed: cannot convert Object@3cf6821 to
Array."
Here is my class that extends JavaScriptObject and wraps the library's
Visualisation object:
public class Visualization extends JavaScriptObject{
protected Visualization(){}
public static final native Visualization create()/*-{
var div_id = "cytoscapeweb";
var options = {
// where you have the Cytoscape Web SWF
swfPath: "swf/CytoscapeWeb",
// where you have the Flash installer SWF
flashInstallerPath: "swf/playerProductInstall"
};
var vis = new $wnd.org.cytoscapeweb.Visualization(div_id,
options);
return vis;
}-*/;
/* BROKEN: Causes the Flash error #1034 */
public final native void draw()/*-{
var network_json = {
data: {
nodes: [ { id: "1" }, { id: "2" } ],
edges: [ { id: "2to1", target: "1", source: "2" } ]
}
};
this.draw({network: network_json});
}-*/;
}
Whenever I call the draw function using a javascript object as an
argument, I get the error #1034 type conversion problem. However, the
library has an alternate method for encoding a graph using an XML
string, and passing the string literal works!
/* Passing a string literal works fine. No error with this method
*/
public final native void draw()/*-{
var xml = '\
<graphml>\
<key id="label" for="all"
attr.name="label"
attr.type="string"/>\
<key id="weight" for="node"
attr.name="weight"
attr.type="double"/>\
<graph edgedefault="directed">\
<node id="1">\
<data key="label">A</data>\
<data key="weight">2.0</data>\
</node>\
<node id="2">\
<data key="label">B</data>\
<data key="weight">1.5</data>\
</node>\
<node id="3">\
<data key="label">C</data>\
<data key="weight">1.0</data>\
</node>\
<edge source="1" target="2">\
<data key="label">A to B</data>\
</edge>\
<edge source="1" target="3">\
<data key="label">A to C</data>\
</edge>\
</graph>\
</graphml>\
';
this.draw({network: xml});
}-*/;
Furthermore, I tried hard-coding the javascript object in the <head>
section of the HTML file, and it ends up working just fine, too
(referenced with the $wnd variable)!
public final native void draw()/*-{
this.draw({network: $wnd.network_json});
}-*/;
Note, however, that if I redefine the $wnd.network_json variable
within the JSNI method, the same error rears its ugly head.
In summary, the flash object seems to not agree with me passing it an
object that I create through a JSNI method. Whenever the object is
hard-coded into the HTML page, there are no errors; copy-pasting the
exact same object into a JSNI method results in an odd error about
converting the object into Array. I've traced through the code with
FireBug, and the object referenced seems fine to me. I don't really
have any way to debug the Flex application, so I'm at a loss to see
what it's complaining about. To me it just seems peculiar that it
only fails when created through a JSNI method. Any help with this
brain-teaser would be kindly appreciated!