Search Unity

Popup blocker and PointerDown / PointerClick

Discussion in 'Web' started by chloridrik, Feb 1, 2016.

  1. chloridrik

    chloridrik

    Joined:
    Sep 9, 2013
    Posts:
    14
    Hi,

    I'm using the facebook sdk for my webgl app, and I have tried PointerDown or PointerClick event for the facebook login, but for each event Chrome block the popup.

    What is the best way to open popup in webgl export ?

    thx.
    Jeremie.
     
  2. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    327
    Hello chloridrik.

    If you want to avoid window.open() popup block, the call should be performed from a user-initiated JavaScript event handler. The difficulty here is that in Unity WebGL input events are not processed directly but instead are passed through an intermediate queue. This means that the initial JavaScript event handler initiated by the user has been already processed by the time when you receive the OnClick event in the managed code.

    Nevertheless, there is a trick that we can perform to make it work: as soon as the user pushes the UI button down, we can register an onclick JavaScript event for the whole WebGL canvas, so that when the user releases the button, we will get a user-initiated onclick JavaScript event and use it's handler to open the popup.

    You will need the following Assets/Plugins/PopupOpener.jslib plugin:
    Code (JavaScript):
    1. var PopupOpenerPlugin = {
    2.   PopupOpenerCaptureClick: function() {
    3.     var OpenPopup = function() {
    4.       window.open('http://unity3d.com', null, 'width=500,height=500');
    5.       document.getElementById('canvas').removeEventListener('click', OpenPopup);
    6.     };
    7.     document.getElementById('canvas').addEventListener('click', OpenPopup, false);
    8.   }
    9. };
    10. mergeInto(LibraryManager.library, PopupOpenerPlugin);
    and the following script to interact with it:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Runtime.InteropServices;
    4.  
    5. public class CanvasScript : MonoBehaviour {
    6.     [DllImport("__Internal")]
    7.     private static extern void PopupOpenerCaptureClick();
    8.  
    9.     public void OnButtonPointerDown () {
    10.         PopupOpenerCaptureClick ();
    11.     }
    12. }
    13.  
    The OnButtonPointerDown should be triggered by the Pointer Down event (available through the Event Trigger component, that you can attach to your UI button).

    Now your popup should open normally.
     
    Marks4 and Seb-1814 like this.
  3. chloridrik

    chloridrik

    Joined:
    Sep 9, 2013
    Posts:
    14
    Thank you Alex,

    Finaly I have added a div with a facebook connect button (with javascript SDK) over the canvas and I send the access_token and userid to UnitySDK and it work well.

    best regards,
    Jeremie
     
  4. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    327
    Yes, using html button is also a solution.
    Nevertheless, using a native Unity UI button has its advantages, as it is a part of the scene and can be easily hidden/displayed/moved directly from the managed code. All you have to do is to add a simple jslib plugin that will handle the click event. Common use cases that you can handle with the helper plugin: open popup, go fullscreen, open file from local drive, save file to local drive.
     
  5. nicos445

    nicos445

    Joined:
    Jun 7, 2016
    Posts:
    2
    Hi Alex,
    I tried your solution with the UI button and what I've got is the unity3d.com popup and chrome blocking the FBlogin popup...
    I've attached the PopupOpenerCaptureClick () to OnButtonPointerDown of the UI button and FBlogin as a normal response of the button click.
    Did I use your code wrong?
     
  6. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    327
    Hello nicos445.

    The window.open() should be executed from inside the JavaScript event handler in order to not be limited by the browser security policy. Your setup can not work, because normal UI button click will go through the intermediate input queue and will be executed after the actual event handler.

    Let me explain how the trick above works:

    - You attach OnButtonPointerDown() to the Pointer Down event (available through the Event Trigger component, that you can attach to your UI button). And then from this OnButtonPointerDown() you call the JavaScript function PopupOpenerCaptureClick() which attaches onclick event listener to the whole canvas. All this happens when the user presses the mouse button down.

    - So, while the mouse button is still down, we have already registered a pure JavaScript onclick event handler OpenPopup() for the canvas which will be executed as soon as the user releases the button somewhere over the canvas (you can alternatively register the onclick event handler for the whole document instead, then it will be triggered if user releases the mouse button somewhere over the page). Note that this has nothing to do with the Unity scripts anymore, because this is a pure JavaScript event handler. Note that JavaScript does not have any concept of the UI buttons and does not know where the original UI button was located, the event will be triggered as soon as the user releases the mouse button somewhere over the canvas (no matter over the original UI button or not).

    - When user releases the mouse button, our JavaScript function OpenPopup() is executed, and as it has been triggered directly by the user action as a JavaScript event handler, you are not limited by the browser security policy during its call. So you can execute for example window.open() without it being blocked. If you have a managed function FBlogin which performs login, then you may call it using SendMessage() from the OpenPopup(). Note that managed FBlogin will only work well if it is synchronous (i.e. FBlogin performs all the necessary processing including the window popup before return), then all the security related actions will be succefully performed inside the onclick event handler.

    - After running all the necessary code, OpenPopup() should now remove the onclick event listener (otherwise it would be triggered each time when user releases the mouse over the canvas in the future).

    If you have any difficulty making it work, post your exact code here (including the JavaScript plugins).
     
    Last edited: Sep 13, 2016
  7. fben

    fben

    Joined:
    Oct 24, 2015
    Posts:
    9
    Hi Alex,

    I'd like to achieve the same and have been following this thread.

    FB.LogInWithReadPermission() which is part of the Facebook Unity SDK is asynchronous. So I see the popup appearing and then vanishing... so despite using your fix I still have the same problem as without the fix ( I understand it's because the login fb function is non-blocking). All I need by the way is the email address of the user.

    Any help or advice would be much appreciated! Thanks a lot.
     
  8. anngo

    anngo

    Joined:
    Dec 29, 2015
    Posts:
    1
    Edan-Smith and Wanderer13 like this.
  9. JakeOfSpades

    JakeOfSpades

    Joined:
    Aug 22, 2015
    Posts:
    44
    Hey @anngo , Im not sure how to implement your fix for the Facebook SDK in my Unity Project. Sent you a PM
     
  10. jeremytm

    jeremytm

    Joined:
    Jun 6, 2016
    Posts:
    30
    @alexsuvorov that's a brilliant explanation of how the click event works. But you never actually explain how to capture the information from the facebook login popup window and return it to Unity to the Facebook SDK. Nor do you show how to close the pop-up again once it's all done.

    Would you mind please shedding some light on this?
     
    hacaro76 likes this.
  11. Eidern

    Eidern

    Joined:
    Mar 29, 2014
    Posts:
    98
    Hello,
    even with your example used as you wrote it, I get an EntryPointNotFoundException.
    Did something changed within the use of DLLImport meantime?
     
    cosmin-zhr likes this.
  12. hacaro76

    hacaro76

    Joined:
    Oct 14, 2015
    Posts:
    25
    I'm in the same situation with facebook login popup. Someone can explain how to solve ?
     
  13. lasco

    lasco

    Joined:
    Nov 12, 2009
    Posts:
    101
    Hello @alexsuvorov and thank you so much for help.
    Though I'm sorry, I can't manage using your codes. I'm really a newb on developpement could you explain how to use them on a 3D collider instead of a UI button ?
     
  14. rahul-ahuja79

    rahul-ahuja79

    Joined:
    Nov 16, 2013
    Posts:
    2
    1. Hi Nicos,
    2. I am not able to find the canvas when i attach the same script in my.jslib function .
    3. Please explain a appropriate solution for the same.
    4. document.getElementById('canvas').removeEventListener('click', OpenPopup);
     
  15. Kristof_Newfort

    Kristof_Newfort

    Joined:
    Feb 21, 2014
    Posts:
    24
    Hi Rahul

    Have you tried using ('#canvas')? If you look in the dev tools of your browser, you can see in the 'Elements' tab that the newer versions of Unity uses a new id.
     
  16. Romano360

    Romano360

    Joined:
    Oct 21, 2014
    Posts:
    8
    I just tryed alexsuvorov's example and it work fine on desktop, but on mobile not.
    There is sadly no error or anything... just doesnt work.
    Any idea how to get this to work on mobile?

    My goal is open a new tab from my webgl app without triggering the popup blocker.

    Thanks!
     
  17. forerun

    forerun

    Joined:
    May 12, 2020
    Posts:
    4
    @Romano360 i was struggling with the same thing and managed to make it work on mobiles too! use the method here http://va.lent.in/opening-links-in-a-unity-webgl-project/ and add ontouchend to the jslib file should look like this...

    Code (JavaScript):
    1. var OpenWindowPlugin = {
    2.     openWindow: function(link)
    3.     {
    4.         var url = Pointer_stringify(link);
    5.         document.onmouseup = function()
    6.         {
    7.             window.open("YOUR.URL.COM");
    8.             document.onmouseup = null;
    9.         }
    10.         var url = Pointer_stringify(link);
    11.         document.ontouchend = function()
    12.         {
    13.             window.open("YOUR.URL.COM");
    14.             document.ontouchend = null;
    15.         }
    16.     }
    17. };
    18.  
    19. mergeInto(LibraryManager.library, OpenWindowPlugin);

    replace "YOUR.URL.COM" with the url you want to access and its done ;)

    always a pleasure :)
     
    Last edited: Jun 11, 2020
    GerDavid likes this.
  18. forerun

    forerun

    Joined:
    May 12, 2020
    Posts:
    4
    also on a side note you can use this on any game object by not using event handler but put this code on any gameobject which basically gets the script component called "Link" and executes OpenLinkJsPlugin onmousedown instead...

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class mousedown : MonoBehaviour{
    6. public GameObject box;
    7.     void OnMouseDown(){
    8.         box.GetComponent<Link>().OpenLinkJSPlugin();
    9.  
    10.     }
    11. }
     
  19. Marks4

    Marks4

    Joined:
    Feb 25, 2018
    Posts:
    548
    @alexsuvorov this trick does not work on Unity 2020.1 beta. I still get the message "Failed to execute 'requestFullscreen' on 'Element': API can only be initiated by a user gesture."