Is there a way to tell if a form is valid from Java?
Basically, a method that returns true if all input fields constrains are satisfied and false otherwise.
Strangely enough, org.w3c.dom.html.HTMLFormElement doesn't actually have a checkValidity() method.
EDIT:
Even more strangely, the implementation com.sun.webkit.dom.HTMLFormElementImpl does support the method checkValidity(). Unfortunately, the package com.sun.webkit is not accessible directly and thus the method is unavailable.
DOM objects like HTMLFormElement only model structure. They are not capable of executing JavaScript.
However, WebEngine itself does have a JavaScript interpreter, which you can invoke using the executeScript method:
boolean valid = (Boolean) webView.getEngine().executeScript(
"document.forms[0].checkValidity();");
The checkValidity() method is documented here and here.
Cast the form to JSObject
Most HTML Java elements, including HTMLFormElement, can be directly cast to the JavaScript object JSObject. It is then trivial to validate the form.
Example:
JSObject jsObject = (JSObject) form;
boolean valid = (boolean) jsObject.call("checkValidity");
Related
I have to send a serialized object from java to javascript with jxbrowser and I do this like this
String json = objectMapper.writeValueAsString(value);
JSValue window = browser.executeJavaScriptAndReturnValue("window");
window.asObject().setProperty(requestName, json);
As far as I know it will set a object in global window as requestName? It is true?
And in another way how I can read this object from java site. This code is ok?
JSValue window = browser.executeJavaScriptAndReturnValue("window."+requestName);
T t = objectMapper.readValue(window.toString(), clazz))
Thanks in advance
Hi there are two aspects here.
Javascript execution context
JSValue that can be a plain value or a JavaScript object.
Once you invoke executeJavaScriptAndReturnValue your execution context is complete. And you can evaluate the returned object. This returned object can be a Java script object with functions in which case you can access it.
Lets say that your JavaScriptObject has a method helloWorld which accepts string.
JSValue document = browser.executeJavaScriptAndReturnValue("myJavascriptObject");
JSValue write = document.asObject().getProperty("helloWorldMethod");
write.asFunction().invoke(document.asObject(), "To Me");
This way we have passed the "To Me" string to the helloWorldMethod.
You can also set properties on the Object and invoke later another method. If this method uses this property, than within the next execution it will be taken into account:
JSValue document = browser.executeJavaScriptAndReturnValue("myJavascriptObject");
JSValue write = document.asObject().getProperty("helloWorldMethod");
document.asObject().setProperty("shouldISayGoodByeInstead",true)
write.asFunction().invoke(document.asObject(), "To Me");
The property shouldISayGoodByeInstead will be evaluated as part of the second execution which happens when helloWorldMethod is invoked, not during the first execution of executeJavaScriptAndReturnValue.
If I understand you correctly, you want to set a JavaScript object through JSON. This can be achieved via the JSONString. You can check the example here: https://jxbrowser.support.teamdev.com/support/solutions/articles/9000013064-working-with-json
After that, you want to get the JSON object. For this case, there is a method
JSObject.toJSONString()
So if we change your sample in the following way, it should work as expected:
String json = objectMapper.writeValueAsString(value);
JSValue window = browser.executeJavaScriptAndReturnValue("window");
window.asObject().setProperty(requestName, new JSONString(json));
JSValue window = browser.executeJavaScriptAndReturnValue("window."+requestName);
T t = objectMapper.readValue(window.asObject().toJSONString(), clazz))
I want to create a JSObject and fill it with properties (kind of like a HashMap), but without casting the result of an eval("({})"), because I would think that constantly evaluating such a thing would really have an impact on performance. Is there a way?
If you want to use script objects like Maps, you might as well use java.util.HashMap instances from Nashorn scripts! In addition to supporting the usual java method calls, Nashorn's linker special cases java.util.Map instances and supports keys-as-property names idiom. This is more efficient than using a Javascript object as a Map.
$ jjs
jjs> var m = new java.util.HashMap
jjs> m.foo = "bar"
bar
jjs> m.foo
bar
jjs> m.get("foo")
bar
jjs> m.put("js", "nashorn")
null
jjs> m.js
nashorn
But, if you insist on using JS-object-as-map, then you can do the eval and cast to JSObject you mentioned. You may want to measure the perf. hit (which is assumed!) before making any further changes!
You can also get hold of JS "Object" constructor object and 'cache' it for repeated object creation from Java code. You can then call newObject() method on it to create a new empty object.
import javax.script.*;
import jdk.nashorn.api.scripting.JSObject;
public class Main {
public static void main(String[] args) throws Exception {
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine e = m.getEngineByName("nashorn");
// get JS "Object" constructor object
JSObject objConstructor = (JSObject)e.eval("Object");
// call 'newObject' on Object constructor
JSObject jsObj = (JSObject) objConstructor.newObject();
// fill properties of the new empty script object
jsObj.setMember("foo", "bar");
// expose the new JS object as global var!
e.put("obj", jsObj);
// print the object as a JSON string
e.eval("print(JSON.stringify(obj))");
}
}
Note that the above scheme works for any user-defined constructor function as well. For eg. if you want to create objects using specific user defined constructor function, you just have to replace
JSObject objConstructor = (JSObject)e.eval("Object");
with
JSObject objConstructor = (JSObject)e.eval("MyConstructorFunc");
(assuming you've eval'ed code to define MyConstructorFunc function earlier).
The rest of the code is same as above.
I use SWT Browser object to load a web page like this:
Browser browser = new Browser(parent, SWT.BORDER);
browser.setUrl("http://localhost:18080/app/test-servlet");
I have a function to call the evaluate method. (The function is triggered by clicking a SWT Button on the control.)
public void evaluate() {
Object content = browser.evaluate("getClientContent();");
System.out.println("content: " + content);
}
On the web page, the javascript function getClientContent() is:
<script type="text/javascript">
function getClientContent() {
alert("test");
return "test";
}
</script>
When I click the test button on SWT application, I could see the alert box shown up with "test". But the evaluate() always returns null. What is wrong with the code? Thanks
You need to 'return' the result in the JavaScript, like this:
Object content = browser.evaluate("return getClientContent();");
The return values are restricted to a few types:
Returns the result, if any, of executing the specified script.
Evaluates a script containing javascript commands in the context of
the current document. If document-defined functions or properties are
accessed by the script then this method should not be invoked until
the document has finished loading (ProgressListener.completed() gives
notification of this).
If the script returns a value with a supported type then a java
representation of the value is returned. The supported javascript ->
java mappings are:
*javascript null or undefined -> null
*javascript > number -> java.lang.Double
*javascript string -> java.lang.String
*javascript boolean -> java.lang.Boolean
*javascript array whose elements are all of supported types -> java.lang.Object[]
Try for example
Object result = browser.evaluate("return 1;");
If the return type is not supported ... null seems to be returned.
Try for example
Object window = browser.evaluate("return window;");
The documentation for "evaluate" states
An SWTException is thrown if the return value has an unsupported type, or
if evaluating the script causes a javascript error to be thrown.
which I find misleading since I would expect the above line to throw an exception since the window object can not be returned.
I need to pass a parameter to my page and I can't find a way to pass parameters that might be null.
If I do:
PageParameters pageParameters = new PageParameters ();
pageParameters.add ("key", null);
This will result in an exception
java.lang.IllegalArgumentException: Argument 'value' may not be null.
at org.apache.wicket.util.lang.Args.notNull(Args.java:41)
If I use Google Guava's Optional, I can't find any way to cast the object even if the the Optional object is not holding a null ie not equals to Optional.absent() :
In my landing page's constructor I do
StringValue sv = parameters.get ("key");
sv.to ( Optional.of (MyEnum.SOME_ENUM_CONSTANT).getClass () );
and when I run it I get this error:
org.apache.wicket.util.string.StringValueConversionException: Cannot
convert 'Optional.of(SOME_ENUM_CONSTANT)'to type class
com.google.common.base.Present.
Am I doing something wrong?
Is there any other way to pass a possibly null object in wicket 6?
I noticed in wicket 1.4 they have PageParameters.NULL which seems to have dissapeared in wicket 6.
Thank you
This might be too simple, but what's wrong with
Object value = ?
if (value != null) {
pageParameters.add ("key", value);
}
and
StringValue sv = pageParameters.get("key");
if (!sv.isNull()) {
// process string value
}
All page parameters in wicket will be treated as Strings eventually. The idea is that a page parameter will be on the URL of the request.
From the javadoc:
Suppose we mounted a page on /user and the following url was accessed /user/profile/bob?action=view&redirect=false. In this example profile and bob are indexed parameters with respective indexes 0 and 1. action and redirect are named parameters.
If you add something like x=y&x, the parameter x will appear twice, once with the String y and another with the empty string.
Depending on what you are trying to accomplish I would suggest to either
Don't pass the parameter at all when there is a null value required and use the isNull or toOptional methods.
Use indexed parameters and test for presence of a certain word
How do I use Rhino return a string from Java to Javascript, all I get is org.mozilla.javascript.JavaNativeObject when I use
var jsString = new java.lang.String("test");
inside my js file.
Is this the right way to do it?
var jsString = String(new java.lang.String("test"));
The goal is to have a Java method to return the String object instead of creating it on the fly like above.
In general, you would call Context.javaToJS which converts a Java object to its closest representation in Javascript. However, for String objects, that function returns the string itself without needing to wrap it. So if you're always returning a string, you don't need to do anything special.
Although in most cases the returned Java String type can be used just like the JS String type within the JS code, it does not have the same methods!
In particular I found it cannot be used in a JS object passed to 'stringify()' as it does not have the toJSON() method.
The only solution I found is to explicitly do the addition of "" in the JS, to convert the Java String to a JS String. I found no way to code the java method to return a good JS string directly... (as Context.javaToJS() doesn't convert a Java String)
Eg:
var jstr = MyJavaObj.methodReturningAString();
JSON.stringify({ "toto":jstr}); // Fails
JSON.stringify({ "toto": ""+jstr}); // OK
Turn off the wrapping of Primitives and then the value returned in your expression will be a JS string:
Context cx = Context.enter();
cx.getWrapFactory().setJavaPrimitiveWrap(false);
For me this is a Rhino bug. The s+"" trick inside JavaScript works, but here's a quick patch to fix it Java-side - after this line in NativeJavaMethod.call()
Object retval = meth.invoke(javaObject, args);
add this check to convert it to a native JavaScript string (ie typeof returns "string" not "object")
if (retval instanceof String) {
return NativeJavaObject.coerceTypeImpl(String.class, retval);
}
This is important otherwise s.replace() calls the Java version so is wrong for eg "h e l l o".replace(" ", "")
https://github.com/mozilla/rhino/issues/638