I am able to get an element by Id like this in JavaFX.
Element nameField = engine.getDocument().getElementById( "name" );
How do I do the same given element's classname?
Thanks.
I am able to get an element by Id like this in JavaFX.
Element nameField = engine.getDocument().getElementById( "name" );
How do I do the same given element's classname?
Thanks.
I came across this and saw there wasn't much for answers. The way I found way to work with dom classes is not great but it gets the job done.
To add a class on a Node you obtained, use the setAttribute() method. Be careful to maintain any classes that might already exist on the Node.
Document doc = engine.getDocument();
if (doc != null){
Element elem = doc.getElementById('someID');
String classNames = elem.getAttribute("class");
classNames += " someClass"; //note the whitespace!
elem.setAttribute("class", classNames);
}
Then, if you wish to search the DOM by class you can execute javascript to do so using the executeScript on the WebEngine. The return type depends on what you're asking the script to do.
Small note: disabling javascript via engine.setJavaScriptEnabled(false); does not prohibit use of the engine.executeScript() method.
HTMLCollection result = (HTMLCollection)engine.executeScript("document.getElementsByClassName('someClass')");
However inefficient, I did this to determine what I would be getting back from executeScript() before writing any further code:
Object result = engine.executeScript("document.getElementsByClassName('someClass')");
System.out.println(result.getClass().getName());
Like I said it isn't great, but you can write some wrapper functions to make it easier to work with. Hope this helps!
You can access any component by using: the lookUp method.
For Example:
Button has class: specialClazz and your mainPane is a StackPane: rootPane
So you just do:
rootPane.lookUp(".specialClazz"); // .-selector!
For an ID:
rootPane.lookUp("#specialID"); // #-selector!
I'd use javax.xml.xpath. See XPath Tutorial - Example 6: Values of attributes can be used as selection criteria.
Note also that there is not necessarily a (single) element's class name. id is unique in a Document whereas class is not. So it should rather read elements' class name. (Subtle, but important. :-) In other words: there is not necessarily just one Element returned when searching for a given class.
The above answer:
"HTMLCollection result = (HTMLCollection)engine.executeScript("document.getElementsByClassName('someClass')");"
is bad. Because executeScript return's JSObject but not HTMLCollection; it cannot be casted.
The corrent is below java9 modular code sample (java14 has var): and you should add vm options to project:
--add-exports javafx.web/com.sun.webkit.dom=atools
var doc = webEngine.getDocument();
if (doc instanceof HTMLDocument htmlDocument) { //actually htmlDoc is HTMLDocumentImpl but java9 have to reflect
try {
Method method = null;
var clazz = htmlDocument.getClass();
method = clazz.getSuperclass().getMethod("getElementsByClassName", String.class);
HTMLCollection collection = (HTMLCollection) method.invoke(htmlDocument,"button");
//if collection not only 1
//you should special the document more deeply
for (int i = 0; i < collection.getLength(); i++) {
var btn = collection.item(i);
//actual is HTMLButtonElementImpl
//HTMLButtonElement htmlButtonElement = (HTMLButtonElement) btn;
var method1 = btn.getClass().getMethod("click");
method1.invoke(btn);
Log.d("");
break;
}
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
If you are not using java9+ modular, these reflects can replace with HTMLButtonElementImpl,HTMLDocumentImpl.