JQuery event.preventDefault () ayarlandığında window.open üzerinde pop-up engelleyiciyi atla


98

Bir köprünün tıklama olayında koşullu olarak bir JQuery iletişim kutusu göstermek istiyorum.

Koşul1'de bir JQuery diyaloğu açın gibi bir gereksinimim var ve koşul1 karşılanmazsa, tıklama etkinliği söz konusu olan 'href' etiketinin referans aldığı sayfaya gidin.

Bağlantının tıklama olayında bir işlevi çağırabiliyorum. Bu işlev şimdi başka bir URL'yi çalıştırarak (Spring denetleyicimi çalıştıran ve yanıtı döndüren) söz konusu koşulu kontrol eder.

Tümü yalnızca window.open, popup engelleyici tarafından engellenerek mükemmel çalışır.

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

e.preventDefault();Koddan kaldırırsam , popoup engelleyici sayfayı engellemez, ancak koşul1 için daha sonra diyaloğu ve 'href' sayfasını açar.

Birini çözersem, diğeri için sorun yaratır. Her iki duruma aynı anda adalet veremiyorum.

Lütfen bu sorunu çözmeme yardım eder misiniz?

Bu çözüldükten sonra çözmem gereken başka bir sorun var, yani diyaloğun OK olayında gezinme :)


1
Kullanımdan kaldırılan .live ve .on () işaretçisi kullanmamaya çalışın!
mas-tasarımlar

@EvilP: Geçen sefer başkalarının da söylediği gibi, sadece 1.7 ve üzeri. Bir sürü projeler hala 1.5 veya 1.6 olacak.
TJ Crowder

10
Olumsuz oy veren: Pop-up'ları sevmediğiniz için, bu soruya olumsuz oy verilmesi gerektiği anlamına gelmez. Bir soru "... herhangi bir araştırma çabası göstermiyorsa; açık değilse veya yararlı değilse" olumsuz oylanmalıdır . Soru açık, tembel görünmüyor ve önemsiz olmayan faktör kombinasyonlarından kaynaklanıyor.
TJ Crowder

@TJCrowder: Hangi sürümü kullandığını belirtmedi. Bu yüzden en son sürümü kullandığını düşünmeliyim. Farklı bir sürüm kullanıyorsa eminim bundan bahsedecektir çünkü BU DURUMDA live'ın kullanımdan kaldırıldığının farkında olacak ve NEDEN .live () kullandığını açıklayacaktır. Hiç kimse bana "son" seferden bahsetmedi, bu yüzden kendinize bir mola verip sakinleşmeniz gerektiğini düşünüyorum. Bu kadar sert olmaya gerek yok ...
mas-tasarımlar

Bununla ilgili herhangi bir bildirim almadım. Ancak, birinin en son sürümü kullandığını düşünmek için kendi sürümünü belirtmemesi normal değil mi? Demek istediğim, 1.3'ü bir nedenle kullanmam gerekiyor ve daha yeni ve daha iyi bir sürümün olduğu gerçeğinin farkındayım.
mas-tasarımlar

Yanıtlar:


144

Pop-up engelleyicileri, genellikle yalnızca bir kullanıcı etkinliğinin işlenmesi sırasında (tıklama gibi) window.openkullanılırsa izin verir . Sizin durumunuzda, etkinlik sırasında değil, daha sonra arayacaksınız çünküwindow.open $.getJSON ararsınız asenkron değildir.

İki seçeneğiniz var:

  1. Bunun yerine başka bir şey yapın window.open.

  2. Ajax çağrısını eşzamanlı yapın, bu normalde tarayıcının kullanıcı arayüzünü kilitlediği için veba gibi kaçınmanız gereken bir şeydir. $.getJSONeşdeğerdir:

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

    ... ve böylece $.getJSONparametrelerinizi yukarıdakilerle eşleştirip şunu ekleyerek aramanızı eşzamanlı yapabilirsiniz 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);
            }
        }
    });

    Yine, hedefinize ulaşmanın başka bir yolunu bulabilirseniz, eşzamanlı ajax çağrılarını savunmuyorum. Ama yapamazsan, oraya gidersin.

    Eşzamansız çağrı nedeniyle testi geçemeyen bir kod örneğini burada bulabilirsiniz:

    Canlı örnek | Canlı kaynak (Canlı bağlantılar artık JSBin'deki değişiklikler nedeniyle çalışmamaktadır)

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

    Ve işte eşzamanlı arama kullanarak işe yarayan bir örnek:

    Canlı örnek | Canlı kaynak (Canlı bağlantılar artık JSBin'deki değişiklikler nedeniyle çalışmamaktadır)

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

3
Milyonlarca kez teşekkürler. Eşzamanlı arama yapma öneriniz bir cazibe gibi çalıştı. Aynı şey, diyalogun OK olayında navigasyonla ilgili olası bir sonraki sayımda bana yardımcı oldu.
mavaze

TJ Crowder 2 soruyu açık bıraktığından, [1. window.open] ve [2. ajax eşzamanlı aramadan kaçının] bu öneriler topluluğun yararına kabul edilir. Aksi takdirde, cevabını söz konusu soru için mükemmel bir çözüm buldum :)
mavaze

4
Benim için, kullanıcıdan tıklamasını istemek için target = "_ blank" içeren bir bağlantı ekledim.
hiroshi

1
@Evan: XHR'yi doğrudan kullanmanız gerekecek. Bilette eşzamanlı isteklerin kullanımdan kaldırılmasına yönelik bir örnek var .
TJ Crowder

2
@mavaze Kontrol akışını önce pencereyi açacak şekilde değiştirebilir, (senkronizasyon), ardından AJax isteğini (zaman uyumsuz) yapıp ardından yanıtı hata mesajını göstermek veya yeniden yönlendirmek için kullanırsanız her iki sorunu da önleyebileceğinizi düşünüyorum.
Stijn de Witt

61

window.open'i tarayıcı engellemesi olmadan yalnızca kullanıcı doğrudan bir eylem yaparsa çağırabilirsiniz. Tarayıcı bazı işaretler gönderir ve bu pencerenin kullanıcı eylemiyle açıldığını belirler.

Yani, bu senaryoyu deneyebilirsiniz:

  1. var myWindow = window.open ('')
  2. bu pencerede herhangi bir yükleme mesajı çizin
  3. istek yapıldığında, myWindow.location = ' http://google.com ' çağrısı yapmanız yeterlidir

2
Bu, Safari Mobile'da çalışmaz (IPhone 4'te test edilmiştir). Diğer birkaç fikri denedim (örneğin myWindow.postMessage), ancak Safari'nin arka planda JavaScript çalıştırmama kısıtlaması nedeniyle, ana pencere bu konum değişikliğini asla gönderemez.
roundrobin

@BausTheBig IPhone 6, IOS8'de test ettim. Büyüleyici çalıştı.
lvarayut

pop-up engellenmeden Google Analytics ile harici bağlantıları izlemenin bir yolunu arıyordu. Bu tam olarak ihtiyacım olan şeydi. İOS7'de (gerçek telefon) ve iOS 8'de (iOS Simülatörü) iPhone 4'lerde iyi çalışıyor gibi görünüyor.
notacouch

37

Bu sorunu yaşadım ve geri arama bazı veriler döndürene kadar url'im hazır değildi. Çözüm, geri aramayı başlatmadan önce boş bir pencere açmak ve ardından geri arama döndüğünde konumu belirlemekti.

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

1
Bu çözümü yeni bir pencere açmak ve açılır pencere engelleyiciyi atlamak için kullandım
VeldMuijz

Bir açılır pencereyi açmam gerekip gerekmediğini önceden bilmiyorsam ne olur? Olduğu gibi: action().then(doWindowOpenThing).catch(doSomethingElseThatDoesntOpenAPopup) Yani daha sonra kullanmayacaksam, elden önce bir pencere açamam (referansını korumak için vb.), Değil mi?
Luiz

Hayır, her seferinde yeni bir sekme açar ve kullanmadığınız durumda bunu istemezsiniz sanırım. Sorun şu ki, tarayıcı yalnızca tıklama işlevinde (kullanıcı tarafından başlatılan eylem) yeni bir sekme açmanıza izin verecek, aksi takdirde açılır pencere engelleyicisi bunu kullanıcı izni olmadan yeni sekme açan bir komut dosyası olarak görecek ve engelleyecektir.
KnuturO

Lütfen newWin'in boş olup olmadığını test edin!
FrancescoMM

Neden ? Bunun için bir sebep göremiyorum.
KnuturO

18

bunu dene, benim için çalışıyor

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

Bu http://jsfiddle.net/safeeronline/70kdacL4/1/ için keman mı?


1
Teşekkürler, benim için de çalıştı - bu keman için olmasaydı muhtemelen inanmazdım, lol!
rmcsharry

3
Kabul edilen cevap bu olmalı! Url'yi oluşturmak için eşzamansız verilere ihtiyacınız varsa redirectWindow.location.assign ('new_url') de kullanabilirsiniz.
matheusr

Güzel çözüm.
Devam

Lütfen, redirectWindow'un boş olup olmadığını test edin! Farklı tarayıcı seçeneklerine göre engellenebilir veya engellenemezsiniz.
FrancescoMM

8

Windows , kullanıcı tarafından başlatılan olay ile aynı yığın üzerinde (diğer adıyla mikro görev ) oluşturulmalıdır , örneğin tıklama geri araması - böylece daha sonra eşzamansız olarak oluşturulamazlar.

Bununla birlikte, URL'siz bir pencere oluşturabilir ve daha sonra , eşzamansız olsa bile, bu pencerenin URL'sini öğrendikten sonra değiştirebilirsiniz !

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

Modern tarayıcılar pencereyi boş bir sayfayla açar (genellikle denir about:blank) ve URL'yi almak için eşzamansız görevinizin oldukça hızlı olduğunu varsayarsak, ortaya çıkan UX çoğunlukla iyidir. Bunun yerine, kullanıcı beklerken pencereye bir yükleme mesajı (veya herhangi bir şey) oluşturmak istiyorsanız, Veri URI'larını kullanabilirsiniz .

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

3

Bu kod bana yardımcı oluyor. Umarım bu bazı insanlara yardımcı olur

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

Bir bağlantı öğesi kullanmayı deneyin ve javascriipt ile tıklayın

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

ve senaryo

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

Bunu böyle kullan

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

Bu benim için boş pencereyle uğraşmaktan kaçındı.
ponder275

Bunun, iPhone'un penceremi pop-up olarak engellemesi ile ilgili sorunumu çözmediği ortaya çıktı.
ponder275

2

Olayın kullanıcı tarafından başlatılması gerektiği gözlemi, bunun ilk bölümünü anlamama yardımcı oldu, ancak bundan sonra bile Chrome ve Firefox yeni pencereyi engelledi. İkinci kısım, bir yorumda bahsedilen bağlantıya target = "_ blank" ekliyordu.

Özetle: kullanıcı tarafından başlatılan bir olaydan window.open'ı çağırmanız gerekir, bu durumda bir bağlantıya tıklarsınız ve bu bağlantının target = "_ blank" olması gerekir.

Aşağıdaki örnekte bağlantı class = "button-twitter" kullanıyor.

$('.button-twitter').click(function(e) {
  e.preventDefault();
  var href = $(this).attr('href');
  var tweet_popup = window.open(href, 'tweet_popup', 'width=500,height=300');
});


1

React kodumdaki açılır pencere engelleyiciden kaçınmak için bu yöntemi kullanıyorum. diğer tüm javascript kodlarında da çalışacaktır.

Tıklama olayında eşzamansız bir çağrı yaptığınızda, önce boş bir pencere açın ve daha sonra eşzamansız bir çağrı tamamlandığında URL'yi buraya yazın.

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

eşzamansız çağrının başarısı üzerine aşağıdakileri yazın

popupWindow.document.write(resonse.url)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.