2012-05-04 6 views
2

Общая цель: вызвать некоторые нестатический метод Java из JavaScriptВозможность вызвать нестатический метод GWT Java с JavaScript

Описание: Чтобы найти виджет GWT на DOM в Java Applet код и назвать это метод Java (не статический)


JSObject win = JSObject.getWindow(this); 
JSObject doc = (JSObject) win.getMember("document"); 
JSObject gwtWidget = (JSObject) doc.call("getElementsByName", widgetName); 

//todo: have possibility to call `exported` java method over here, smth like: 
//Object[] params = new Object[1]; 
//params[0] = widgetName; 
//Object result = gwtWidget.call("exportedJavaMethod", params); 

//todo: or just call global ($wnd) static JSNI bridge method: 
//Object result = win.call("exportedJavaMethod", params); 
// 

Проблема: я могу найти по id виджета, а не по виджетам, но это DivElement, у которого нет экспортированных инстантных методов.

Мой класс виджет Exportable (GWT-экспорт):


@Export(value="somewidget") 
public class SomeWidget extends SimplePanel implements ..., Exportable { 
    private final String id = "id_some_widget_" + count++; 
    private static int count = 0; 

    public SomeWidget() { 
     getElement().setAttribute("name", id); 
     getElement().setId(id); 
    } 
    ... 

    public static Element getInstanceById(String elementId) { 
     Element someWidget= DOM.getElementById(elementId); 
     return someWidget; 
    } 

    public String getSomeInstancedData() { 
     return "useful_inner_data" + this.id; 
    } 

Так, например, я хотел бы, чтобы найти конкретный виджет добавлен в DOM и вызвать нестатический метод getSomeInstancedData() в JavaScript. Это вообще возможно?

Пусть как-л:


var someWidget = document.getElementById(widgetId); 
alert(someWidget.getSomeInstancedData()); 

//or: 
var someWidgetExported = com.mypackage.widgets.somewidget.getInstanceById(listenerId); 
alert(someWidgetExported.getSomeInstancedData()); 

В модуле Base я пишу:


ExporterUtil.exportAll(); 

Существует мнение (ViewWithSomeWidget.ui.xml), который содержит этот виджет:

 
... 
base:Form 
base:SomeWidget ui:field="someWidget" ... 
... 
/base:SomeWidget 
... 

Когда SomeWidget не реализует Exportable, проект работает хорошо, но я не мог назвать нестатические методы поиска виджета DIV.

К тому времени, чтобы решить эту проблему SomeWidget реализует Exportable, но Progect не показывает вид с SomeWidget хорошо из-за ClassCastException использованием отложенного связывания:


ClassCastException: com.mypackage.widgets.SomeWidgetExporterImpl cannot be cast to com.mypackage.widgets.SomeWidget 

Таким образом, вероятно, есть какие-либо другие методы найти javascript-объект виджета и вызвать его экспортированный метод java? В любом случае, любая идея очень ценится.

ответ

11

Вы можете объявить функцию javascript, которая будет запускать нестатический метод.

Например:

package com.example; 
public class Layout extends VLayout() { 
    private String nonStaticVar = "nonStaticVar"; 
    public Layout() { 
     declareMethod(this); 
    } 

    //Method which declares non-static method in javascript 
    public native void declareMethod(Layout layout) /*-{ 
     var layout = layout; 
     $wnd.doSomething = function(someString) { 
      [email protected]::doSomething(Ljava/lang/String;)(someString); 
     } 
    }-*/; 

    //Non static method which is being called 
    public String doSomething(String someString) { 
     //Do something, e.g. set var in this instantiated class, or output stuff 
     this.nonStaticVar = someString; 
     Window.alert(someString); 
    } 
} 

Теперь, называя DoSomething ("бла"); из javascript вызовет ваш нестатический метод.

1

вместо того, чтобы пытаться принести виджет через DOM элемент, впрыснуть его экземпляр Java первую в глобальном масштабе и относятся к нему:

public class SomeWidget extends SimplePanel implements ..., Exportable { 

    //... 

    public SomeWidget() { 
     getElement().setAttribute("name", id); 
     getElement().setId(id); 

     attachToGlobalScope(id, this); 
    } 

    private native void attachToGlobalScope(String id, SomeWidget instance) /*-{ 
     $wnd.shared[id] = instance; 
    }-*/; 

    //... 
} 

, чем позже, обновлять соответствующие выборки в Applet API слоя:

JSObject win = JSObject.getWindow(this); 
JSObject shared = (JSObject) win.getMember("shared"); 
Widget widgetRef = (Widget) shared.getMember(widgetId); 

отречения: это несколько криво решение реле на JavaScript переменных глобальной области, который считается плохой практикой в ​​целом, но здесь действует в качестве единственного общего объема, таким образом, злоупотребляет для хранения объектов.

+0

проблема заключается в том, что getElement() возвращает элемент DIV, который не имеет объявленных java-методов ... На самом деле, я уже пробовал почти такую ​​же попытку. Текущее решение, которое я использую на мгновение, - объявить статический метод (мост), который будет запускать GWTEvent с полезными обернутыми данными. И Widget просто слушает такие события, подписываясь в своем contructor. Каждый экземпляр Widget получит событие и просто фильтрует его собственным идентификатором. – rauch

+0

@rauch, я понимаю, что тиканье другого ответа принято, так как оно лучше решает проблему, но зачем также удалять голосование? –

4

вы можете определить собственный jsmethod на элементе сНа, который может назвать виджет-метод

@Export(value="somewidget") 
public class SomeWidget extends SimplePanel implements ..., Exportable { 
    private final String id = "id_some_widget_" + count++; 
    private static int count = 0; 

    public SomeWidget() { 
     getElement().setAttribute("name", id); 
     getElement().setId(id); 
     attachInstanceHook(getElement()); 
    } 
    ... 

    public String getSomeInstancedData() { 
     return "useful_inner_data" + this.id; 
    } 


    private native void attachInstanceHook(Element element) /*-{ 
     var elem = element; 
     var widget = this; 
     elem.getWidgetData = function() { 
      [email protected]::getSomeInstancedData()(); 
     }; 

    }-*/; 

и ваш JS-код должен выглядеть следующим образом:

var someWidget = document.getElementById(widgetId); //the id of the div element 
alert(someWidget.getWidgetData());