diff options
9 files changed, 185 insertions, 28 deletions
diff --git a/client/src/main/java/com/vaadin/client/ConnectorMap.java b/client/src/main/java/com/vaadin/client/ConnectorMap.java index d0dc4d9ab5..f79aa0250f 100644 --- a/client/src/main/java/com/vaadin/client/ConnectorMap.java +++ b/client/src/main/java/com/vaadin/client/ConnectorMap.java @@ -126,21 +126,9 @@ public class ConnectorMap { ComponentDetail componentDetail = GWT.create(ComponentDetail.class); idToComponentDetail.put(id, componentDetail); componentDetail.setConnector(connector); - if (connector instanceof ComponentConnector) { - ComponentConnector pw = (ComponentConnector) connector; - Widget widget = pw.getWidget(); - Profiler.enter("ConnectorMap.setConnectorId"); - setConnectorId(widget.getElement(), id); - Profiler.leave("ConnectorMap.setConnectorId"); - } Profiler.leave("ConnectorMap.registerConnector"); } - private static native void setConnectorId(Element el, String id) - /*-{ - el.tkPid = id; - }-*/; - /** * Gets the connector id using a DOM element - the element should be the * root element for a connector, otherwise no id will be found. Use diff --git a/client/src/main/java/com/vaadin/client/JavaScriptConnectorHelper.java b/client/src/main/java/com/vaadin/client/JavaScriptConnectorHelper.java index b9f4ae8962..1d4939f40d 100644 --- a/client/src/main/java/com/vaadin/client/JavaScriptConnectorHelper.java +++ b/client/src/main/java/com/vaadin/client/JavaScriptConnectorHelper.java @@ -53,6 +53,7 @@ public class JavaScriptConnectorHelper { private int tag; private String initFunctionName; + private String tagName; public JavaScriptConnectorHelper(ServerConnector connector) { this.connector = connector; @@ -153,14 +154,8 @@ public class JavaScriptConnectorHelper { } protected boolean initJavaScript() { - ApplicationConfiguration conf = connector.getConnection() - .getConfiguration(); - ArrayList<String> attemptedNames = new ArrayList<>(); - Integer tag = Integer.valueOf(this.tag); - while (tag != null) { - String serverSideClassName = conf.getServerSideClassNameForTag(tag); - String initFunctionName = serverSideClassName.replaceAll("\\.", - "_"); + ArrayList<String> initFunctionNames = getPotentialInitFunctionNames(); + for (String initFunctionName : initFunctionNames) { if (tryInitJs(initFunctionName, getConnectorWrapper())) { getLogger().info("JavaScript connector initialized using " + initFunctionName); @@ -169,12 +164,10 @@ public class JavaScriptConnectorHelper { } else { getLogger().warning("No JavaScript function " + initFunctionName + " found"); - attemptedNames.add(initFunctionName); - tag = conf.getParentTag(tag.intValue()); } } getLogger().info("No JavaScript init for connector found"); - showInitProblem(attemptedNames); + showInitProblem(initFunctionNames); return false; } @@ -408,7 +401,7 @@ public class JavaScriptConnectorHelper { delete state[key]; } } - + for(var key in input) { if (input.hasOwnProperty(key)) { state[key] = input[key]; @@ -505,6 +498,44 @@ public class JavaScriptConnectorHelper { return initFunctionName; } + private ArrayList<String> getPotentialInitFunctionNames() { + ApplicationConfiguration conf = connector.getConnection() + .getConfiguration(); + ArrayList<String> initFunctionNames = new ArrayList<String>(); + Integer tag = Integer.valueOf(this.tag); + while (tag != null) { + String initFunctionName = conf.getServerSideClassNameForTag(tag); + initFunctionName = initFunctionName.replaceAll("\\.", "_"); + initFunctionNames.add(initFunctionName); + tag = conf.getParentTag(tag); + } + return initFunctionNames; + } + + public String getTagName() { + if (tagName != null) { + return tagName; + } + for (String initFunctionName : getPotentialInitFunctionNames()) { + tagName = getTagJs(initFunctionName); + if (tagName != null) { + return tagName; + } + } + // No tagName found, use default + tagName = "div"; + return tagName; + } + + private static native String getTagJs(String initFunctionName) + /*-{ + if ($wnd[initFunctionName] && typeof $wnd[initFunctionName].tag == 'string') { + return $wnd[initFunctionName].tag; + } else { + return null; + } + }-*/; + private static Logger getLogger() { return Logger.getLogger(JavaScriptConnectorHelper.class.getName()); } diff --git a/client/src/main/java/com/vaadin/client/ui/AbstractConnector.java b/client/src/main/java/com/vaadin/client/ui/AbstractConnector.java index 552e4eb424..e078f3f126 100644 --- a/client/src/main/java/com/vaadin/client/ui/AbstractConnector.java +++ b/client/src/main/java/com/vaadin/client/ui/AbstractConnector.java @@ -23,10 +23,12 @@ import java.util.List; import java.util.Set; import com.google.gwt.core.client.JsArrayString; +import com.google.gwt.dom.client.Element; import com.google.gwt.event.shared.GwtEvent; import com.google.gwt.event.shared.HandlerManager; import com.google.gwt.event.shared.HandlerRegistration; import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.ComponentConnector; import com.vaadin.client.FastStringMap; import com.vaadin.client.FastStringSet; import com.vaadin.client.JsArrayObject; @@ -118,6 +120,15 @@ public abstract class AbstractConnector this.connection = connection; id = connectorId; + // Doing this here because we want to run it after connection and id has + // been set but before init() is called to enable e.g. + // JavaScriptConnector to use connection when determining the tag name + if (this instanceof ComponentConnector) { + setConnectorId( + ((ComponentConnector) this).getWidget().getElement(), + connectorId); + } + addStateChangeHandler(this); if (Profiler.isEnabled()) { Profiler.enter( @@ -131,6 +142,11 @@ public abstract class AbstractConnector Profiler.leave("AbstractConnector.doInit"); } + private static native void setConnectorId(Element el, String id) + /*-{ + el.tkPid = id; + }-*/; + /** * Called when the connector has been initialized. Override this method to * perform initialization of the connector. diff --git a/client/src/main/java/com/vaadin/client/ui/JavaScriptComponentConnector.java b/client/src/main/java/com/vaadin/client/ui/JavaScriptComponentConnector.java index 28f05fa7ca..a2daef273c 100644 --- a/client/src/main/java/com/vaadin/client/ui/JavaScriptComponentConnector.java +++ b/client/src/main/java/com/vaadin/client/ui/JavaScriptComponentConnector.java @@ -15,6 +15,7 @@ */ package com.vaadin.client.ui; +import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.JavaScriptConnectorHelper; import com.vaadin.client.communication.HasJavaScriptConnectorHelper; import com.vaadin.shared.ui.Connect; @@ -35,6 +36,11 @@ public final class JavaScriptComponentConnector extends }; @Override + protected Widget createWidget() { + return new JavaScriptWidget(helper.getTagName()); + } + + @Override public JavaScriptWidget getWidget() { return (JavaScriptWidget) super.getWidget(); } diff --git a/client/src/main/java/com/vaadin/client/ui/JavaScriptWidget.java b/client/src/main/java/com/vaadin/client/ui/JavaScriptWidget.java index f5b5ca9c68..002827ed40 100644 --- a/client/src/main/java/com/vaadin/client/ui/JavaScriptWidget.java +++ b/client/src/main/java/com/vaadin/client/ui/JavaScriptWidget.java @@ -21,8 +21,22 @@ import com.google.gwt.dom.client.Document; import com.google.gwt.user.client.ui.Widget; public class JavaScriptWidget extends Widget { + + /** + * Creats a JavaScriptWidget based on a <div> element + */ public JavaScriptWidget() { - setElement(Document.get().createDivElement()); + this("div"); + } + + /** + * Creates a JavaScriptWidget based on an element with the given tag + * + * @param tagName + * the tag to use for the element + */ + public JavaScriptWidget(String tagName) { + setElement(Document.get().createElement(tagName)); } public void showNoInitFound(ArrayList<String> attemptedNames) { diff --git a/server/src/main/java/com/vaadin/ui/AbstractJavaScriptComponent.java b/server/src/main/java/com/vaadin/ui/AbstractJavaScriptComponent.java index f643615b81..211d7aed27 100644 --- a/server/src/main/java/com/vaadin/ui/AbstractJavaScriptComponent.java +++ b/server/src/main/java/com/vaadin/ui/AbstractJavaScriptComponent.java @@ -40,9 +40,28 @@ import elemental.json.JsonValue; * <code>com_example_MyComponent</code> has not been defined. * <p> * JavaScript components have a very simple GWT widget ( - * {@link com.vaadin.client.ui.JavaScriptWidget} ) just consisting of a - * <code>div</code> element to which the JavaScript code should initialize its - * own user interface. + * {@link com.vaadin.client.ui.JavaScriptWidget} ) just consisting of a single + * element (a <code>div</code> by default) to which the JavaScript code should + * initialize its own user interface. The tag can be overridden by defining a + * string named <code>com_example_MyComponent.tag</code>. If no tag has been + * defined, a tag defined in a super class will be located in the same manner as + * with the init function. + * <p> + * For example, to create a component ({@code my.package.Span}) with the DOM + * {@code <span>some text</span>}, taking the {@code span} text from the state, + * the JavaScript would be: + * + * <pre> + * <code> +my_package_Span = function() { + this.onStateChange = function() { + this.getElement().innerText = this.getState().text; + } +} +my_package_Span.tag = "span"; +</code> + * </pre> + * * <p> * The initialization function will be called with <code>this</code> pointing to * a connector wrapper object providing integration to Vaadin. Please note that diff --git a/uitest/src/main/java/com/vaadin/tests/components/javascriptcomponent/JavaScriptSpan.java b/uitest/src/main/java/com/vaadin/tests/components/javascriptcomponent/JavaScriptSpan.java new file mode 100644 index 0000000000..7c1a79471b --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/components/javascriptcomponent/JavaScriptSpan.java @@ -0,0 +1,46 @@ +/* + * Copyright 2000-2014 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.javascriptcomponent; + +import com.vaadin.annotations.JavaScript; +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.JavaScriptComponentState; +import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.ui.AbstractJavaScriptComponent; + +public class JavaScriptSpan extends AbstractTestUIWithLog { + + @Override + protected void setup(VaadinRequest request) { + addComponent(new Span("Hello World")); + } + + @JavaScript("JavaScriptSpanComponent.js") + public static class Span extends AbstractJavaScriptComponent { + public Span(String text) { + this.getState().text = text; + } + + @Override + protected SpanState getState() { + return (SpanState) super.getState(); + } + } + + public static class SpanState extends JavaScriptComponentState { + public String text; + } +} diff --git a/uitest/src/main/resources/com/vaadin/tests/components/javascriptcomponent/JavaScriptSpanComponent.js b/uitest/src/main/resources/com/vaadin/tests/components/javascriptcomponent/JavaScriptSpanComponent.js new file mode 100644 index 0000000000..c217a10ed6 --- /dev/null +++ b/uitest/src/main/resources/com/vaadin/tests/components/javascriptcomponent/JavaScriptSpanComponent.js @@ -0,0 +1,6 @@ +com_vaadin_tests_components_javascriptcomponent_JavaScriptSpan_Span = function() { + this.onStateChange = function() { + this.getElement().innerText = this.getState().text; + } +} +com_vaadin_tests_components_javascriptcomponent_JavaScriptSpan_Span.tag = "span"; diff --git a/uitest/src/test/java/com/vaadin/tests/components/javascriptcomponent/JavaScriptSpanTest.java b/uitest/src/test/java/com/vaadin/tests/components/javascriptcomponent/JavaScriptSpanTest.java new file mode 100644 index 0000000000..353a5e89f4 --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/components/javascriptcomponent/JavaScriptSpanTest.java @@ -0,0 +1,31 @@ +/* + * Copyright 2000-2014 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.javascriptcomponent; + +import org.junit.Test; +import org.openqa.selenium.By; + +import com.vaadin.tests.tb3.SingleBrowserTest; + +public class JavaScriptSpanTest extends SingleBrowserTest { + @Test + public void componentShownAsSpan() { + openTestURL(); + + assertElementPresent(By.xpath("//span[text()='Hello World']")); + + } +} |