You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

IntegratingAJavaScriptComponent.asciidoc 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. ---
  2. title: Integrating A JavaScript Component
  3. order: 38
  4. layout: page
  5. ---
  6. [[integrating-a-javascript-component]]
  7. Integrating a JavaScript component
  8. ----------------------------------
  9. You can use an existing JavaScript component as a component in Vaadin by
  10. creating a server-side API for the component as well as writing the
  11. JavaScript code that connects the server-side API to the actual
  12. JavaScript component. Because of the dynamic nature of JavaScript, you
  13. don't need to use GWT development mode or recompile the widgetset while
  14. making client-side changes.
  15. The server-side component should extend `AbstractJavaScriptComponent` and
  16. provide the API that the developer uses to interact with the component.
  17. The class should also have a `@JavaScript` annotation that defines the
  18. required JavaScript libraries in the order they should be loaded. This
  19. example uses the Flot graph library from http://code.google.com/p/flot/.
  20. Float requires jQuery which is loaded using
  21. https://developers.google.com/speed/libraries/[Google Libraries API].
  22. [source,java]
  23. ....
  24. import com.vaadin.annotations.*;
  25. @JavaScript({"https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js", "jquery.flot.js", "flot_connector.js"})
  26. public class Flot extends AbstractJavaScriptComponent {
  27. public void addSeries(double... points) {
  28. List<List<Double>> pointList = new ArrayList<List<Double>>();
  29. for (int i = 0; i < points.length; i++) {
  30. pointList.add(Arrays.asList(Double.valueOf(i),
  31. Double.valueOf(points[i])));
  32. }
  33. getState().series.add(pointList);
  34. }
  35. @Override
  36. public FlotState getState() {
  37. return (FlotState) super.getState();
  38. }
  39. }
  40. ....
  41. The shared state class will not be used by any GWT code so you don't
  42. have to put it in the widgetset's client package. The state class should
  43. extend `JavaScriptComponentState` but is otherwise similar to the shared
  44. state of a normal GWT component.
  45. [source,java]
  46. ....
  47. public class FlotState extends JavaScriptComponentState {
  48. public List<List<List<Double>>> series = new ArrayList<List<List<Double>>>();
  49. }
  50. ....
  51. The only remaining code is the client-side JavaScript connector in
  52. `flot_connector.js`. The connector defines a global initializer function
  53. named based on the fully qualified name of the server-side `Component`
  54. class with dots replaced with underscores. In this example the
  55. server-side `Component` is `com.example.Flot` which means that the function
  56. name should be `com_example_Flot`.
  57. This initializer function should initialize the JavaScript part of the
  58. component. It is called by the framework with `this` pointing to a
  59. connector wrapper providing integration to the framework. For full
  60. information about the services provided by the connector wrapper, please
  61. read the Javadoc for the `AbstractJavaScriptComponent` class.
  62. In this example, the initializer first initializes the `element`
  63. variable with a jQuery object for the DOM element of the component.
  64. Next, a state change listener is defined by assigning a function to the
  65. `onStateChange` field of the connector wrapper. This function will be
  66. called whenever the shared state is changed from the server-side code.
  67. In the state change listener, the Flot API is used to initialize a graph
  68. with the data series from the shared state into the DOM element.
  69. The format of the series property in the `FlotState` Java class has been
  70. chosen with the Flot API in mind. Flot expects an array of data series
  71. where each item is an array of data points where each data point is an
  72. array with the x value followed by the y value. This is defined in Java
  73. as `List<List<List<Double>>>` and then the framework takes care of the
  74. conversion between server-side Java values and client-side JavaScript
  75. values. `double[][][]` in Java would give the same JavaScript structure,
  76. but it was not used here as it gives less flexibility in the Java code.
  77. [source,javascript]
  78. ....
  79. window.com_example_Flot = function() {
  80. var element = $(this.getElement());
  81. this.onStateChange = function() {
  82. $.plot(element, this.getState().series);
  83. }
  84. }
  85. ....
  86. By implementing a server-side Java class extending
  87. `AbstractJavaScriptConnector` and a client-side JavaScript connector
  88. initialization function, existing JavaScript component libraries can
  89. easily be integrated to Vaadin. The server-side code is almost similar
  90. to the code required for a component based on GWT and the client-side
  91. code is quite similar to a `ComponentConnector` implemented using GWT.
  92. [WARNING]
  93. .Security Warning
  94. ====
  95. Do note that third-party JavaScript code could be dangerous
  96. (https://www.owasp.org/index.php/3rd_Party_Javascript_Management_Cheat_Sheet),
  97. and you should take into account the security risks of using such.
  98. ====