2008-11-17 5 views
10

Estoy desarrollando un Applet invisible de Java, que se controlará completamente desde JavaScript.¿Cómo registrar una devolución de llamada de JavaScript en un Applet de Java?

Puedo llamar fácilmente a los métodos Java del applet, y puedo llamar a los métodos JavaScript desde el applet usando netscape.javascript.JSObject.getWindow(this).call().

Pero para registrar una devolución de llamada de JavaScript en el applet, supongo que necesitaría un objeto de función de JavaScript de algún tipo.

me gustaría hacer:

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

que podría llamar de Javascript:

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

así que podría llamar a esta función en el código más tarde:

func.call(...); 

hace algo como esto existe? ¿Cómo puedo hacer esto?

Rigth ahora estoy pensando en crear algo de Javascript para manejar este mecanismo de devolución de llamada en lugar de hacerlo desde el applet.

Respuesta

2

Soy nuevo en Java < -> comunicación de JavaScript, ya que planeaba explorarlo esta semana. Una buena oportunidad aquí ... :-)

Después de algunas pruebas, parece que no se puede pasar una función JS a un applet de Java. A menos que lo estoy haciendo por el camino equivocado ...

me trataron:

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); 
} 

donde llamada está (n) definido como:

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); 
} 

Cuando paso una función JS (todas las pruebas en FF3), obtengo un nulo en el lado de Java.

Tenga en cuenta que la siguiente rutina de Java permite visualizar el código JS de la función 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(); 
} 

Hasta el punto: Hice una función JS:

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

extraigo el nombre de la función JS del resultado toString y pasarlo al applet de Java. No creo que podamos manejar funciones anónimas porque Java llama a las funciones de JS por su nombre.

lado de 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

Parece que sólo se puede pasar a las funciones de Java por su nombre, por lo tanto, lo que se necesita hacer es crear un objeto de fachada que envuelva el applet y que tendría referencias de las funciones y proponer nombres temporales para ellos. – w00t

1

win.eval() llamará a un javascript predefinido.

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 es más genérico, por lo tanto, menos eficiente que llamar para esta tarea precisa, y es más complejo pasar parámetros a la función JS. – PhiLho

4

que dan cuenta de esto es una realidad vieja pregunta, pero el puesto 2 en una de mis búsquedas para otra cosa, y creo que el siguiente puede ayudar a otra persona que se encuentra presente.

Recientemente he hecho algo similar por el cual un applet de Java necesita volver a llamar a JavaScript al completar una tarea, llamando a diferentes funciones por éxito o error. Como ha sido la tendencia en los últimos tiempos, mis necesidades eran llamar a funciones anónimas definidas como parámetros pasados ​​a otras funciones. Este es el javascript en el lado del cliente:

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

Como se menciona en las otras respuestas, Java solo puede llamar a los métodos de JavaScript por su nombre. Esto significa que necesita un método de devolución de llamada global, que luego puede llamar a otros métodos como se da el caso:

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

Esta función se llama directamente desde el applet de 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}); 
} 

Usted podría mantenerse en el la referencia del objeto de parámetro que se pasa indefinidamente si desea utilizarlo como una forma de devolución de llamada registrada en lugar de uno desechable si es necesario, etc.

En nuestro caso, el procesamiento puede ser muy intenso, así que realmente giramos otro hilo: el cal lbacks todavía trabajan aquí también:

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(); 
} 
Cuestiones relacionadas