Fixes #7005tags/8.0.0.beta2
@@ -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 |
@@ -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()); | |||
} |
@@ -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. |
@@ -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; | |||
@@ -34,6 +35,11 @@ public final class JavaScriptComponentConnector extends | |||
} | |||
}; | |||
@Override | |||
protected Widget createWidget() { | |||
return new JavaScriptWidget(helper.getTagName()); | |||
} | |||
@Override | |||
public JavaScriptWidget getWidget() { | |||
return (JavaScriptWidget) super.getWidget(); |
@@ -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) { |
@@ -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 |
@@ -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; | |||
} | |||
} |
@@ -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"; |
@@ -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']")); | |||
} | |||
} |