]> source.dussan.org Git - vaadin-framework.git/commitdiff
Migrate AbstractJavaScriptRenderer to the new Grid (#182).
authorDenis Anisimov <denis@vaadin.com>
Wed, 21 Sep 2016 13:22:47 +0000 (16:22 +0300)
committerVaadin Code Review <review@vaadin.com>
Fri, 23 Sep 2016 10:36:45 +0000 (10:36 +0000)
Change-Id: Ic514875fab8d90484b3a73b073bcc9d53697de75

client/src/main/java/com/vaadin/client/connectors/JavaScriptRendererConnector.java [new file with mode: 0644]
client/src/main/java/com/vaadin/client/connectors/grid/AbstractGridRendererConnector.java
server/src/main/java/com/vaadin/ui/renderers/AbstractJavaScriptRenderer.java [new file with mode: 0644]
uitest/src/main/java/com/vaadin/tests/components/grid/JavaScriptRenderers.java [new file with mode: 0644]
uitest/src/main/java/com/vaadin/tests/components/grid/JavaScriptStringRenderer.java [new file with mode: 0644]
uitest/src/main/java/com/vaadin/tests/components/grid/MyBeanJSRenderer.java [new file with mode: 0644]
uitest/src/main/resources/com/vaadin/tests/components/grid/myBeanJsRenderer.js
uitest/src/main/resources/com/vaadin/v7/tests/components/grid/JavaScriptStringRenderer.js [new file with mode: 0644]
uitest/src/main/resources/com/vaadin/v7/tests/components/grid/myBeanJsRenderer.js [new file with mode: 0644]
uitest/src/test/java/com/vaadin/tests/components/grid/JavaScriptRenderersTest.java [new file with mode: 0644]

diff --git a/client/src/main/java/com/vaadin/client/connectors/JavaScriptRendererConnector.java b/client/src/main/java/com/vaadin/client/connectors/JavaScriptRendererConnector.java
new file mode 100644 (file)
index 0000000..90ced5e
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.connectors;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.core.client.JsArrayString;
+import com.google.gwt.dom.client.NativeEvent;
+import com.vaadin.client.JavaScriptConnectorHelper;
+import com.vaadin.client.Util;
+import com.vaadin.client.communication.HasJavaScriptConnectorHelper;
+import com.vaadin.client.connectors.grid.AbstractGridRendererConnector;
+import com.vaadin.client.connectors.grid.GridConnector;
+import com.vaadin.client.renderers.ComplexRenderer;
+import com.vaadin.client.renderers.Renderer;
+import com.vaadin.client.widget.grid.CellReference;
+import com.vaadin.client.widget.grid.RendererCellReference;
+import com.vaadin.shared.JavaScriptExtensionState;
+import com.vaadin.shared.ui.Connect;
+
+import elemental.json.JsonObject;
+import elemental.json.JsonValue;
+
+/**
+ * Connector for server-side renderer implemented using JavaScript.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+// This is really typed to <JsonValue>, but because of the way native strings
+// are not always instanceof JsonValue, we need to accept Object
+@Connect(com.vaadin.ui.renderers.AbstractJavaScriptRenderer.class)
+public class JavaScriptRendererConnector
+        extends AbstractGridRendererConnector<Object>
+        implements HasJavaScriptConnectorHelper {
+    private final JavaScriptConnectorHelper helper = new JavaScriptConnectorHelper(
+            this);
+
+    private final JavaScriptObject cellReferenceWrapper = createCellReferenceWrapper();
+
+    @Override
+    protected void init() {
+        super.init();
+        helper.init();
+
+        addGetRowKey(helper.getConnectorWrapper());
+    }
+
+    private static native JavaScriptObject createCellReferenceWrapper()
+    /*-{
+        var reference = {};
+    
+        var setProperty = function(name, getter, setter) {
+            var descriptor = {
+                get: getter
+            }
+            if (setter) {
+                descriptor.set = setter;
+            }
+            Object.defineProperty(reference, name, descriptor);
+        };
+    
+        setProperty("element", function() {
+            return reference.target.@CellReference::getElement()();
+        }, null);
+    
+        setProperty("rowIndex", function() {
+            return reference.target.@CellReference::getRowIndex()();
+        }, null);
+    
+        setProperty("columnIndex", function() {
+            return reference.target.@CellReference::getColumnIndex()();
+        }, null);
+    
+        setProperty("colSpan", function() {
+            return reference.target.@RendererCellReference::getColSpan()();
+        }, function(colSpan) {
+            reference.target.@RendererCellReference::setColSpan(*)(colSpan);
+        });
+    
+        return reference;
+    }-*/;
+
+    @Override
+    public JavaScriptExtensionState getState() {
+        return (JavaScriptExtensionState) super.getState();
+    }
+
+    private native void addGetRowKey(JavaScriptObject wrapper)
+    /*-{
+        var self = this;
+        wrapper.getRowKey = $entry(function(rowIndex) {
+            return @JavaScriptRendererConnector::findRowKey(*)(self, rowIndex);
+        });
+    }-*/;
+
+    private static String findRowKey(JavaScriptRendererConnector connector,
+            int rowIndex) {
+        GridConnector gc = connector.getGridConnector();
+        JsonObject row = gc.getWidget().getDataSource().getRow(rowIndex);
+        return connector.getRowKey(row);
+    }
+
+    private boolean hasFunction(String name) {
+        return hasFunction(helper.getConnectorWrapper(), name);
+    }
+
+    private static native boolean hasFunction(JavaScriptObject wrapper,
+            String name)
+    /*-{
+        return typeof wrapper[name] === 'function';
+    }-*/;
+
+    @Override
+    protected Renderer<Object> createRenderer() {
+        helper.ensureJavascriptInited();
+
+        if (!hasFunction("render")) {
+            throw new RuntimeException(
+                    "JavaScriptRenderer " + helper.getInitFunctionName()
+                            + " must have a function named 'render'");
+        }
+
+        final boolean hasInit = hasFunction("init");
+        final boolean hasDestroy = hasFunction("destroy");
+        final boolean hasOnActivate = hasFunction("onActivate");
+        final boolean hasGetConsumedEvents = hasFunction("getConsumedEvents");
+        final boolean hasOnBrowserEvent = hasFunction("onBrowserEvent");
+
+        return new ComplexRenderer<Object>() {
+            @Override
+            public void render(RendererCellReference cell, Object data) {
+                if (data instanceof JsonValue) {
+                    data = Util.json2jso((JsonValue) data);
+                }
+                render(helper.getConnectorWrapper(), getJsCell(cell), data);
+            }
+
+            private JavaScriptObject getJsCell(CellReference<?> cell) {
+                updateCellReference(cellReferenceWrapper, cell);
+                return cellReferenceWrapper;
+            }
+
+            public native void render(JavaScriptObject wrapper,
+                    JavaScriptObject cell, Object data)
+            /*-{
+                wrapper.render(cell, data);
+            }-*/;
+
+            @Override
+            public void init(RendererCellReference cell) {
+                if (hasInit) {
+                    init(helper.getConnectorWrapper(), getJsCell(cell));
+                }
+            }
+
+            private native void init(JavaScriptObject wrapper,
+                    JavaScriptObject cell)
+            /*-{
+                wrapper.init(cell);
+            }-*/;
+
+            private native void updateCellReference(
+                    JavaScriptObject cellWrapper, CellReference<?> target)
+            /*-{
+                cellWrapper.target = target;
+            }-*/;
+
+            @Override
+            public void destroy(RendererCellReference cell) {
+                if (hasDestroy) {
+                    destory(helper.getConnectorWrapper(), getJsCell(cell));
+                } else {
+                    super.destroy(cell);
+                }
+            }
+
+            private native void destory(JavaScriptObject wrapper,
+                    JavaScriptObject cell)
+            /*-{
+                wrapper.destory(cell);
+            }-*/;
+
+            @Override
+            public boolean onActivate(CellReference<?> cell) {
+                if (hasOnActivate) {
+                    return onActivate(helper.getConnectorWrapper(),
+                            getJsCell(cell));
+                } else {
+                    return super.onActivate(cell);
+                }
+            }
+
+            private native boolean onActivate(JavaScriptObject wrapper,
+                    JavaScriptObject cell)
+            /*-{
+                return !!wrapper.onActivate(cell);
+            }-*/;
+
+            @Override
+            public Collection<String> getConsumedEvents() {
+                if (hasGetConsumedEvents) {
+                    JsArrayString events = getConsumedEvents(
+                            helper.getConnectorWrapper());
+
+                    ArrayList<String> list = new ArrayList<>(events.length());
+                    for (int i = 0; i < events.length(); i++) {
+                        list.add(events.get(i));
+                    }
+                    return list;
+                } else {
+                    return super.getConsumedEvents();
+                }
+            }
+
+            private native JsArrayString getConsumedEvents(
+                    JavaScriptObject wrapper)
+            /*-{
+                var rawEvents = wrapper.getConsumedEvents();
+                var events = [];
+                for(var i = 0; i < rawEvents.length; i++) {
+                  events[i] = ""+rawEvents[i];
+                }
+                return events;
+            }-*/;
+
+            @Override
+            public boolean onBrowserEvent(CellReference<?> cell,
+                    NativeEvent event) {
+                if (hasOnBrowserEvent) {
+                    return onBrowserEvent(helper.getConnectorWrapper(),
+                            getJsCell(cell), event);
+                } else {
+                    return super.onBrowserEvent(cell, event);
+                }
+            }
+
+            private native boolean onBrowserEvent(JavaScriptObject wrapper,
+                    JavaScriptObject cell, NativeEvent event)
+            /*-{
+                return !!wrapper.onBrowserEvent(cell, event);
+            }-*/;
+        };
+    }
+
+    @Override
+    public Object decode(JsonValue value) {
+        // Let the js logic decode the raw json that the server sent
+        return value;
+    }
+
+    @Override
+    public void onUnregister() {
+        super.onUnregister();
+        helper.onUnregister();
+    }
+
+    @Override
+    public JavaScriptConnectorHelper getJavascriptConnectorHelper() {
+        return helper;
+    }
+}
index e448c5f2fe863492ba5e52fe4fc2c8a876245420..38504ff86775cb12c93671c90277cc74e41157d9 100644 (file)
@@ -68,11 +68,20 @@ public abstract class AbstractGridRendererConnector<T>
      * @return the column id for the given column
      */
     protected String getColumnId(Column<?, JsonObject> column) {
+        return getGridConnector().getColumnId(column);
+    }
+
+    /**
+     * Gets the grid connector for this renderer connector.
+     * 
+     * @return the parent grid connector.
+     */
+    protected GridConnector getGridConnector() {
         final ServerConnector parent = getParent();
         if (parent instanceof ColumnConnector) {
             final ServerConnector parentGrid = parent.getParent();
             if (parentGrid instanceof GridConnector) {
-                return ((GridConnector) parentGrid).getColumnId(column);
+                return (GridConnector) parentGrid;
             }
         }
         throw new IllegalStateException(
diff --git a/server/src/main/java/com/vaadin/ui/renderers/AbstractJavaScriptRenderer.java b/server/src/main/java/com/vaadin/ui/renderers/AbstractJavaScriptRenderer.java
new file mode 100644 (file)
index 0000000..5663569
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.ui.renderers;
+
+import com.vaadin.server.AbstractJavaScriptExtension;
+import com.vaadin.server.JavaScriptCallbackHelper;
+import com.vaadin.server.JsonCodec;
+import com.vaadin.shared.JavaScriptExtensionState;
+import com.vaadin.shared.communication.ServerRpc;
+import com.vaadin.ui.JavaScriptFunction;
+
+import elemental.json.Json;
+import elemental.json.JsonValue;
+
+/**
+ * Base class for Renderers with all client-side logic implemented using
+ * JavaScript.
+ * <p>
+ * When a new JavaScript renderer is initialized in the browser, the framework
+ * will look for a globally defined JavaScript function that will initialize the
+ * renderer. The name of the initialization function is formed by replacing .
+ * with _ in the name of the server-side class. If no such function is defined,
+ * each super class is used in turn until a match is found. The framework will
+ * thus first attempt with <code>com_example_MyRenderer</code> for the
+ * server-side
+ * <code>com.example.MyRenderer extends AbstractJavaScriptRenderer</code> class.
+ * If MyRenderer instead extends <code>com.example.SuperRenderer</code> , then
+ * <code>com_example_SuperRenderer</code> will also be attempted if
+ * <code>com_example_MyRenderer</code> has not been defined.
+ * <p>
+ *
+ * In addition to the general JavaScript extension functionality explained in
+ * {@link AbstractJavaScriptExtension}, this class also provides some
+ * functionality specific for renderers.
+ * <p>
+ * The initialization function will be called with <code>this</code> pointing to
+ * a connector wrapper object providing integration to Vaadin. Please note that
+ * in JavaScript, <code>this</code> is not necessarily defined inside callback
+ * functions and it might therefore be necessary to assign the reference to a
+ * separate variable, e.g. <code>var self = this;</code>. In addition to the
+ * extension functions described for {@link AbstractJavaScriptExtension}, the
+ * connector wrapper object also provides this function:
+ * <ul>
+ * <li><code>getRowKey(rowIndex)</code> - Gets a unique identifier for the row
+ * at the given index. This identifier can be used on the server to retrieve the
+ * corresponding ItemId using {@link #getItemId(String)}.</li>
+ * </ul>
+ * The connector wrapper also supports these special functions that can be
+ * implemented by the connector:
+ * <ul>
+ * <li><code>render(cell, data)</code> - Callback for rendering the given data
+ * into the given cell. The structure of cell and data are described in separate
+ * sections below. The renderer is required to implement this function.
+ * Corresponds to
+ * {@link com.vaadin.client.renderers.Renderer#render(com.vaadin.client.widget.grid.RendererCellReference, Object)}
+ * .</li>
+ * <li><code>init(cell)</code> - Prepares a cell for rendering. Corresponds to
+ * {@link com.vaadin.client.renderers.ComplexRenderer#init(com.vaadin.client.widget.grid.RendererCellReference)}
+ * .</li>
+ * <li><code>destory(cell)</code> - Allows the renderer to release resources
+ * allocate for a cell that will no longer be used. Corresponds to
+ * {@link com.vaadin.client.renderers.ComplexRenderer#destroy(com.vaadin.client.widget.grid.RendererCellReference)}
+ * .</li>
+ * <li><code>onActivate(cell)</code> - Called when the cell is activated by the
+ * user e.g. by double clicking on the cell or pressing enter with the cell
+ * focused. Corresponds to
+ * {@link com.vaadin.client.renderers.ComplexRenderer#onActivate(com.vaadin.client.widget.grid.CellReference)}
+ * .</li>
+ * <li><code>getConsumedEvents()</code> - Returns a JavaScript array of event
+ * names that should cause onBrowserEvent to be invoked whenever an event is
+ * fired for a cell managed by this renderer. Corresponds to
+ * {@link com.vaadin.client.renderers.ComplexRenderer#getConsumedEvents()}.</li>
+ * <li><code>onBrowserEvent(cell, event)</code> - Called by Grid when an event
+ * of a type returned by getConsumedEvents is fired for a cell managed by this
+ * renderer. Corresponds to
+ * {@link com.vaadin.client.renderers.ComplexRenderer#onBrowserEvent(com.vaadin.client.widget.grid.CellReference, com.google.gwt.dom.client.NativeEvent)}
+ * .</li>
+ * </ul>
+ *
+ * <p>
+ * The cell object passed to functions defined by the renderer has these
+ * properties:
+ * <ul>
+ * <li><code>element</code> - The DOM element corresponding to this cell.
+ * Readonly.</li>
+ * <li><code>rowIndex</code> - The current index of the row of this cell.
+ * Readonly.</li>
+ * <li><code>columnIndex</code> - The current index of the column of this cell.
+ * Readonly.</li>
+ * <li><code>colSpan</code> - The number of columns spanned by this cell. Only
+ * supported in the object passed to the <code>render</code> function - other
+ * functions should not use the property. Readable and writable.
+ * </ul>
+ * 
+ * @param <T>
+ *            the grid type this renderer can be attached to
+ * @param <V>
+ *            the type this renderer knows how to present
+ *
+ * @author Vaadin Ltd
+ * @since 8.0
+ */
+public abstract class AbstractJavaScriptRenderer<T, V>
+        extends AbstractRenderer<T, V> {
+    private JavaScriptCallbackHelper callbackHelper = new JavaScriptCallbackHelper(
+            this);
+
+    protected AbstractJavaScriptRenderer(Class<V> presentationType,
+            String nullRepresentation) {
+        super(presentationType, nullRepresentation);
+    }
+
+    protected AbstractJavaScriptRenderer(Class<V> presentationType) {
+        super(presentationType, null);
+    }
+
+    @Override
+    protected <R extends ServerRpc> void registerRpc(R implementation,
+            Class<R> rpcInterfaceType) {
+        super.registerRpc(implementation, rpcInterfaceType);
+        callbackHelper.registerRpc(rpcInterfaceType);
+    }
+
+    /**
+     * Register a {@link JavaScriptFunction} that can be called from the
+     * JavaScript using the provided name. A JavaScript function with the
+     * provided name will be added to the connector wrapper object (initially
+     * available as <code>this</code>). Calling that JavaScript function will
+     * cause the call method in the registered {@link JavaScriptFunction} to be
+     * invoked with the same arguments.
+     *
+     * @param functionName
+     *            the name that should be used for client-side callback
+     * @param function
+     *            the {@link JavaScriptFunction} object that will be invoked
+     *            when the JavaScript function is called
+     */
+    protected void addFunction(String functionName,
+            JavaScriptFunction function) {
+        callbackHelper.registerCallback(functionName, function);
+    }
+
+    /**
+     * Invoke a named function that the connector JavaScript has added to the
+     * JavaScript connector wrapper object. The arguments can be any boxed
+     * primitive type, String, {@link JsonValue} or arrays of any other
+     * supported type. Complex types (e.g. List, Set, Map, Connector or any
+     * JavaBean type) must be explicitly serialized to a {@link JsonValue}
+     * before sending. This can be done either with
+     * {@link JsonCodec#encode(Object, JsonValue, java.lang.reflect.Type, com.vaadin.ui.ConnectorTracker)}
+     * or using the factory methods in {@link Json}.
+     *
+     * @param name
+     *            the name of the function
+     * @param arguments
+     *            function arguments
+     */
+    protected void callFunction(String name, Object... arguments) {
+        callbackHelper.invokeCallback(name, arguments);
+    }
+
+    @Override
+    protected JavaScriptExtensionState getState() {
+        return (JavaScriptExtensionState) super.getState();
+    }
+}
diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/JavaScriptRenderers.java b/uitest/src/main/java/com/vaadin/tests/components/grid/JavaScriptRenderers.java
new file mode 100644 (file)
index 0000000..934ae13
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Grid;
+
+public class JavaScriptRenderers extends AbstractTestUI {
+
+    public static class ItemBean {
+        private Integer id;
+        private String string;
+        private MyBean bean;
+
+        public Integer getId() {
+            return id;
+        }
+
+        public void setId(Integer id) {
+            this.id = id;
+        }
+
+        public String getString() {
+            return string;
+        }
+
+        public void setString(String string) {
+            this.string = string;
+        }
+
+        public MyBean getBean() {
+            return bean;
+        }
+
+        public void setBean(MyBean bean) {
+            this.bean = bean;
+        }
+    }
+
+    public static class MyBean {
+        private int integer;
+        private String string;
+
+        public MyBean(int integer, String string) {
+            super();
+            this.integer = integer;
+            this.string = string;
+        }
+
+        public int getInteger() {
+            return integer;
+        }
+
+        public void setInteger(int integer) {
+            this.integer = integer;
+        }
+
+        public String getString() {
+            return string;
+        }
+
+        public void setString(String string) {
+            this.string = string;
+        }
+    }
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        List<ItemBean> items = new ArrayList<>(1000);
+        for (int i = 0; i < 1000; i++) {
+            ItemBean bean = new ItemBean();
+            bean.setId(i);
+            bean.setString("string" + i);
+            bean.setBean(new MyBean(i + 1, Integer.toString(i - 1)));
+            items.add(bean);
+        }
+
+        Grid<ItemBean> grid = new Grid<>();
+
+        grid.addColumn("id", item -> item.getId().toString());
+        grid.addColumn("bean", ItemBean::getBean, new MyBeanJSRenderer());
+        grid.addColumn("string", ItemBean::getString,
+                new JavaScriptStringRenderer());
+
+        grid.setItems(items);
+
+        addComponent(grid);
+    }
+
+}
diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/JavaScriptStringRenderer.java b/uitest/src/main/java/com/vaadin/tests/components/grid/JavaScriptStringRenderer.java
new file mode 100644 (file)
index 0000000..48cfd59
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.annotations.JavaScript;
+import com.vaadin.tests.components.grid.JavaScriptRenderers.ItemBean;
+import com.vaadin.ui.renderers.AbstractJavaScriptRenderer;
+
+@JavaScript("JavaScriptStringRenderer.js")
+public class JavaScriptStringRenderer
+        extends AbstractJavaScriptRenderer<ItemBean, String> {
+
+    protected JavaScriptStringRenderer() {
+        super(String.class);
+    }
+
+}
diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/MyBeanJSRenderer.java b/uitest/src/main/java/com/vaadin/tests/components/grid/MyBeanJSRenderer.java
new file mode 100644 (file)
index 0000000..d5ccc65
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.annotations.JavaScript;
+import com.vaadin.tests.components.grid.JavaScriptRenderers.ItemBean;
+import com.vaadin.tests.components.grid.JavaScriptRenderers.MyBean;
+import com.vaadin.ui.renderers.AbstractJavaScriptRenderer;
+
+/**
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+@JavaScript("myBeanJsRenderer.js")
+public class MyBeanJSRenderer
+        extends AbstractJavaScriptRenderer<ItemBean, MyBean> {
+
+    public MyBeanJSRenderer() {
+        super(MyBean.class, "");
+    }
+
+}
index 5e7bde5ec72040a9389ca58cafa7d1cd423afb3d..9beeabb6770132eeaed3854057ec53c362da26d5 100644 (file)
@@ -4,13 +4,16 @@ window.com_vaadin_tests_components_grid_MyBeanJSRenderer = function() {
        }
        
        this.render = function(cell, data) {
-               cell.element.innerHTML = 'Bean(' + data.integer + ', ' + data.string + ')'
+               if (!cell.renderedText) {
+                       cell.element.innerHTML = 'Bean(' + data.integer + ', ' + data.string + ')';
+               }
        }
        
        this.getConsumedEvents = function() { return ["click"] };
        
        this.onBrowserEvent = function(cell, event) {
-               cell.element.innerHTML =  "Clicked " + cell.rowIndex + " with key " + this.getRowKey(cell.rowIndex) +" at " + event.clientX;
+               cell.renderedText ="Clicked " + cell.rowIndex + " with key " + this.getRowKey(cell.rowIndex) +" at " + event.clientX;
+               cell.element.innerHTML=cell.renderedText;
                return true;
        }
 }
\ No newline at end of file
diff --git a/uitest/src/main/resources/com/vaadin/v7/tests/components/grid/JavaScriptStringRenderer.js b/uitest/src/main/resources/com/vaadin/v7/tests/components/grid/JavaScriptStringRenderer.js
new file mode 100644 (file)
index 0000000..14266d3
--- /dev/null
@@ -0,0 +1,5 @@
+com_vaadin_v7_tests_components_grid_JavaScriptStringRenderer = function() {
+       this.render = function(cell, data) {
+               cell.element.textContent = data;
+       }
+}
\ No newline at end of file
diff --git a/uitest/src/main/resources/com/vaadin/v7/tests/components/grid/myBeanJsRenderer.js b/uitest/src/main/resources/com/vaadin/v7/tests/components/grid/myBeanJsRenderer.js
new file mode 100644 (file)
index 0000000..45aff71
--- /dev/null
@@ -0,0 +1,16 @@
+window.com_vaadin_v7_tests_components_grid_MyBeanJSRenderer = function() {
+       this.init = function(cell) {
+               cell.element.setAttribute("column", cell.columnIndex);
+       }
+       
+       this.render = function(cell, data) {
+               cell.element.innerHTML = 'Bean(' + data.integer + ', ' + data.string + ')'
+       }
+       
+       this.getConsumedEvents = function() { return ["click"] };
+       
+       this.onBrowserEvent = function(cell, event) {
+               cell.element.innerHTML =  "Clicked " + cell.rowIndex + " with key " + this.getRowKey(cell.rowIndex) +" at " + event.clientX;
+               return true;
+       }
+}
\ No newline at end of file
diff --git a/uitest/src/test/java/com/vaadin/tests/components/grid/JavaScriptRenderersTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/JavaScriptRenderersTest.java
new file mode 100644 (file)
index 0000000..ca5ded7
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.customelements.GridElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.testbench.parallel.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class JavaScriptRenderersTest extends MultiBrowserTest {
+
+    @Test
+    public void testJavaScriptRenderer() {
+        setDebug(true);
+        openTestURL();
+
+        GridElement grid = $(GridElement.class).first();
+        GridCellElement cell_1_1 = grid.getCell(1, 1);
+
+        GridCellElement cell_2_2 = grid.getCell(2, 2);
+
+        // Verify render functionality
+        Assert.assertEquals("Bean(2, 0)", cell_1_1.getText());
+
+        Assert.assertEquals("string2", cell_2_2.getText());
+
+        // Verify init functionality
+        Assert.assertEquals("1", cell_1_1.getAttribute("column"));
+
+        // Verify onbrowserevent
+        cell_1_1.click();
+        Assert.assertTrue(
+                cell_1_1.getText().startsWith("Clicked 1 with key 2 at"));
+    }
+}