web-dev-qa-db-de.com

Popup-Blocker in window.open umgehen, wenn JQuery event.preventDefault () gesetzt ist

Ich möchte ein JQuery-Dialogfeld abhängig vom Klickereignis eines Hyperlinks anzeigen.

Ich habe eine Anforderung, wie bei Bedingung1 ein JQuery-Dialogfeld geöffnet. Wenn Bedingung1 nicht erfüllt ist, navigieren Sie zu der Seite, auf die durch das 'href'-Tag verwiesen wird, dessen Klickereignis in Frage steht.

Ich kann eine Funktion beim Klickereignis eines Links aufrufen. Diese Funktion überprüft nun die besagte Bedingung, indem sie eine andere URL ausführt (die meinen Spring-Controller ausführt und eine Antwort zurückgibt).

Alles funktioniert perfekt, wenn nur window.open vom Popup-Blocker blockiert wird.

$('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);
        }
    });
});

Wenn ich e.preventDefault(); aus dem Code entferne, blockiert der Popoup-Blocker die Seite nicht. Bei condition1 wird jedoch der Dialog sowie die 'href'-Seite geöffnet.

Wenn ich eines löse, entsteht ein Problem für ein anderes. Ich kann nicht gleichzeitig beiden Bedingungen gerecht werden.

Könnten Sie mir bitte helfen, dieses Problem zu lösen?

Sobald dies gelöst ist, muss ich ein anderes Problem lösen, d.

93
mavaze

Popup-Blocker erlauben window.open normalerweise nur, wenn während die Verarbeitung eines Benutzerereignisses (wie ein Klick) verwendet wird. In Ihrem Fall rufen Sie window.openlater auf, nicht während des Ereignisses, da $.getJSON asynchron ist.

Sie haben zwei Möglichkeiten:

  1. Tun Sie etwas anderes als window.open.

  2. Machen Sie den Ajax-Aufruf synchron, was Sie normalerweise wie die Seuche vermeiden sollten, da die Benutzeroberfläche des Browsers blockiert wird. $.getJSON entspricht:

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

    ... und so können Sie Ihren $.getJSON-Anruf synchronisieren, indem Sie Ihre Parameter den obigen Anweisungen zuordnen und async: false hinzufügen:

    $.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);
            }
        }
    });
    

    Ich befürworte auch keine synchronen Ajax-Aufrufe, wenn Sie einen anderen Weg finden, um Ihr Ziel zu erreichen. Aber wenn du nicht kannst, dann gehst du hin.

    Hier ein Beispiel für Code, bei dem der Test aufgrund des asynchronen Aufrufs fehlschlägt:

    Live-Beispiel | Live-Quelle (Die Live-Links funktionieren aufgrund von Änderungen an JSBin nicht mehr.)

    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");
        });
      });
    });
    

    Und hier ist ein Beispiel, das mit einem synchronen Aufruf funktioniert:

    Live-Beispiel | Live-Quelle (Die Live-Links funktionieren aufgrund von Änderungen an JSBin nicht mehr.)

    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

sie können window.open nur dann aufrufen, wenn der Browser blockiert, wenn der Benutzer direkt eine Aktion ausführt. Der Browser sendet ein Flag und ermittelt, dass das Fenster durch die Benutzeraktion geöffnet wird.

Sie können also dieses Szenario ausprobieren:

  1. var myWindow = window.open ('')
  2. zeichnen Sie eine Lademeldung in diesem Fenster
  3. rufen Sie nach Abschluss der Anforderung einfach myWindow.location = " http://google.com " auf.
59

Ich hatte dieses Problem und ich hatte meine URL nicht bereit, bis der Rückruf einige Daten zurückgab. Die Lösung bestand darin, ein leeres Fenster zu öffnen, bevor der Rückruf gestartet wurde, und dann den Ort festzulegen, wenn der Rückruf zurückkehrt.

$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

probiere das, es funktioniert für mich,

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

Ist Geige für diese http://jsfiddle.net/safeeronline/70kdacL4/1/

17
Mohammed Safeer

Windows muss auf demselben Stack (aka microtask ) wie das vom Benutzer initiierte Ereignis erstellt werden, z. Ein Klick-Rückruf - damit sie später nicht asynchron erstellt werden können.

Sie können jedoch ein Fenster ohne URL erstellen und dann die URL dieses Fensters wenn Sie es wissen auch asynchron ändern!

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);
}

Moderne Browser öffnen das Fenster mit einer leeren Seite (oft als about:blank bezeichnet), und wenn Sie davon ausgehen, dass Ihre async-Task relativ schnell auf die URL zugreifen kann, ist die resultierende UX meistens in Ordnung. Wenn Sie stattdessen eine Lademeldung (oder etwas anderes) in das Fenster rendern möchten, während der Benutzer wartet, können Sie Data URIs verwenden.

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

Dieser Code hilft mir. Hoffe das hilft einigen Leuten

$('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

Versuchen Sie es mit einem einem Link-Element und klicken Sie mit Javascript darauf

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

und das Skript

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

Verwenden Sie es so

//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

Die Beobachtung, dass das Ereignis vom Benutzer initiiert werden musste, half mir dabei, den ersten Teil des Problems herauszufinden, aber auch danach blockierten Chrome und Firefox das neue Fenster. Der zweite Teil war das Hinzufügen von target = "_ blank" zum Link, der in einem Kommentar erwähnt wurde.

Zusammenfassend: Sie müssen window.open über ein vom Benutzer initiiertes Ereignis aufrufen. Klicken Sie in diesem Fall auf einen Link, und dieser Link muss target = "_ blank" haben.

Im folgenden Beispiel verwendet der Link 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

Ich verwende diese Methode, um den Popup-Blocker in meinem React Code zu umgehen. es wird auch in allen anderen Javascript-Codes funktionieren.

Wenn Sie bei einem Klickereignis einen asynchronen Anruf tätigen, öffnen Sie einfach zuerst ein leeres Fenster und schreiben Sie dann die URL in dieses Fenster, wenn ein asynchroner Anruf abgeschlossen wird.

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

wenn der asynchrone Aufruf erfolgreich ist, schreiben Sie Folgendes

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

das hat für mich funktioniert.