3

Hi I have a following code:

    button.addClickHandler( new ClickHandler( ) {
        @Override   
        public void onClick( ClickEvent event ) {    
             Call 1 --> Window.open( publicBookingUrl, "_blank", null );                
            dispatcher.execute( new HasServicesAction(true), 
                    new ActionCallback<SomeResult>( ){       
                @Override 
                public void onSuccess( SomeResult result ) {
             Call 2 --> Window.open( publicBookingUrl, "_blank", null );
                } 
            });  
        }        
    });

In Call 1 popup blocker does not block the popup from opening. It successfully opens a window in a new tab or in new window. In Call2 however popup blocker will prevent popup, so user have to explicitly enable popup. I found a post explaining the reasoning behind this: https://groups.google.com/forum/?fromgroups=#!topic/google-web-toolkit/V0s7goJxuhc Unfortunately this solution doesn't work for me.

Does anyone know why this is the case? How can we get around this?

Thanks in advance.

user_1357
  • 7,766
  • 13
  • 63
  • 106

2 Answers2

6

As the page you linked to indicated, windows may only be opened as a result of a direct user action. You can get around this by opening the window before your RPC call and setting the URL of the window after the RPC call returns. GWT's built-in Window doesn't expose all of the underlying window object's properties, so a custom implementation is necessary:

public class MyWindow extends JavaScriptObject {
  // All types that extend JavaScriptObject must have a protected,
  // no-args constructor. 
  protected MyWindow() {}

  public static native MyWindow open(String url, String target, String options) /*-{
    return $wnd.open(url, target, options);
  }-*/;

  public native void close() /*-{
    this.close();
  }-*/;

  public native void setUrl(String url) /*-{
    if (this.location) {
      this.location = url;
    }
  }-*/;
}

Then in your click handler:

public void onClick(ClickEvent event) {
  final MyWindow window = MyWindow.open(null, "_blank", null);

  dispatcher.execute(new HasServicesAction(true), 
      new ActionCallback<SomeResult>( ){       
        @Override 
        public void onSuccess(SomeResult result) {
          if (result.isGood()) {
            window.setUrl(publicBookingUrl);
          } else {
            window.close();
          }
        }
      });  
}

Note that, if your call to setUrl() changes the origin of the opened window you won't be able to modify any properties or call any functions afterwards.

Jason Terk
  • 6,005
  • 1
  • 27
  • 31
-2

Get rid of window popups. Use PopupDialog instead.

If a user disabled popups and you found a way to show it, what will this user think about you?

Andrei Volgin
  • 40,755
  • 6
  • 49
  • 58
  • 1
    There are legitimate uses for `window.open`. – Jason Terk Nov 08 '12 at 02:09
  • May be. But if a user blocked popups, it's not "legitimate" to hack your way around it. Tell them to enable popups for your website, if you can't use a PopupDialog for any reason. – Andrei Volgin Nov 08 '12 at 04:39
  • One example: Try showing a PDF (or actually, offering it for download) in a popup dialog. For your workaround, how can I know whether a popup blocker is active (to tell the user to disable it)? – Paŭlo Ebermann May 29 '13 at 07:31
  • @PaŭloEbermann I do offer PDF downloads in one of my applications by opening a new tab. The difference is that when a user initiates the action (i.e. a user clicks on the download button or icon), browsers allow it. When you try to open a new tab programmatically without a user action, a browser blocks it. – Andrei Volgin May 29 '13 at 18:29
  • Yes ... we just changed the behaviour of our app so the button click does a GWT-RPC call first and on the return loads the PDF (so we can have some feedback to the user in case something doesn't work). It is not exactly without user action, but I suppose the browser doesn't see the difference. For now the workaround is to tell the users (by mail) to allow it, but I would like to check it from my app. Or I'll try the solution from Jason. – Paŭlo Ebermann May 30 '13 at 17:16
  • I don't understand what you are trying to do. You do not need popups or tabs to let a user download a PDF. All you need is a link that returns a PDF file from a servlet - set the right "Content-Disposition" header on your response and you are all set. – Andrei Volgin May 30 '13 at 18:03
  • The PDF has first to be generated, and there are some things which can go wrong here. If something goes wrong, I want to show the problem in a useful error message, if not, I want to open it (in a new tab, so it doesn't clear out my GWT frontend). – Paŭlo Ebermann May 30 '13 at 18:44
  • You can deliver an error message in the same http response: set a different header, and a browser will display your error message as text, for example, instead of offering to save a PDF file. Or you have to have a two step process: (1) show an icon/button to generate a PDF, then (2) show a link to download it if it was generated correctly. – Andrei Volgin May 31 '13 at 20:50