summaryrefslogtreecommitdiffstats
path: root/documentation/gwt/gwt-javascript.asciidoc
diff options
context:
space:
mode:
Diffstat (limited to 'documentation/gwt/gwt-javascript.asciidoc')
-rw-r--r--documentation/gwt/gwt-javascript.asciidoc299
1 files changed, 299 insertions, 0 deletions
diff --git a/documentation/gwt/gwt-javascript.asciidoc b/documentation/gwt/gwt-javascript.asciidoc
new file mode 100644
index 0000000000..517740b33a
--- /dev/null
+++ b/documentation/gwt/gwt-javascript.asciidoc
@@ -0,0 +1,299 @@
+---
+title: Integrating JavaScript Components and Extensions
+order: 13
+layout: page
+---
+
+[[gwt.javascript]]
+= Integrating JavaScript Components and Extensions
+
+((("JavaScript integration", id="term.gwt.javascript", range="startofrange")))
+
+
+Vaadin allows simplified integration of pure JavaScript components, as well as
+component and UI extensions. The JavaScript connector code is published from the
+server-side. As the JavaScript integration does not involve GWT programming, no
+widget set compilation is needed.
+
+[[gwt.javascript.example]]
+== Example JavaScript Library
+
+There are many kinds of component libraries for JavaScript. In the following, we
+present a simple library that provides one object-oriented JavaScript component.
+We use this example later to show how to integrate it with a server-side Vaadin
+component.
+
+The example library includes a single [classname]#MyComponent# component,
+defined in [filename]#mylibrary.js#.
+
+
+----
+// Define the namespace
+var mylibrary = mylibrary || {};
+
+mylibrary.MyComponent = function (element) {
+ element.innerHTML =
+ "<div class='caption'>Hello, world!</div>" +
+ "<div class='textinput'>Enter a value: " +
+ "<input type='text' name='value'/>" +
+ "<input type='button' value='Click'/>" +
+ "</div>";
+
+ // Style it
+ element.style.border = "thin solid red";
+ element.style.display = "inline-block";
+
+ // Getter and setter for the value property
+ this.getValue = function () {
+ return element.
+ getElementsByTagName("input")[0].value;
+ };
+ this.setValue = function (value) {
+ element.getElementsByTagName("input")[0].value =
+ value;
+ };
+
+ // Default implementation of the click handler
+ this.click = function () {
+ alert("Error: Must implement click() method");
+ };
+
+ // Set up button click
+ var button = element.getElementsByTagName("input")[1];
+ var self = this; // Can't use this inside the function
+ button.onclick = function () {
+ self.click();
+ };
+};
+----
+
+When used in an HTML page, the library would be included with the following
+definition:
+
+
+----
+<script type="text/javascript"
+ src="mylibrary.js"></script>
+----
+
+You could then use it anywhere in the HTML document as follows:
+
+
+----
+<!-- Placeholder for the component -->
+<div id="foo"></div>
+
+<!-- Create the component and bind it to the placeholder -->
+<script type="text/javascript">
+ window.foo = new mylibrary.MyComponent(
+ document.getElementById("foo"));
+ window.foo.click = function () {
+ alert("Value is " + this.getValue());
+ }
+</script>
+----
+
+[[figure.gwt.javascript.example]]
+.A JavaScript Component Example
+image::img/javascript-component.png[]
+
+You could interact with the component with JavaScript for example as follows:
+
+
+----
+<a href="javascript:foo.setValue('New value')">Click here</a>
+----
+
+
+[[gwt.javascript.server-side]]
+== A Server-Side API for a JavaScript Component
+
+To begin integrating such a JavaScript component, you would need to sketch a bit
+how it would be used from a server-side Vaadin application. The component should
+support writing the value as well as listening for changes to it.
+
+
+----
+final MyComponent mycomponent = new MyComponent();
+
+// Set the value from server-side
+mycomponent.setValue("Server-side value");
+
+// Process a value input by the user from the client-side
+mycomponent.addValueChangeListener(
+ new MyComponent.ValueChangeListener() {
+ @Override
+ public void valueChange() {
+ Notification.show("Value: " + mycomponent.getValue());
+ }
+});
+
+layout.addComponent(mycomponent);
+----
+
+[[gwt.javascript.server-side.component]]
+=== Basic Server-Side Component
+
+A JavaScript component extends the [classname]#AbstractJavaScriptComponent#,
+which handles the shared state and RPC for the component.
+
+
+----
+package com.vaadin.book.examples.client.js;
+
+@JavaScript({"mylibrary.js", "mycomponent-connector.js"})
+public class MyComponent extends AbstractJavaScriptComponent {
+ public interface ValueChangeListener extends Serializable {
+ void valueChange();
+ }
+ ArrayList<ValueChangeListener> listeners =
+ new ArrayList<ValueChangeListener>();
+ public void addValueChangeListener(
+ ValueChangeListener listener) {
+ listeners.add(listener);
+ }
+
+ public void setValue(String value) {
+ getState().value = value;
+ }
+
+ public String getValue() {
+ return getState().value;
+ }
+
+ @Override
+ protected MyComponentState getState() {
+ return (MyComponentState) super.getState();
+ }
+}
+----
+
+Notice later when creating the JavaScript connector that its name must match the
+package name of this server-side class.
+
+The shared state of the component is as follows:
+
+
+----
+public class MyComponentState extends JavaScriptComponentState {
+ public String value;
+}
+----
+
+If the member variables are private, you need to have public setters and getters
+for them, which you can use in the component.
+
+
+
+[[gwt.javascript.connector]]
+== Defining a JavaScript Connector
+
+A JavaScript connector is a function that initializes the JavaScript component
+and handles communication between the server-side and the JavaScript code.//TOD
+Clarify -
+code?
+
+A connector is defined as a connector initializer function that is added to the
+[literal]#++window++# object. The name of the function must match the
+server-side class name, with the full package path. Instead of the Java dot
+notation for the package name, underscores need to be used as separators.
+
+The Vaadin client-side framework adds a number of methods to the connector
+function. The [methodname]#this.getElement()# method returns the HTML DOM
+element of the component. The [methodname]#this.getState()# returns a shared
+state object with the current state as synchronized from the server-side.
+
+
+----
+window.com_vaadin_book_examples_client_js_MyComponent =
+function() {
+ // Create the component
+ var mycomponent =
+ new mylibrary.MyComponent(this.getElement());
+
+ // Handle changes from the server-side
+ this.onStateChange = function() {
+ mycomponent.setValue(this.getState().value);
+ };
+
+ // Pass user interaction to the server-side
+ var self = this;
+ mycomponent.click = function() {
+ self.onClick(mycomponent.getValue());
+ };
+};
+----
+
+In the above example, we pass user interaction using the JavaScript RPC
+mechanism, as described in the next section.
+
+
+[[gwt.javascript.rpc]]
+== RPC from JavaScript to Server-Side
+
+User interaction with the JavaScript component has to be passed to the
+server-side using an RPC (Remote Procedure Call) mechanism. The JavaScript RPC
+mechanism is almost equal to regular client-side widgets, as described in
+<<dummy/../../../framework/gwt/gwt-rpc#gwt.rpc,"RPC Calls Between Client- and
+Server-Side">>.
+
+[[gwt.javascript.rpc.handling]]
+=== Handling RPC Calls on the Server-Side
+
+Let us begin with the RPC function registration on the server-side. RPC calls
+are handled on the server-side in function handlers that implement the
+[interfacename]#JavaScriptFunction# interface. A server-side function handler is
+registered with the [methodname]#addFunction()# method in
+[classname]#AbstractJavaScriptComponent#. The server-side registration actually
+defines a JavaScript method that is available in the client-side connector
+object.
+
+Continuing from the server-side [classname]#MyComponent# example we defined
+earlier, we add a constructor to it that registers the function.
+
+
+----
+public MyComponent() {
+ addFunction("onClick", new JavaScriptFunction() {
+ @Override
+ public void call(JsonArray arguments) {
+ getState().setValue(arguments.getString(0));
+ for (ValueChangeListener listener: listeners)
+ listener.valueChange();
+ }
+ });
+}
+----
+
+
+[[gwt.javascript.rpc.calling]]
+=== Making an RPC Call from JavaScript
+
+An RPC call is made simply by calling the RPC method in the connector. In the
+constructor function of the JavaScript connector, you could write as follows
+(the complete connector code was given earlier):
+
+
+----
+window.com_vaadin_book_examples_gwt_js_MyComponent =
+ function() {
+ ...
+ var connector = this;
+ mycomponent.click = function() {
+ connector.onClick(mycomponent.getValue());
+ };
+ };
+----
+
+Here, the [literal]#++mycomponent.click++# is a function in the example
+JavaScript library, as described in <<gwt.javascript.example>>. The
+[methodname]#onClick()# is the method we defined on the server-side. We pass a
+simple string parameter in the call.
+
+You can pass anything that is valid in JSON notation in the parameters.
+
+
+
+(((range="endofrange", startref="term.gwt.javascript")))
+
+