Is there a reliable way to detect the closing of the browser tab or window on the server side in a wicket application?
It must work under firefox version 68.11.0 or higher. I use wicket 8.8.0.
I tried it with websockets and catching the connection close event. But unfortunately this event is also raised when a page is refreshed (F5).
new WebSocketBehavior() {
#Override
protected void onClose(ClosedMessage message) { // invoked on tab close, window close and unfortunately on page reload
super.onClose(message);
log.info("Connection for page = '{}' closed.", message.getKey());
}
}
From browser point of view there is no difference between closing the tab and refreshing the tab. In both cases the browser fires beforeunload JavaScript event and closes all open connections (WebSocket, ServerSideEvent, Ajax).
So, you can use
page.add(new AjaxEventBehavior("beforeunload") {
#Override public void onEvent(AjaxRequestTarget target) {...}
});
but this just tell you that the user navigates away from the current page. There is no info what comes next.
Related
I would like to have a multi-tab/windowed Eclipse RAP application.
I am able to open a second window using
UrlLauncher launcher = RWT.getClient().getService(UrlLauncher.class);
launcher.openURL("/gasf?foo=other_perspective");
Where I use the foo paramter to select the perspetive I want. However using this method will create a speparate http session, thus the various listeners and so on won't communicate with my first window.
I also tried opening a second window/page using
PlatformUI.getWorkbench().getActiveWorkbenchWindow().openPage("other_perspective" , null);
But this merely changes the current window perspective but does not open a second window or tab in my browser.
Has anyone achieved a multi-tab RAP application with working selectionlisteners between the tabs?
Thanks for any help you can provide
EDIT:
THANKS a lot ralfstx, as you pointed out, I can share the listeners or anything using the shared HTTP session, so far so good. Now the next step is to be able to update a tab based on an external event.
To try my idea of refresh from another tab, I did a dummy timer that does something 2 seconds later (i.e. simulate something triggered from another tab) with:
final ServerPushSession pushSession = new ServerPushSession();
pushSession.start();
Display display = Display.getDefault();
NavigationView navigationView = ((NavigationView) window.getActivePage().findView(NavigationView.ID));
timer.schedule(new TimerTask() {
#Override
public void run() {
display.asyncExec(new Runnable() {
public void run() {
navigationView.doSomething();
}
});
}
}, 2000);
This works! The pushSession.start() forces the UI to refresh without any user interaction. So now the action doSomething() is executed on the navigationView as soon as the 2 seconds are reached.
My only remaining concern is how much load this puts on the server, but its a reasonable solution at least. I validated your answer.
EDIT2:
Just to be complete, to make sure not bump in an invalid Thread access error since we are updating a display from another display, in the doSomething() method we must execute actions using display.asyncExec:
Display display = Display.getCurrent();
public void doSomething() {
display.asyncExec(new Runnable() {
public void run() {
treeViewer.refresh();
}
});
}
With the current architecture of RAP, you can't spread workbench windows over different browser tabs. Every new browser starts a new UISession which implies another Display (see Scopes in RAP).
However, the HttpSession should be the same (unless you have cookies turned off), so you could use this as a means of communicating between different browser tabs.
I am trying to open an email client just like using mail me tag.
But I want to use my custom widget, which is not hyperlink, anchor or so. I added a DOM handler to my widget to listen to clicks:
public class VContactWidget extends VHorizontalLayout implements ClickHandler {
private HandlerRegistration clickHandler;
public VContactWidget() {
// added some content here
clickHandler = addDomHandler(this, ClickEvent.getType());
}
#Override
public void onClick(ClickEvent event) {
Window.open("mailto:john.doe#mail.com", "_blank", "");
}
}
Everything is working fine except one detail: When the widget is clicked, new empty browser tab will open with url set to mailto:john.doe#mail.com. I don't want the new tab opened. Can I avoid it somehow?
Note I set _blank parameter, as used in many examples. I also tried to use empty string or some other values as well. I looked into documentation, but didn't find anything useful.
https://developer.mozilla.org/en-US/docs/Web/API/window.open
One solution may be to use Anchor, but my component is more complex, not just single <a> link.
Another detail to note may be application server - I am using Tomcat 7 now.
Trying to fire native event on hidden Anchor programatically did not work for me. (Which does not mean it cannot be done.)
This is, how I actually solved my problem: Instead of Window.open(), I used following call:
public void onClick(ClickEvent event) {
Window.Location.assign("mailto:john.doe#mail.com");
}
This is not something that you can control. Whether this link opens in a new tab or a new window depends on the browser settings and user preferences.
I don't think it will make a difference if you use an Anchor or Window.open. In either case, the behavior may be different in different browsers. Also remember that for some users a click on this link will open Outlook or Mail, while for other users it will open Gmail in a browser window.
UPDATE:
If you want an exact behavior of an <a> element, create a hidden anchor element and fire a click on it when a user clicks on your composite widget.
Firing click event from code in gwt
So I'm making a eclipse plugin and I have a made my own dialog by extending the dialog class.
My dialog basically populates a treeview with data from a server. Sometimes the data cannot be populated (because the server is down) so my treeview is empty.
I have made another dialog appear reporting the error if I am unable to connect to the server.
My problem is that I would like to close the initial dialog when I press ok in the error dialog.
I have not been able to find a good way to do this.
I have tried setting setBlockOnOpen to false.
I have tried calling cancelPressed.
Neither of them have worked.
I called them in the createDialogArea function.
Any Ideas on how I could get this to work?
It is basically user cancelling dialog. you need to invoke cancelPressed() so it will be consistent handling if you have any code that depends on returnCode
if(noDataLoaded){
Display.getDefault().asyncExec(new Runnable() {
public void run() {
cancelPressed():
}
});
}
You need to do the close call after the dialog creation has finished. You can do this by using this code:
parent.getDisplay().asyncExec(new Runnable()
{
#Override
public void run()
{
close();
}
});
in your createDialogArea method. However the dialog may appear briefly. It would be better to do your check before creating the dialog.
i am using GWT. on window close we get browser provided message" Are you sure you want to navigate away from this page?". i want to replace the message with my own message. please help me. below is my code.
Window.addWindowClosingHandler(new Window.ClosingHandler() {
#Override
public void onWindowClosing(final Window.ClosingEvent closingEvent) {
closingEvent.setMessage("some message.");
}
});
you can not modify the dialog that is opened if you provide a string in the closing event.
The dialog is handled by the browser and can not be customized.
I have a web app that uses GXT (version 1.2.2) grids extensively. I'd like to warn the user if they make changes but don't save.
When I use the grid in a popup dialog, the only way for the user to leave is via a button (either Close or OK). If I add a SelectionListener to the Close button, I can do my "isDirty()" check and warn the user.
If I am not using a dialog, the restriction for leaving the page isn't there. The user can click on a side menu, select a different tab, hit a refresh or next page button that we have on each page. I could listen for an event on everyone of those, but is there an easier way? Something like a "before unload" event that gets fired?
Window.addCloseListener
Or in GWT 1.6:
Window.addCloseHandler
You cannot prevent the window from closing, but you can prompt the user to click cancel which will leave the page open. You can also perform a last-chance save operation after the user chooses to confirm the window close, but before your page is unloaded.
Try this:
Window.addListener(Events.Close,
new Listener<ComponentEvent>() {
public void handleEvent(ComponentEvent be) {
//Do something
}
});
or
Window.addListener(Events.Detach,
new Listener<ComponentEvent>() {
public void handleEvent(ComponentEvent be) {
//Do something
}
});