Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    SmartClient code running from within JSNI

    Dear Folks:

    I'm trying to run SmartClient code triggered from within SmartGWT code.

    So I've written the following class:
    public class ScriptHelper {

    public static native void runJavascript(String javascript) /*-{


    console.log("Trying to create window");
    $wnd.isc.Window.create({
    ID: "modalWindow",
    title: "Modal Window",
    autoSize:true,
    autoCenter: true,
    isModal: true,
    showModalMask: true,
    autoDraw: false,
    closeClick : function () {console.log("CloseClick");},
    items: [
    $wnd.isc.IButton.create({
    ID: "touchButton",
    width: 120,
    title: "Touch This"
    })
    ]
    });
    console.log("Created Window "+$wnd.modalWindow);
    console.log("Trying to show window");
    $wnd.modalWindow.show();
    console.log("ScriptHelper.runJavascript: Done with function");
    //eval(javascript);
    }-*/;
    }

    The code gets stuck at $wnd.modalWindow.show();

    In the Chrome debugger, I see the following exception thrown:

    TypeError: _4.duplicate is not a function at Object.isc_Window_makeBody [as makeBody]

    _4 in this context is an Array of size 1, i.e., the list of items defined for the Window.

    Versions:

    Chrome 46.0.2490.33 beta (64-bit)

    SmartClient Version: v9.1p_2015-09-01/PowerEdition Deployment (built 2015-09-01)

    What am I missing?

    Thanks for the help.





    #2
    OK, I figured out how to make it work. The items in the Window are declared straightforwardly as a Javascript array [...]. However, that array doesn't get the duplicate method attached, since the array is apparently created outside of the gwt frame. To make it work, I had to change the way items was declared, i.e.,
    ve items: new $wnd.Array(
    $wnd.isc.IButton.create({
    ID: "touchButton",
    width: 120,
    title: "Touch This",
    click: function () {alert('hello world');}
    })
    )

    This can work, but it's a bit more awkward. If there's a better way, I'm all ears.


    Let me expand on the specific use case I'm trying to solve. I want to allow our users to be able to create user interface elements from within our application.I've created the ability for users to edit javascript using the gwt-ace editor, built on top of the very flexible ace editor. For example, a user could use VisualBuilder to create UI elements expressed as javascript and copy and paste the javascript into the ace editor pane.

    I'm able to get that javascript executed (by using JSNI to take that string containing javascript and wrapping it in a Javascript function, and injecting the $wnd parameter into the Function).

    I was having troubles, though, with basically the javascript above because of the .duplicate method not existing outside the gwt frame. The solution to create arrays using new $wnd.Array() solves the immediate problem, with some awkwardness.

    So my real question is: is there a better way to dynamically create UI elements from within my application?

    Comment


      #3
      OK, I figured out the scoping issue. Here's the JSNI code that works to run the Javascript inside the gwt frame...
      public static native void runJavascript(String javascript) /*-{
      var dynamically_defined_function = new $wnd.Function('isc','wnd',javascript);
      dynamically_defined_function.call($wnd,$wnd.isc,$wnd);
      }-*/;


      The key is new $wnd.Function(). Originally it was just new Function(). new $wnd.Function() creates the dynamic function inside the scope of the GWT frame. new Function() creates the function in the scope of the main window, not the scope of the frame.

      Comment

      Working...
      X