]> source.dussan.org Git - vaadin-framework.git/commitdiff
Merged implementation for #3589
authorJoonas Lehtinen <joonas.lehtinen@itmill.com>
Fri, 6 Nov 2009 09:41:07 +0000 (09:41 +0000)
committerJoonas Lehtinen <joonas.lehtinen@itmill.com>
Fri, 6 Nov 2009 09:41:07 +0000 (09:41 +0000)
svn changeset:9659/svn branch:6.2

src/com/vaadin/terminal/gwt/client/ui/VView.java
src/com/vaadin/ui/Window.java
tests/src/com/vaadin/tests/tickets/Ticket3589.java [new file with mode: 0644]

index 35b411ff1bf6d79467a0a45e7f0218445399fc38..162d5fa5d7ac2c37dc8f4a31dd1f98d4eebb7366 100644 (file)
@@ -10,6 +10,7 @@ import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.Set;
 
+import com.google.gwt.core.client.JavaScriptObject;
 import com.google.gwt.dom.client.DivElement;
 import com.google.gwt.dom.client.Document;
 import com.google.gwt.event.logical.shared.ResizeEvent;
@@ -143,6 +144,40 @@ public class VView extends SimplePanel implements Container, ResizeHandler,
          $wnd.location.reload();
      }-*/;
 
+    /**
+     * Evaluate given script in browser document.
+     * 
+     * @param script
+     *            Script to be executed with $1, $2, ... markers to be replaced
+     *            with argument references.
+     * @param args
+     *            JavaScript array of element references to be replaced in
+     *            script
+     */
+    private static native void eval(String script, JavaScriptObject args)
+    /*-{
+      try {
+         if (script == null) return;
+         $wnd.evalargs = args;
+         if (args != null) 
+             for (var i=1;i<= args.length;i++) 
+                script = script.replace("$"+i, "$wnd.evalargs["+(i-1)+"]");
+         eval(script);
+         $wnd.evalargs = null;
+      } catch (e) {
+      }
+    }-*/;
+
+    /** Helper for creating empty javascript arrays */
+    private native static JavaScriptObject createArray() /*-{
+                                                         return new Array();
+                                                         }-*/;
+
+    /** Add an element to javascript array */
+    private native static void pushArray(JavaScriptObject array, Element e) /*-{
+                                                                            array.push(e);
+                                                                            }-*/;
+
     public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
         rendering = true;
 
@@ -263,6 +298,18 @@ public class VView extends SimplePanel implements Container, ResizeHandler,
                     actionHandler = new ShortcutActionHandler(id, client);
                 }
                 actionHandler.updateActionMap(childUidl);
+            } else if (tag == "execJS") {
+                String script = childUidl.getStringAttribute("script");
+                int argNum = childUidl.getChildCount();
+                JavaScriptObject args = createArray();
+                for (int i = 0; i < argNum; i++) {
+                    String id = childUidl.getChildUIDL(i).getStringAttribute(
+                            "ref");
+                    Paintable p = client.getPaintable(id);
+                    pushArray(args, p == null ? null : ((Widget) p)
+                            .getElement());
+                }
+                eval(script, args);
             } else if (tag == "notifications") {
                 for (final Iterator it = childUidl.getChildIterator(); it
                         .hasNext();) {
index a91bd4026bd1ba2353a07d707de3abcfdf00846f..d8f4972104794b7250808e1c4c513f3240907a0a 100644 (file)
@@ -8,6 +8,7 @@ import java.io.Serializable;
 import java.lang.reflect.Method;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
@@ -19,6 +20,7 @@ import com.vaadin.Application;
 import com.vaadin.terminal.DownloadStream;
 import com.vaadin.terminal.PaintException;
 import com.vaadin.terminal.PaintTarget;
+import com.vaadin.terminal.Paintable;
 import com.vaadin.terminal.ParameterHandler;
 import com.vaadin.terminal.Resource;
 import com.vaadin.terminal.Sizeable;
@@ -119,6 +121,9 @@ public class Window extends Panel implements URIHandler, ParameterHandler {
 
     private Focusable pendingFocus;
 
+    private ArrayList<String> jsExecQueue = null;
+    private ArrayList<ArrayList<Paintable>> jsExecParamsQueue = null;
+
     /* ********************************************************************* */
 
     /**
@@ -520,6 +525,26 @@ public class Window extends Panel implements URIHandler, ParameterHandler {
         // Contents of the window panel is painted
         super.paintContent(target);
 
+        // Add executable javascripts if needed
+        if (jsExecQueue != null) {
+            while (jsExecQueue.size() > 0) {
+                String script = jsExecQueue.get(0);
+                ArrayList<Paintable> args = jsExecParamsQueue.get(0);
+                target.startTag("execJS");
+                target.addAttribute("script", script);
+                for (Paintable p : args) {
+                    target.startTag("arg");
+                    target.paintReference(p, "ref");
+                    target.endTag("arg");
+                }
+                target.endTag("execJS");
+                jsExecQueue.remove(0);
+                jsExecParamsQueue.remove(0);
+            }
+            jsExecQueue = null;
+            jsExecParamsQueue = null;
+        }
+
         // Window position
         target.addVariable(this, "positionx", getPositionX());
         target.addVariable(this, "positiony", getPositionY());
@@ -1632,4 +1657,67 @@ public class Window extends Panel implements URIHandler, ParameterHandler {
         }
     }
 
+    /**
+     * Executes JavaScript in this window.
+     * 
+     * <p>
+     * This method allows one to inject javascript from the server to client.
+     * Client implementation is not required to implenment this functionality,
+     * but currently all web-based clients do implement this.
+     * </p>
+     * 
+     * <p>
+     * The script may contain markers indentified with "$x", where x is a one
+     * digit number. The number of markers must match to the number of optional
+     * Paintable reference parameters. The first marker is $1, second $2 and so
+     * on. If the markers are specified, the markers are replaced in the browser
+     * with references to outmost DOM elements connected to the given
+     * paintables.
+     * </p>
+     * 
+     * <p>
+     * Use example 1: <code>
+       mainWindow.executeJavaScript("alert(foo");
+     * </code>
+     * </p>
+     * 
+     * <p>
+     * Use example 2: <code>
+        Label label = new Label("Label");
+        TextField textfield = new TextField("TestField");
+        mainWindow.addComponent(label);
+        mainWindow.addComponent(textfield);
+        mainWindow.executeJavaScript("$1.style.backgroundColor='yellow';$2.style.borderColor='red';",label,textfield);
+     * </code>
+     * </p>
+     * 
+     * @param script
+     *            JavaScript snippet that will be executed and that might
+     *            optionally contain $1, $2, ... markers.
+     * @param paintables
+     *            References to number of visible paintables that correspond the
+     *            to markers listed in script
+     */
+    public void executeJavaScript(String script, Paintable... paintables) {
+
+        if (getParent() != null) {
+            throw new UnsupportedOperationException(
+                    "Only application level windows can execute javascript.");
+        }
+
+        ArrayList<Paintable> ps = new ArrayList<Paintable>();
+        for (Paintable p : paintables) {
+            ps.add(p);
+        }
+
+        if (jsExecQueue == null) {
+            jsExecQueue = new ArrayList<String>();
+            jsExecParamsQueue = new ArrayList<ArrayList<Paintable>>();
+        }
+
+        jsExecQueue.add(script);
+        jsExecParamsQueue.add(ps);
+
+        requestRepaint();
+    }
 }
diff --git a/tests/src/com/vaadin/tests/tickets/Ticket3589.java b/tests/src/com/vaadin/tests/tickets/Ticket3589.java
new file mode 100644 (file)
index 0000000..5b7182e
--- /dev/null
@@ -0,0 +1,39 @@
+package com.vaadin.tests.tickets;
+
+import com.vaadin.Application;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.Window;
+import com.vaadin.ui.Button.ClickEvent;
+
+public class Ticket3589 extends Application {
+
+    @Override
+    public void init() {
+        final Window mainWindow = new Window("Test");
+        setMainWindow(mainWindow);
+
+        mainWindow.addComponent(new Button("alert('foo')",
+                new Button.ClickListener() {
+
+                    public void buttonClick(ClickEvent event) {
+                        mainWindow.executeJavaScript("alert('foo');");
+                    }
+                }));
+
+        final Label label = new Label("Label");
+        final TextField textfield = new TextField("TestField");
+        mainWindow.addComponent(label);
+        mainWindow.addComponent(textfield);
+
+        final String script = "$1.style.backgroundColor='yellow';$2.style.borderColor='red';";
+        mainWindow.addComponent(new Button(script, new Button.ClickListener() {
+
+            public void buttonClick(ClickEvent event) {
+                mainWindow.executeJavaScript(script, label, textfield);
+            }
+        }));
+
+    }
+}