2008-11-17 8 views
10

Я разрабатываю невидимый Java-апплет, который будет полностью управляться JavaScript.Как зарегистрировать обратный вызов JavaScript в Java-апплете?

Я могу легко вызвать методы Java апплета, и я могу вызвать методы JavaScript из апплета, используя netscape.javascript.JSObject.getWindow(this).call().

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

Я хотел бы сделать:

public void registerCallback(SomeJavascriptFunction func) { ... } 

Что я мог бы назвать из Javascript:

myapplet.registerCallback(function(){ alert("called back"); }); 

Так что я мог бы вызвать эту функцию в пожилом код:

func.call(...); 

ли что-то как это существует? Как я могу это сделать?

Теперь я собираюсь создать Javascript для обработки этого механизма обратного вызова вместо этого из апплета.

ответ

2

Я новичок в Java < -> JavaScript-коммуникация, так как я планировал исследовать ее на этой неделе. Хорошая возможность здесь ... :-)

После некоторых тестов кажется, что вы не можете передать JS-функцию в Java-апплет. Если я не делаю это неправильный путь ...

Я пробовал:

function CallJava() 
{ 
    document.Applet.Call("Does it work?"); 
    document.Applet.Call(function() { alert("It works!"); }); 
    document.Applet.Call(DoSomething); // A simple parameterless JS function 
    document.Applet.Call(window.location); 
} 
function DumbTest(message, value) 
{ 
    alert("This is a dumb test with a message:\n" + message + "\n" + value); 
} 

, где вызов (ются) определяется как:

public void Call(String message) 
{ 
    JSObject win = (JSObject) JSObject.getWindow(this); 
    String[] arguments = { "Call with String", message }; 
    win.call("DumbTest", arguments); 
} 

public void Call(JSObject jso) 
{ 
    JSObject win = (JSObject) JSObject.getWindow(this); 
    String[] arguments = { "Call with JSObject", jso.toString() }; 
    win.call("DumbTest", arguments); 
} 

Когда я прохожу функцию JS (все тесты в FF3), я получаю нуль на стороне Java.

Обратите внимание, что следующая процедура Java позволяет отображать JS-код функции DumberTest!

public int Do() 
{ 
    JSObject win = (JSObject) JSObject.getWindow(this); 
    JSObject doc = (JSObject) win.getMember("document"); 
    JSObject fun = (JSObject) win.getMember("DumberTest"); 
    JSObject loc = (JSObject) doc.getMember("location"); 
    String href = (String) loc.getMember("href"); 
    String[] arguments = { href, fun.toString() }; 
    win.call("DumbTest", arguments); 
    return fun.toString().length(); 
} 

К точке: Я сделал функцию JS:

function RegisterCallback(cbFunction) 
{ 
    var callback = cbFunction.toString(); // We get JS code 
    var callbackName = /^function (\w+)\(/.exec(callback); 
    document.Applet.RegisterCallback(callbackName[1]); 
} 

извлечь имя функции JS из результата ToString и передать его в Java-апплета. Я не думаю, что мы можем обрабатывать анонимные функции, потому что Java вызывает JS-функции по имени.

Java сторона:

String callbackFunction; 
public void RegisterCallback(String functionName) 
{ 
    callbackFunction = functionName; 
} 
void UseCallbackFunction() 
{ 
    if (callbackFunction == null) return; 
    JSObject win = (JSObject) JSObject.getWindow(this); 
    win.call(callbackFunction, null); 
} 
+0

кажется, что вы можете передать функции Java по имени, поэтому то, что вам нужно сделать, это создать объект фасада, который будет обернуть апплет и который будет принимать ссылки функции и придумайте временные имена для них. – w00t 2011-08-04 04:44:15

1

win.eval() будет вызывать предустановленный JavaScript.

String callbackFunction; 
public void RegisterCallback(String functionName) 
{ 
    callbackFunction = functionName; 
} 
void UseCallbackFunction() 
{ 
    if (callbackFunction == null) return; 
    JSObject win = (JSObject) JSObject.getWindow(this); 
    win.eval(callbackFunction); 
} 
+0

eval более общий, следовательно, менее эффективен, чем вызов этой точной задачи, и сложнее передать параметры функции JS. – PhiLho 2008-11-18 09:23:17

4

Я понимаю, что это на самом деле старый вопрос, но он занимает 2 место в одном из моих поисках чего-то еще, и я думаю, что ниже, может помочь кому-то еще, что это находит.

Я недавно сделал что-то подобное, благодаря чему Java-аплету нужно было перезвонить в JavaScript по завершении задачи, вызвав различные функции при успешном выполнении или ошибке. Как и в последнее время, мои потребности заключались в анонимных функциях, определяемых как параметры, передаваемые другим функциям. Это Javascript на стороне клиента:

applet.DoProcessing({ 
    success: function(param) { 
     alert('Success: ' + param); 
    }, 
    error: function(param) { 
     alert('Failed: ' + param); 
    } 
}); 

Как уже упоминалось в других ответах, Java может вызвать только на методы JavaScript по имени. Это означает, что вам нужен глобальный метод обратного вызова, который затем может вызывать другие методы, как это необходимо:

function ProcessingCallback(isSuccessful, cbParam, jsObject) { 
    if (isSuccessful && jsObject.success) 
     jsObject.success(cbParam); 
    else if (!isSuccessful && jsObject.error) 
     jsObject.error(cbParam); 
} 

Эта функция вызывается непосредственно из Java-апплета:

public void DoProcessing(final Object callbacks) { 
    //do processing.... 


    JSObject w = JSObject.getWindow(this); 
    //Call our named callback, note how we pass the callbacks parameter straight 
    //back out again - it will be unchanged in javascript. 
    w.call("ProcessingCallback", new Object[]{successful, output, callbacks}); 
} 

Вы могли бы провести на ссылка на объект параметра передается неограниченно, если вы хотите использовать его как некоторая форма зарегистрированного обратного вызова, а не как однократная, если это необходимо и т. д.

В нашем случае обработка может быть временной интенсивной, поэтому мы фактически вращаем еще один поток - cal lbacks еще здесь работает также:

public void DoProcessing(final Object callbacks) { 
    //hold a reference for use in the thread 
    final Applet app = this; 

    //Create a new Thread object to run our request asynchronously 
    //so we can return back to single threaded javascript immediately 
    Thread async = new Thread() { 
     //Thread objects need a run method 
     public void run() { 
      //do processing.... 


      JSObject w = JSObject.getWindow(app); 
      //Call our named callback, note how we pass the callbacks parameter 
      //straight back out again - it will be unchanged in javascript. 
      w.call("ProcessingCallback", new Object[]{successful, output, callbacks}); 
     } 
    } 
    //start the thread 
    async.start(); 
}