Search code examples
javascriptjavafxjxbrowser

Is it possible to return the result of a JS confirmation dialog presented by JXBrowser back to the JS section that called it?


I'm using JavaFX/JXBrowser to show an alert/dialog when the web page loaded into the Browser calls on Window.alert or window.confirm. However, I can't figure out how to return the result of the confirmation dialog (true/false) to JS. Since alert.showAndWait() is a blocking function, JS should wait for this result. However, showAndWait is also called in a Platform.runLater runnable, so I can't return the result. Short of writing JS functions to do the true/false code and calling those based on the result of showAndWait, is there any other option?

browser.setDialogHandler(new DialogHandler() {
@Override
        public CloseStatus onConfirmation(DialogParams params) {
            Platform.runLater(new Runnable() {

                @Override
                public void run() {
                    Alert alert = new Alert(AlertType.CONFIRMATION);
                    alert.setTitle("Yes/No");
                    alert.setHeaderText(null);
                    alert.setContentText("Yes/No");
                    Optional<ButtonType> result = alert.showAndWait();
                    if(result.isPresent())
                    {
                        if(result.get()==ButtonType.YES)
                        {
                            //Send true to calling JS function
                        }else
                        {
                            //Send false to calling JS function
                        }

                    }else
                    {
                        System.out.println("No result!");
                    }
                }
            });
            return null; //because I need to return something and I can't figure out how to get values from the runnable
        }
...
}

Solution

  • You can use the following approach:

    @Override
    public CloseStatus onConfirmation(DialogParams params) {
        final AtomicReference<CloseStatus> status = new AtomicReference<CloseStatus>();
        final CountDownLatch latch = new CountDownLatch(1);
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                Alert alert = new Alert(AlertType.CONFIRMATION);
                alert.setTitle("Yes/No");
                alert.setHeaderText(null);
                alert.setContentText("Yes/No");
                Optional<ButtonType> result = alert.showAndWait();
                if (result.isPresent()) {
                    if (result.get() == ButtonType.YES) {
                        status.set(CloseStatus.OK);
                    } else {
                        status.set(CloseStatus.CANCEL);
                    }
    
                } else {
                    System.out.println("No result!");
                }
            }
        });
        try {
            latch.await();
        } catch (InterruptedException ignored) {
            Thread.currentThread().interrupt();
        }
        return status.get();
    }