web-dev-qa-db-fra.com

Contourner le bloqueur de fenêtres contextuelles sur window.open lorsque JQuery event.preventDefault () est défini

Je souhaite afficher conditionnellement une boîte de dialogue JQuery sur l'événement de clic d'un lien hypertexte.

J'ai une exigence telle que sur condition1, ouvrir un dialogue JQuery et si condition1 n'est pas remplie, accédez à la page référencée par la balise 'href' de l'événement de clic en question.

Je suis en mesure d'appeler une fonction sur l'événement de clic de link. Cette fonction vérifie maintenant ladite condition en exécutant une autre URL (qui exécute mon contrôleur Spring et renvoie une réponse).

Tout fonctionne parfaitement avec uniquement window.open bloqué par un bloqueur de popup.

$('a[href*=/viewpage?number]').live('click', function(e) {
    e.preventDefault();
    redirectionURL = this.href;
    pageId= getUrlVars(redirectionURL)["number"];
    $.getJSON("redirect/" + pageId, {}, function(status) {
        if (status == null) {
            alert("Error in verifying the status.");
        } else if(!status) {
            $("#agreement").dialog("open");
        } else {
            window.open(redirectionURL);
        }
    });
});

Si je supprime e.preventDefault(); du code, Popoup Blocker ne bloque pas la page. Cependant, pour condition1, il ouvre alors la boîte de dialogue ainsi que la page 'href'.

Si je résous un problème, cela crée un problème pour un autre. Je ne suis pas capable de rendre justice aux deux conditions simultanément.

Pourriez-vous m'aider à résoudre ce problème s'il vous plaît?

Une fois que cela est résolu, j’ai un autre problème à résoudre, à savoir la navigation dans l’événement OK du dialogue :)

93
mavaze

Les bloqueurs de fenêtres publicitaires n'autorisent généralement que window.open si utilisé pendant le traitement d'un événement utilisateur (comme un clic). Dans votre cas, vous appelez window.openlater, pas pendant l'événement, car $.getJSON est asynchrone.

Vous avez deux options:

  1. Faites quelque chose d'autre, plutôt que window.open.

  2. Faites en sorte que l'appel ajax soit synchrone, ce que vous devriez normalement éviter comme la peste, car il verrouille l'interface utilisateur du navigateur. $.getJSON est équivalent à:

    $.ajax({
      url: url,
      dataType: 'json',
      data: data,
      success: callback
    });
    

    ... et pour rendre votre appel $.getJSON synchrone en mappant vos paramètres sur ceux ci-dessus et en ajoutant async: false:

    $.ajax({
        url:      "redirect/" + pageId,
        async:    false,
        dataType: "json",
        data:     {},
        success:  function(status) {
            if (status == null) {
                alert("Error in verifying the status.");
            } else if(!status) {
                $("#agreement").dialog("open");
            } else {
                window.open(redirectionURL);
            }
        }
    });
    

    Encore une fois, je ne préconise pas les appels ajax synchrones si vous pouvez trouver un autre moyen d'atteindre votre objectif. Mais si vous ne pouvez pas, voilà.

    Voici un exemple de code qui échoue au test en raison de l'appel asynchrone:

    Exemple live | Live source (Les liens actifs ne fonctionnent plus à cause des modifications apportées à JSBin)

    jQuery(function($) {
      // This version doesn't work, because the window.open is
      // not during the event processing
      $("#theButton").click(function(e) {
        e.preventDefault();
        $.getJSON("http://jsbin.com/uriyip", function() {
          window.open("http://jsbin.com/ubiqev");
        });
      });
    });
    

    Et voici un exemple qui fonctionne, utilisant un appel synchrone:

    Exemple live | Live source (Les liens actifs ne fonctionnent plus à cause des modifications apportées à JSBin)

    jQuery(function($) {
      // This version does work, because the window.open is
      // during the event processing. But it uses a synchronous
      // ajax call, locking up the browser UI while the call is
      // in progress.
      $("#theButton").click(function(e) {
        e.preventDefault();
        $.ajax({
          url:      "http://jsbin.com/uriyip",
          async:    false,
          dataType: "json",
          success:  function() {
            window.open("http://jsbin.com/ubiqev");
          }
        });
      });
    });
    
139
T.J. Crowder

vous pouvez appeler window.open sans blocage du navigateur uniquement si l'utilisateur effectue directement une action . Le navigateur envoie un indicateur et détermine la fenêtre ouverte par l'action de l'utilisateur.

Donc, vous pouvez essayer ce scénario:

  1. var myWindow = window.open ('')
  2. dessine n'importe quel message de chargement dans cette fenêtre
  3. une fois la demande effectuée, appelez simplement myWindow.location = ' http://google.com '
59
Evgeniy Kubyshin

J'ai eu ce problème et je n'avais pas mon URL prête jusqu'à ce que le rappel retourne des données. La solution consistait à ouvrir une fenêtre vierge avant de lancer le rappel, puis à définir l'emplacement au retour du rappel.

$scope.testCode = function () {
    var newWin = $window.open('', '_blank');
    service.testCode().then(function (data) {
        $scope.testing = true;
        newWin.location = '/Tests/' + data.url.replace(/["]/g, "");
    });
};
36
KnuturO

essayez ça, ça marche pour moi,

$('#myButton').click(function () {
    var redirectWindow = window.open('http://google.com', '_blank');
    $.ajax({
        type: 'POST',
        url: '/echo/json/',
        success: function (data) {
            redirectWindow.location;
        }
    });
});

Est un violon pour cela http://jsfiddle.net/safeeronline/70kdacL4/1/

17
Mohammed Safeer

Windows doit être créé sur la même pile (alias microtask ) que l’événement initié par l’utilisateur, par exemple. un rappel de clic - afin qu'ils ne puissent pas être créés plus tard, de manière asynchrone.

Cependant, vous pouvez créer une fenêtre sans URL et modifier ensuite l'URL de cette fenêtre une fois que vous la connaissez, même de manière asynchrone!

window.onclick = () => {
  // You MUST create the window on the same event
  // tick/stack as the user-initiated event (e.g. click callback)
  const googleWindow = window.open();

  // Do your async work
  fakeAjax(response => {
    // Change the URL of the window you created once you
    // know what the full URL is!
    googleWindow.location.replace(`https://google.com?q=${response}`);
  });
};

function fakeAjax(callback) {
  setTimeout(() => {
    callback('example');
  }, 1000);
}

Les navigateurs modernes ouvrent la fenêtre avec une page vierge (souvent appelée about:blank), et en supposant que votre tâche asynchrone pour obtenir l'URL soit assez rapide, l'UX obtenue est généralement satisfaisante. Si vous souhaitez plutôt rendre un message de chargement (ou quoi que ce soit) dans la fenêtre pendant que l'utilisateur attend, vous pouvez utiliser URI de données .

window.open('data:text/html,<h1>Loading...<%2Fh1>');
7
jayphelps

Ce code m'aide. J'espère que cela aidera certaines personnes

$('formSelector').submit( function( event ) {

    event.preventDefault();

    var newWindow = window.open('', '_blank', 'width=750,height=500');

    $.ajax({

        url: ajaxurl,
        type: "POST",
        data: { data },

    }).done( function( response ) {

        if ( ! response ) newWindow.close();
        else newWindow.location = '/url';

    });
});
3
Richard

Essayez d’utiliser un élément un lien et cliquez dessus avec javascript.

<a id="SimulateOpenLink" href="#" target="_blank" rel="noopener noreferrer"></a>

et le script

function openURL(url) {
    document.getElementById("SimulateOpenLink").href = url
    document.getElementById("SimulateOpenLink").click()
}

Utilisez-le comme ça

//do stuff
var id = 123123141;
openURL("/api/user/" + id + "/print") //this open webpage bypassing pop-up blocker
openURL("https://www.google.com") //Another link
3
Fernando Carvajal

L'observation selon laquelle l'événement devait être initié par l'utilisateur m'a aidé à comprendre la première partie de celle-ci, mais même après cela, Chrome et Firefox ont toujours bloqué la nouvelle fenêtre. La deuxième partie ajoutait target = "_ blank" au lien, ce qui était mentionné dans un commentaire.

En résumé: vous devez appeler window.open à partir d'un événement initié par l'utilisateur, en cliquant ici sur un lien, et ce lien doit avoir target = "_ blank".

Dans l'exemple ci-dessous, le lien utilise class = "button-Twitter".

$('.button-Twitter').click(function(e) {
  e.preventDefault();
  var href = $(this).attr('href');
  var Tweet_popup = window.open(href, 'Tweet_popup', 'width=500,height=300');
});
2
Alexis Bellido

J'utilise cette méthode pour éviter le bloqueur de popup dans mon code React. cela fonctionnera également dans tous les autres codes javascript.

Lorsque vous effectuez un appel asynchrone au clic, ouvrez tout d’abord une fenêtre vierge, puis écrivez l’URL plus tard lorsqu’un appel asynchrone sera terminé.

const popupWindow = window.open("", "_blank");
popupWindow.document.write("<div>Loading, Plesae wait...</div>")

sur le succès de l'appel asynchrone, écrivez ce qui suit

popupWindow.document.write(resonse.url)
1
Tabish
var url = window.open("", "_blank");
url.location = "url";

cela a fonctionné pour moi.