1 package org
.argeo
.app
.ux
.js
;
3 import java
.util
.Arrays
;
4 import java
.util
.Locale
;
6 import java
.util
.StringJoiner
;
7 import java
.util
.concurrent
.CompletionStage
;
8 import java
.util
.function
.Function
;
11 * A remote JavaScript view (typically in a web browser) which is tightly
12 * integrated with a local UX part.
14 public interface JsClient
{
21 * Execute this JavaScript on the client side after making sure that the page
22 * has been loaded and the map object has been created.
24 * @param js the JavaScript code, possibly formatted according to
25 * {@link String#format}, with {@link Locale#ROOT} as locale (for
26 * stability of decimal separator, as expected by JavaScript.
27 * @param args the optional arguments of
28 * {@link String#format(String, Object...)}
30 Object
evaluate(String js
, Object
... args
);
33 * Executes this JavaScript without expecting a return value.
35 * @param js the JavaScript code, possibly formatted according to
36 * {@link String#format}, with {@link Locale#ROOT} as locale (for
37 * stability of decimal separator, as expected by JavaScript.
38 * @param args the optional arguments of
39 * {@link String#format(String, Object...)}
41 void execute(String js
, Object
... args
);
43 /** @return the globally usable function name. */
44 String
createJsFunction(String name
, Function
<Object
[], Object
> toDo
);
46 /** Get a global variable name. */
47 String
getJsVarName(String name
);
50 * Completion stage when the client is ready (typically the page has loaded in
53 CompletionStage
<Boolean
> getReadyStage();
59 default Object
callMethod(String jsObject
, String methodCall
, Object
... args
) {
60 return evaluate(jsObject
+ '.' + methodCall
, args
);
63 default void executeMethod(String jsObject
, String methodCall
, Object
... args
) {
64 execute(jsObject
+ '.' + methodCall
, args
);
67 default boolean isInstanceOf(String reference
, String jsClass
) {
69 return (Boolean
) evaluate("return " + getJsVarName(reference
) + " instanceof " + jsClass
);
70 } catch (Exception e
) {
71 // TODO better understand why instanceof is often failing with SWT Browser
80 static String
toJsValue(Object o
) {
81 if (o
instanceof CharSequence
)
82 return '\'' + o
.toString() + '\'';
83 else if (o
instanceof Number
)
85 else if (o
instanceof Boolean
)
87 else if (o
instanceof Map map
)
89 else if (o
instanceof Object
[] arr
)
90 return toJsArray(arr
);
91 else if (o
instanceof int[] arr
)
92 return toJsArray(arr
);
93 else if (o
instanceof long[] arr
)
94 return toJsArray(arr
);
95 else if (o
instanceof double[] arr
)
96 return toJsArray(arr
);
97 else if (o
instanceof AbstractJsObject jsObject
) {
99 return jsObject
.newJs();
101 return jsObject
.getJsReference();
102 } else if (o
instanceof JsReference jsReference
) {
103 return jsReference
.get();
105 return '\'' + o
.toString() + '\'';
108 static String
toJsArgs(Object
... arr
) {
109 StringJoiner sj
= new StringJoiner(",");
110 for (Object o
: arr
) {
111 sj
.add(toJsValue(o
));
113 return sj
.toString();
116 static String
toJsArray(Object
... arr
) {
117 StringJoiner sj
= new StringJoiner(",", "[", "]");
118 for (Object o
: arr
) {
119 sj
.add(toJsValue(o
));
121 return sj
.toString();
124 static String
toJsArray(String
... arr
) {
125 return toJsArray((Object
[]) arr
);
128 static String
toJsArray(double... arr
) {
129 return Arrays
.toString(arr
);
132 static String
toJsArray(long... arr
) {
133 return Arrays
.toString(arr
);
136 static String
toJsArray(int... arr
) {
137 return Arrays
.toString(arr
);
140 static String
toJsMap(Map
<?
, ?
> map
) {
141 StringJoiner sj
= new StringJoiner(",", "{", "}");
142 // TODO escape forbidden characters
143 for (Object key
: map
.keySet()) {
144 sj
.add("'" + key
+ "':" + toJsValue(map
.get(key
)));
146 return sj
.toString();
149 static String
escapeQuotes(String str
) {
150 return str
.replace("'", "\\'").replace("\"", "\\\"");