Thursday, January 26, 2017

JavaFX WebView: Hyperlink listeners and issue with extracting href value from tag 'A'

In our previous post, we talked about mouse event handling on hyperlinks displayed in webview component. This post discusses a problem observed in correctly identifying tag 'A' and retrieving its href value. We noticed that sometimes, the event target is not the hyperlink tag 'A' instead the sub element in it (tag 'b' in this case) such as the one shown below.

Click me

Event listeners are added to the hyperlink nodes as shown below

Document doc = eng.getDocument();
NodeList nodeList = doc.getElementsByTagName("a");
for (int i = 0; i < nodeList.getLength(); i++) {
((EventTarget) nodeList.item(i)).addEventListener("click", listener, false);
((EventTarget) nodeList.item(i)).addEventListener("mouseover", listener, false);
((EventTarget) nodeList.item(i)).addEventListener("mouseout", listener, false);
}

In the respective event handler, event target is retrieved as shown below. For some elements, the href is null. When we tried to find why is href null, we observed that the element is not tag 'A' instead it is 'B', which is the sub element of tag 'A'.

public void handleEvent(Event ev) {
String domEventType = ev.getType();
Element element = ((Element) ev.getTarget()) ;
String href = element.getAttribute("href");
}

So, in order to process all hyperlinks, when href is null, get it's parent element and retrieve the parent href as one expects to do it. After doing this as shown below, all our hyperlink events started firing and we got them working as expected.

public void handleEvent(Event ev) {
String domEventType = ev.getType();
Element element = (Element)ev.getTarget() ;
String href = element.getAttribute("href");
if (href == null){
Node parentNode = element.getParentNode() ;
if (parentNode != null){
String parentNodeName = parentNode.getNodeName() ;
if ("A".equalsIgnoreCase(parentNodeName)){
href = ((Element)parentNode).getAttribute("href") ;
}
}
}
//do something with href here
}

Full code is embedded in our previous article, you just need to add the highlighted lines from above code piece to get this working.