Friday, June 3, 2016

Re: jsinterop: GWT app as a widdget: default script injection fails.

So here is a hacky workaround:

Q: What the hacky workaround enables?

A: You can inject any js library you want in the GWT iframe thus succeeding encapsulation of the GWT and js code from the rest of the page. No duplicate libaries - no clashed versions etc.

Q: Does it work?

A: sort of. jquery works because you can always search for elements with in $wnd and thus works correctly (at least the 3% I tried). Bootstrap modals on the other hand need to access the body element and there is no way to tell bootstrap (at least without a patch) that it should try to access the body that is parent of the $wnd.modal and not just "body". The same will be true for all javascript libraries that assume that they are running in page all by themselves.

Q: So what's the trick?

Pretty easy actually. The problem is that jsinterop assumes that js libraries are loaded in TOP_WINDOW ($wnd) and when this is not true it fails to find the functions to call them.

So let's give jsinterop a clue.

1) First of all create a js variable in top window that holds GWT iframe

    public static native void jsInit() /*-{
               $wnd.__gwtIFrame = $wnd.document.querySelectorAll('iframe#YourGWTApplicationID')[0].contentWindow;
    }-*/;

2) The load the jslibrary in GWT iframe

package com.common.lib.gwt.client.js.resources;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.ScriptInjector;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.TextResource;

public interface JQueryResources extends ClientBundle {
    public static final JQueryResources INSTANCE = GWT
            .create(JQueryResources.class);

    public static JQueryResources load() {
        // loads by default in GWT Iframe
        ScriptInjector.fromString(INSTANCE.js().getText()).inject();
        return INSTANCE;
    }

   @Source("jquery.min.js")
    TextResource js();
}

3) Then in jsinterop define __gwtIFrame as the namespace
 
    // instead of that
    // @JsMethod(namespace = JsPackage.GLOBAL)
    // do that
    @JsMethod(namespace = "__gwtIFrame")
     public static native <T extends JQuerySelection> T $(String selector);

Now you can call $ from GWT Iframe

Hope that helps somebody.

Any comments on the approach?

On Mon, May 30, 2016 at 10:58 AM, Vassilis Virvilis <vasvir2@gmail.com> wrote:
This looks like the logical conclusion to my question.
https://github.com/w3c/webcomponents/blob/gh-pages/proposals/Isolated-Imports-Proposal.md

Since the aboveis probably several years down the road I wonder if anyone has any more ideas or workarounds in how to work with GWT/jsinterop and foreign js libraries __loaded in GWT context__ (iframe) in the immediate future...

Anyone?

  Thanks in advance.

On Thu, May 26, 2016 at 1:01 PM, Vassilis Virvilis <vasvir2@gmail.com> wrote:
Hi,

This issue has been discussed before https://github.com/gwtproject/gwt/issues/9264

Here is the problem in my own words:

When a script is injected GWT has the option to inject it in the TOP_WINDOW ($wnd) or in the iframe window where GWT code is located normally.

Case 1: Insert in $wnd

Everything works but the page is polluted with the scripts you inject. This is not a problem when the GWT application controls the whole page. It is however a problem when GWT program is loaded as part of a page (Widget). Then all kind of problems may arise due to javascript libraries clashing.

Case 2: insert in iframe window (default)

The script is loaded but jsinterop assumes that the scripts are loaded in $wnd which is not true.

Question:

Is it possible to
1) add a compile time flag in jsinterop that will not prepend $wnd in all global objects defined by the script ...OR...
2) add a namespace JsPackage.LOCAL (as opposed to JsPackage.GLOBAL) option that does not imply $wnd ...OR...
3) do something that fixes the problem somehow!

--
Vassilis Virvilis



--
Vassilis Virvilis



--
Vassilis Virvilis

--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscribe@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at https://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment