Parcourir la source

Support for defining the root element for Javascript components (#8143)

Fixes #7005
tags/8.0.0.beta2
Artur il y a 7 ans
Parent
révision
8fca887996

+ 0
- 12
client/src/main/java/com/vaadin/client/ConnectorMap.java Voir le fichier

@@ -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

+ 43
- 12
client/src/main/java/com/vaadin/client/JavaScriptConnectorHelper.java Voir le fichier

@@ -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());
}

+ 16
- 0
client/src/main/java/com/vaadin/client/ui/AbstractConnector.java Voir le fichier

@@ -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.

+ 6
- 0
client/src/main/java/com/vaadin/client/ui/JavaScriptComponentConnector.java Voir le fichier

@@ -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();

+ 15
- 1
client/src/main/java/com/vaadin/client/ui/JavaScriptWidget.java Voir le fichier

@@ -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 &lt;div&gt; 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) {

+ 22
- 3
server/src/main/java/com/vaadin/ui/AbstractJavaScriptComponent.java Voir le fichier

@@ -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

+ 46
- 0
uitest/src/main/java/com/vaadin/tests/components/javascriptcomponent/JavaScriptSpan.java Voir le fichier

@@ -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;
}
}

+ 6
- 0
uitest/src/main/resources/com/vaadin/tests/components/javascriptcomponent/JavaScriptSpanComponent.js Voir le fichier

@@ -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";

+ 31
- 0
uitest/src/test/java/com/vaadin/tests/components/javascriptcomponent/JavaScriptSpanTest.java Voir le fichier

@@ -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']"));

}
}

Chargement…
Annuler
Enregistrer