如何从 javafx 单击 HTMLAnchorElementImpl

How to click a HTMLAnchorElementImpl from javafx

website 包含以下 html 定义:

<input class="startDateInput" id="startdate" name="startdate" type="text" value="09/21/2015" maxlength="10" size="10" onkeypress="return isDateKey(event)" onblur="if (this.value.length!=10) { this.value='09/21/2015'; }">
<a id="retrieve" href="javascript:void(0);" onclick="doSubmit('Retrieve')">Retrieve Share Prices</a>

使用 javafx,可以使用

更新开始日期字段
int startDateIndx = ...;
String newStartDate = ...;
String setStartDate  =  "document.getElementsByTagName('input')["
    +startDateIndx+"].value='" + newStartDate + "';";
webEngine.executeScript(setStartDate);

但是,如何点击 java 中的 "Retrieve Share Prices" 元素?

本次尝试:

HTMLInputElement doRetrieve = (HTMLInputElement) doc.getElementById("retrieve");
doRetrieve.click();

生成此错误:

com.sun.webkit.dom.HTMLAnchorElementImpl cannot be cast to org.w3c.dom.html.HTMLInputElement

这里是演示代码

public class subForms extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    private boolean notEmpty(String s) {
        return s != null && !"".equals(s);
    }

    @Override
    public void start(Stage stage) {
        final TextField fxUsername = new TextField();
        final TextField fxPassword = new PasswordField();
        final TextField fxStartDate = new TextField();

        final BooleanProperty loginAttempted = new SimpleBooleanProperty(false);

        final WebView webView = new WebView();
        final WebEngine webEngine = webView.getEngine();
        webEngine.documentProperty().addListener(new ChangeListener<Document>() {

            @Override
            public void changed(ObservableValue<? extends Document> ov, Document oldDoc, Document doc) {
                if (doc != null && !loginAttempted.get()) {
                    if (doc.getElementsByTagName("input").getLength() > 0) {
                        int startDateIndx = getInputIndex(doc, "startdate");

                        if (startDateIndx >= 0) {
                            // webEngine.executeScript("window.coordinates.lat =
                            // 31.2;");
                            String newStartDate = fxStartDate.getText();
                            String setStartDate = "document.getElementsByTagName('input')[" + startDateIndx
                                    + "].value='" + newStartDate + "';";
                            loginAttempted.set(true);
                            webEngine.executeScript(setStartDate);
                            // com.sun.webkit.dom.HTMLAnchorElementImpl cannot
                            // be cast to org.w3c.dom.html.HTMLInputElement
                            ((HTMLInputElement) doc.getElementById("retrieve")).click();

                        }

                    }
                }
            }

            private int getInputIndex(Document doc, String matchName) {
                // matchName = "startdate"
                NodeList htmlInputs = doc.getElementsByTagName("input");
                for (int indx = 0; indx < htmlInputs.getLength(); indx++) {
                    Node inNode = htmlInputs.item(indx);
                    NamedNodeMap attributes = inNode.getAttributes();
                    // iterate over attributes
                    for (int i = 0; i < attributes.getLength(); i++) {
                        Attr attr = (Attr) attributes.item(i);
                        String attrName = attr.getNodeName();
                        if (attrName.equalsIgnoreCase("name")) {
                            String attrValue = attr.getNodeValue();
                            if (attrValue.equalsIgnoreCase(matchName)) {
                                return indx;
                            }
                        }
                    }
                }
                return -1;
            }
        });
        webEngine.getLoadWorker().exceptionProperty().addListener(new ChangeListener<Throwable>() {
            @Override
            public void changed(ObservableValue<? extends Throwable> ov, Throwable oldException, Throwable exception) {
                System.out.println("Load Exception: " + exception);
            }
        });

        GridPane inputGrid = new GridPane();
        inputGrid.setHgap(10);
        inputGrid.setVgap(10);
        Button fxButton = null;
        fxStartDate.setText("3/3/2003");
        inputGrid.addRow(0, new Label("Start Date: "), fxStartDate);
        fxButton = new Button("Get TSP Share Price History");

        fxButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                if (notEmpty(fxStartDate.getText())) {
                    loginAttempted.set(false);
                    final String tspURL = "https://www.tsp.gov/InvestmentFunds/FundPerformance/index.html";
                    webEngine.load(tspURL);
                }
            }
        });

        final VBox layout = new VBox(10);
        layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");
        layout.getChildren().addAll(new Label("Enter start date for TSP share price history"), 
                inputGrid, fxButton, webView);

        stage.setScene(new Scene(layout));
        stage.show();
    }

}

对于您发布的代码,单击 link 只需调用 Javascript 函数 doSubmit('Retrieve')。因此,对于这个特定的用例,您可以通过调用

来实现您想要的效果
webEngine.executeScript("doSubmit('Retrieve')");

不过,这并没有回答您的实际问题。我怀疑通过正确的向下转换,可以强制单击 HTML 元素;但是相关的 DOM 类 不是 public API.