我正在努力使用测试数据通过JSNI利用一个名为cytoscape.js的外部JavaScript库。当我按我的Java类的要求运行脚本时,它无法生成图形。但是,当我通过Chrome Devtools控制台运行它时,它可以正常工作。
所有值似乎正确地传递到cytoscape.js库。当前,JSNI代码未能通过控制台库能够通过的Javascript库执行的测试。
这是我正在使用的JSNI代码:
public static native void cytoscape() /*-{
var cy = $wnd.cy = $wnd.cytoscape({container: $wnd.document.getElementById('cy'),
elements: $wnd.glyElements,
style: [ { selector: 'node', style: { 'background-color': '#666', 'label': 'data(id)' } },
{ selector: 'edge', style: { 'width': 3, 'line-color': '#ccc', 'target-arrow-color': '#ccc', 'target-arrow-shape': 'triangle' } } ],
layout: { name: 'grid', rows: 1 } });
}-*/;
“ $ wnd”。用于获取正确的范围。
这是控制台代码:
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
elements: glyElements,
style: [ { selector: 'node', style: { 'background-color': '#666', 'label': 'data(id)' } }, { selector: 'edge', style: { 'width': 3, 'line-color': '#ccc', 'target-arrow-color': '#ccc', 'target-arrow-shape': 'triangle' } } ],
layout: { name: 'grid', rows: 1 }
});
我在两种情况下使用的元素都存储在.js文件中,并且我确保在两种情况下都可以访问它们。就像我提到的那样,Devtools调试向我展示了正确的值已传递到cytoscape.js库中。
JSNI代码使cytoscape.js库中的以下return语句失败:
var plainObject = function plainObject(obj) {
return obj != null && _typeof(obj) === typeofobj && !array(obj) && obj.constructor === Object;
};
如果我注释掉“ && obj.constructor ===对象;”在cytoscape.js的第145行上,代码使用我的JSNI脚本正确运行。这使我相信通过JSNI和控制台创建cytoscape对象的方式有所不同。尽管如此,Dev工具仍将控制台和JSNI方法列为提供相同的对象。如何更新我的JSNI代码以使其符合此检查要求?
理想情况下,在这种情况下,JSNI应该可用。我不确定为什么通过JSNI传递值会导致该if语句在通过控制台运行时失败,并且会传递if语句。
答案 0 :(得分:2)
问题在于Object与Object不完全相同,并且检查instanceof
几乎肯定比cytoscape的作者认为的要多得多-JS难道不是吗?
cytoscape.js
项目的instanceof Object
测试不仅是对“这是一个普通对象而不是某种其他类型的实例”的测试,而且实际上是在测试“这是一个对象的实例吗? my 窗口实例中的对象类,而不是其他任何iframe /窗口中的对象类”。
GWT的默认链接器在iframe中评估您的代码,以防止意外泄漏全局变量并使加载到同一页面的JS混乱,或者让同一页面上的其他JS覆盖或以其他方式弄乱GWT的代码。
除了尝试将cytoscape的代码更正为不太僵化和不灵活的方式以外,还有几种方法可以解决此问题。
{...}
语法,该语法默认为您恰巧在其中执行的任何窗口。类似这样的东西: public static native void cytoscape() /*-{
var obj = new $wnd.Object();
obj.container = $wnd.document.getElementById('cy');//can also be simply $doc.getElementById('cy')
obj.elements = $wnd.glyElements;
// Note that you may have to repeat this for each of these nested objects, depending
// on how picky the library is being on otherwise identically structured code...
obj.style = [ { selector: 'node', style: { 'background-color': '#666', 'label': 'data(id)' } },
{ selector: 'edge', style: { 'width': 3, 'line-color': '#ccc', 'target-arrow-color': '#ccc',
'target-arrow-shape': 'triangle' } } ];
obj.layout = { name: 'grid', rows: 1 };
var cy = $wnd.cy = $wnd.cytoscape(obj);
}-*/;