/* * Copyright 2000-2021 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; import com.vaadin.server.JavaScriptCallbackHelper; import com.vaadin.server.JsonCodec; import com.vaadin.shared.communication.ServerRpc; import com.vaadin.shared.ui.JavaScriptComponentState; import elemental.json.Json; import elemental.json.JsonValue; /** * Base class for Components with all client-side logic implemented using * JavaScript. *

* When a new JavaScript component is initialized in the browser, the framework * will look for a globally defined JavaScript function that will initialize the * component. 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 com_example_MyComponent for the * server-side * com.example.MyComponent extends AbstractJavaScriptComponent * class. If MyComponent instead extends com.example.SuperComponent * , then com_example_SuperComponent will also be attempted if * com_example_MyComponent has not been defined. *

* JavaScript components have a very simple GWT widget ( * {@link com.vaadin.client.ui.JavaScriptWidget} ) just consisting of a single * element (a div by default) to which the JavaScript code should * initialize its own user interface. The tag can be overridden by defining a * string named com_example_MyComponent.tag. 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. *

* For example, to create a component ({@code my.package.Span}) with the DOM * {@code some text}, taking the {@code span} text from the state, * the JavaScript would be: * *

 * 
my_package_Span = function() {
  this.onStateChange = function() {
    this.getElement().innerText = this.getState().text;
  }
}
my_package_Span.tag = "span";

 * 
* *

* The initialization function will be called with this pointing to * a connector wrapper object providing integration to Vaadin. Please note that * in JavaScript, this is not necessarily defined inside callback * functions and it might therefore be necessary to assign the reference to a * separate variable, e.g. var self = this;. The following * functions are provided by the connector wrapper object: *

* The connector wrapper also supports these special functions: * *

* * Values in the Shared State and in RPC calls are converted between Java and * JavaScript using the following conventions: *

* * @author Vaadin Ltd * @since 7.0.0 */ public abstract class AbstractJavaScriptComponent extends AbstractComponent { private final JavaScriptCallbackHelper callbackHelper = new JavaScriptCallbackHelper( this); @Override protected void registerRpc(T implementation, Class 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 this). 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 function * @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 JavaScriptComponentState getState() { return (JavaScriptComponentState) super.getState(); } @Override protected JavaScriptComponentState getState(boolean markAsDirty) { return (JavaScriptComponentState) super.getState(markAsDirty); } }