Javascript to Java call from Embedded

Hello

My scenario:
I have a html page containing a Flash object (a tagcloud) and a bit of javascript to set some parameter of mentioned object.
When you click on a Tag of the Tagcloud the Flash object “executes” a href tag which then should cause a Vaadin application, in which it is embedded, to switch to another menu.

Until now i solved it by using the Embedded/BrowserFrame component to embed the html page inside the application and then when you click on a tag setting the url to the same page + hash + a number. Then in the Java/Vaadin class i added a UriFragmentListener to get this number and then make my operations.
This worked decently well but it was not very quick, acted different in some browsers( IE ) and was messing up my Fragment controlled Navigation.

Now after updating to Vaadin 7.1.1 i decided to try something out:
I would like to call a java function inside a Client-side Widget from Javascript and then directly start my operations. I already created a Custom Component and made a function which will update the text of a gwt label but i’m having problems calling the java function from the javascript.

My JavaScript line is: this.@com....widgetset.client.MyComponentWidget::dostuff(Ljava/lang/String;)("Test"); and the important part in widget looks like this:[code]
public class MyComponentWidget extends Label {
public static final String CLASSNAME = “mycomponent”;

public MyComponentWidget() {
    setText("This is MyComponent");
    setStyleName(CLASSNAME);
    //dostuff("testing123");
}
public void dostuff(String text){
  client.updateVariable(PID, "dostuff", text, true);   
}

private ApplicationConnection client;
private String PID;

public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
     this.client = client;
     this.PID = uidl.getId();
}

}

[/code]My html doesn’t even render as it says the line i posted is an Illegal Argument.

What am i doing wrong? Is it even possible to use an Embedded/BrowserFrame for this? Would it work better with a CustomLayout in which the html is embedded? …or maybe even using a JavaScriptComponent…somehow?

I know these are a lot of questions but this problem already bugged me before Vaadin 7 was even released.

Best Regards,
M R

Update: Added more code from the Widget because when i just call dostuff from the widget constructur my app is crashing and giving me this javascript exception in the DevTool Console of the browser. SEVERE: (TypeError) : Cannot call method 'bj' of nullcom.google.gwt.core.client.JavaScriptException: (TypeError) : Cannot call method 'bj' of null As i’m quite new to this whole Custom Component thing i don’t know if that’s supposed to happen, something changed in Vaadin 7 or i’m doing something wrong.

Do you need more information or is this something too extraordinary for someone to know?

It is not clear where that line is defined. The syntax is only valid inside JSNI methods (i.e. native methods in GWT code) and not in e.g. external javascript files. If you want external javascript to be able to call into GWT code, you’d need to “export” that function as a JavaScript function. See
http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJSNI.html#calling
for a simple example of how to do this.

In your case, I would however suggest completely leaving out the GWT part. It seems that what you are trying to do could be achieved using only JavaScript and server-side Java, either with
JavaScript.addFunction
or as a
JavaScript Component
.

Thank you Leif for your reply.

I now ditched the GWT idea (which i only used because it was mentioned in another forum thread) and tried it with the JavaScript.addFunction method. I can’t believe i missed it because i thought i read through pretty much all wiki articles regarding Vaadin 7.
The only problem is that it’s not really working with my Embedded.
In my UI init method i have: JavaScript.getCurrent().addFunction("tagcloudclick", new JavaScriptFunction() { public void call(JSONArray arguments) throws JSONException { Notification.show("Test"); } }); When i call tagcloudclick() in the Chrome Dev Tool Console it is working fine but when i use it like this: tagcloudclick(); in the Javascript tag of my embedded html it isn’t called and also not when i try to use it like this: <a href='javascript:(function(){tagcloudclick();})();' style='12' color='0x0072BA' hicolor='0x000000' >sometag</a> from the produced flash/html. It looks like the calls in the embedded are expecting to find the function in the header or body of its html tag and not inside of the main Vaadin-Application html tag.

Is there a way to route the calls outside of the embedded or am i doing something wrong? Maybe i have to embed the html page differently?

An embedded html page can’t directly access javascript from the original page. If both pages are loaded from the same domain, you could try using window.parent.tagcloudclick(). The browser will however stop this for security reasons if the pages are loaded from different domains.

Do you need to have the tagcloud as a separate HTML document loaded with Embedded now that you are no longer depending on URL changes for detecting the clicks?

Using window.parent works when i execute from the javascript tag of the html’s body of the Embedded but not when i change the href to: <a href='javascript:(function(){window.parent.tagcloudclick();})();'... I don’t really need it as an embedded objects if i can add it to my app in a different way. If you want to have a look at the base html structure you can have a look
here
(This site written in German but it shouldn’t be necessary to read any of it except of the html code which is displayed in the middle).
What would be the best way to do it otherwise?

PS: I just remembered that i’m sending some parameters (the tags for the cloud) via the url of the html but i think that if the html is “embedded” differently/closer then using an Embedded Component this should not be a big problem.

After a lot of testing i now managed to load my html in a customLayout and send a Javascript to Java call from a Tag to the Vaadin class the Customlayout is defined in. I just had a few problems attaching the Javascript and Flash classes/objects to it and executing some javascript which is normally in the script tag of the html. I solved it by adding the Javascript class in the bootstrap header, fixing the path to the Flash object and executing the Javascript from Java using Javascript.getCurrent().execute after the Customlayout instance was created.

I even tried to replace the tags with

tags to replace the tags with Vaadin components but the Flash objects sadly doesn’t render anything except an -tag (not even html input tags).

Is there a better way for my purpose or did i use the optimal way?

Thank you Leif for your support.

Update: I just now succeeded in creating a JavaScript Component from the TagCloud files (just need to add the event handling now). This makes it even easier to integrate it into a Vaadin Application.
I really start loving what you put in Vaadin 7 to integrate JavaScript better :slight_smile:

Ok I’m still having a little problem with my JavaScriptComponent. Especially when it comes to the RPC between the JavascriptConnector and the Server-side Java class.

My connector.js looks something like this:[code]
com_…TagCloudComp = function(){
//All the code to create the Javascript object from the library
}

function tagcloudclicked(numberclicked){

}
[/code]The tagcloudclicked method already gets executed (tested with alert) but the Java class just doesn’t recognize it althoug i added: addFunction("tagcloudclicked", new JavaScriptFunciton(){ .... }) to it. Also when i remove the tagcloudclicked function from the connector i can’t call tagcloudclicked() through the console like i could when i added the function in the ui or a “layout class”.
When i use JavaScript.getCurrent().addFunction(“tagcloudclicked”,… from the ui or customcomponent/layout class it gets called, btw.

Am i missing something obvious here?

If i change the this.addFunction(… in the JS Component constructor to JavaScript.getCurrent().addFunction(… it works.
So i’m not sure if either the method is broken or if there is something else wrong, like for example a domain thing as Leif pointed out.

So as a workaround i’m currently testing if it works when i add the function in the constructor and remove it in the DetachListener (to avoid having more identical functions added).

So the workaround works but still i would like to know whether it’s a bug that the AbstractJavaScriptComponent.addFunction method doesn’t work (for me) or i did something wrong.