web-dev-qa-db-fra.com

Ouvrir un nouvel onglet sans bloqueur de popup après un appel ajax sur le clic de l'utilisateur

J'ai une page qui permet à l'utilisateur d'effectuer une manipulation d'image via le canevas HTML5, sur la page, il y a un bouton de partage facebook pour partager une image générée du canevas sur facebook.

Lorsque le lien est cliqué, une demande ajax est envoyée au serveur (ASP.NET MVC) pour effectuer la génération d'image, enregistrer l'image sur le serveur, puis générer une URL (qui relie à l'image) qui est renvoyée comme ajax réponse. L'URL retournée est ce que je veux passer comme paramètre pour Facebook à partager. Le problème est que le bloqueur de popup bloque la boîte de dialogue de partage Facebook lorsque j'appelle "window.open".

Existe-t-il un autre moyen d'ouvrir un nouvel onglet sans bloqueur de popups? Je pense que depuis que l'utilisateur a lancé l'action, il devrait y avoir un moyen pour moi de contourner le bloqueur de fenêtres contextuelles. Merci.

37
Syma

Mise à jour d'octobre 2014:

Il a été noté correctement dans les commentaires que Firefox a déprécié le paramètre synchrone en juin 2014, mais il fonctionne toujours dans ce navigateur.

En outre, Chrome a reçu des mises à jour qui ne permettront que cela fonctionne comme souhaité si l'appel ajax revient en moins d'une seconde. Ce qui est plutôt difficile à garantir. J'ai créé une autre question consacrée à la Chrome timeout: Synchrone Ajax - est-ce que Chrome a un timeout sur les événements de confiance?

Le message lié contient un JSFiddle démontrant ce concept et le problème.

Réponse originale

Réponse courte: rendre la demande ajax synchrone.

Réponse complète: Un navigateur n'ouvrira un onglet/popup sans l'avertissement du bloqueur de popups, si la commande pour ouvrir l'onglet/popup vient d'un événement de confiance . Cela signifie que l'utilisateur doit cliquer activement quelque part pour ouvrir une fenêtre contextuelle.

Dans votre cas, l'utilisateur effectue un clic pour que vous ayez l'événement de confiance. Cependant, vous perdez ce contexte approuvé en exécutant la demande Ajax. Votre gestionnaire de réussite n'a plus cet événement. La seule façon de contourner cela est d'effectuer une requête Ajax synchrone qui bloquera votre navigateur pendant son exécution, mais préservera le contexte de l'événement.

Dans jQuery, cela devrait faire l'affaire:

$.ajax({
 url: 'http://yourserver/',
 data: 'your image',
 success: function(){window.open(someUrl);},
 async: false
});
59

Voici comment j'ai résolu le problème de ma demande ajax asynchrone en perdant le contexte de confiance:

J'ai ouvert le popup directement sur le clic des utilisateurs, dirigé l'url vers about:blank et a obtenu une poignée sur cette fenêtre. Vous pourriez probablement diriger le popup vers une URL de "chargement" pendant que votre demande ajax est faite

var myWindow = window.open("about:blank",'name','height=500,width=550');

Ensuite, lorsque ma demande est acceptée, j'ouvre mon URL de rappel dans la fenêtre

function showWindow(win, url) {
    win.open(url,'name','height=500,width=550');
}
23
wsgeorge

La réponse de wsgeorge est celle qui m'a mis sur la bonne voie. Voici une fonction qui, nous l'espérons, illustre plus clairement la technique.

function openNewAjaxTab(url) {
    var tabOpen = window.open("about:blank", 'newtab'),
        xhr = new XMLHttpRequest();

    xhr.open("GET", '/get_url?url=' + encodeURIComponent(url), true);
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
            tabOpen.location = xhr.responseText;
        }
    }
    xhr.send(null);
}
6
Chris Broski