Tarayıcı açılır pencere engelleyicilerinden kaçının


172

Tamamen JavaScript'te bir OAuth kimlik doğrulama akışı geliştiriyorum ve kullanıcıya bir açılır pencerede "erişim izni ver" penceresini göstermek istiyorum, ancak engelleniyor.

Nasıl yoluyla oluşturulan pencereler açılır önleyebilir window.openveya window.showModalDialogfarklı tarayıcılarda Pop-up engelleyicileri tarafından bloke edilmesinin?


11
Mümkün olsa bile (bilmiyorum), insanlar pop-up engelleyicileri kullanıyorsa buna saygı duymalısınız. Çoğu tarayıcı, bir site bir açılır pencere açmaya çalıştığında bir ileti görüntüler, böylece isterse yine de görebilir. Sitenize bazı içeriğin bir açılır pencerede açıldığını ve kullanıcının devam edebilmesi için izin vermesi gerektiğini belirtebilirsiniz.
Felix Kling

5
En iyi uygulama şöyle görünecektir: 1) Bunu başarılı bir şekilde yapın 2) Pencerelerinizi kapatın ve üzgün web patronlarının bir araya geldiği kalabalığın korkusuyla kapınızı ve korkunuzu engelleyin 3) Tövbe edin, pop-up-busta-busta'yı kaldırın ve saygı gösterin kitleniz.
Alex Mcp

Alex ve Felix, soruyu güncelledim. Bilgiyi kötülük için kullanmayacağım :). Teşekkürler!
Pablo Fernandez

9
Bir pop-up engelleyiciyi atlamanın aslında kullanıcı deneyimini daha iyi hale getirmeye çalıştığını eklemek istiyorum. Şimdi üzerinde çalıştığım bir örnekte, bir Javascript uygulaması (ExtJS tabanlı) kullanıyoruz ve kullanıcıların paypal kullanarak ödeme yapmasına izin vermeye çalışıyoruz. Onlara yeni bir pencerede paypal'ı başlatmak için tıklatabilecekleri bir düğme veriyoruz, ancak IE'nin belirli sürümleri bir pop-up olarak engelliyor (bir düğme tıklaması olmasına rağmen). Artık pop-up'ı etkinleştirirlerse, ekran yeniden yüklenir ve bir JavaScript uygulaması olarak pencere durumunu kaybederiz ve baştan başlamaları gerekir. Yani gerçekten: problem IE'nin aptal olması.
NateDSaint

1
@FelixKling Evet bu mümkün. Tarayıcı üreticileri bunu zaten düşündü. Bir pop-up açmak kullanıcı amacı olduğu sürece sorun olmaz (kullanıcı bir bağlantıyı veya düğmeyi tıklatarak sinyal verir). Açılır pencere engelleyicileri kullanıcının amacına saygı göstermelidir. IE'nin pop-up engelleyicisi çalışmıyorsa, hatalı olan pop-up engelleyicisi. Kullanıcılar, kendileri açmaya çalıştıkları pop-up'ları engellemek için değil, komut dosyalarının açılır pencereleri açmasını önlemek için açılır pencere engelleyicileri kullanır (bir düğmeyi veya bağlantıyı tıklayarak).
Stijn de Witt

Yanıtlar:


286

Genel kural, doğrudan kullanıcı eylemiwindow.open tarafından çağrılmayan javascript'ten çağrılırsa veya benzeri bir durumda açılır pencere engelleyicilerin devreye girmesidir . Yani, pop-up engelleyici tarafından vurulmadan bir düğme tıklamasına yanıt olarak çağırabilirsiniz , ancak aynı kodu bir zamanlayıcı etkinliğine koyarsanız engellenir. Çağrı zincirinin derinliği de bir faktördür - bazı eski tarayıcılar sadece anında arayan kişiye bakar, yeni tarayıcılar arayanın arayan kişinin fare tıklaması vb. Olup olmadığını görmek için biraz geriye doğru hareket edebilir.window.open


2
İlginç bir şekilde, bir seçili öğeye bağlı bir değişiklik olayı aracılığıyla başlatılan pop-up'lar, o olay bir tıklama gibi doğrudan kullanıcı işlemi tarafından başlatılsa bile (Chrome'da FF değil) engellenir. Bir girdiye bağlı olsalar da, bunlara izin verilir. Garip.
ccnokes

6
Kimse tarayıcının tutarlı olduğunu söylemedi. : P
dthorpe

8
Deneyler sayesinde yığın derinliğinin pop-up engelleyici ile bir ilgisi olmadığını anlamalıyım. Aslında window.open öğesinin kullanıcı işleminden sonraki 1 saniye içinde çağrılıp çağrılmadığını denetler. Chrome 46 ve Firefox 42'de test edildi.
Mesqalito

1 saniyelik zaman aşımı her iki tarayıcıda da atlanabilir, bu sayfadaki @ tj-crowder'ın cevabını kullanarak belirsiz bir süre izin verir .. ajax aracılığıyla aradığınız URL'nin uyku kullanan bazı php (veya her neyse) olması ( ) yanıt vermeden önce belirli bir süre için. Tarayıcı, sayfayı 'yüklerken' askıda kalır. Ardından bir yanıt aldığında açılır pencereyi tetikler. Bununla birlikte, Chrome'da, bu hilenin çalışması için ajax'tan () hemen önce bir alert () eklemeniz gerekir.
fanfare

184

Dayanarak Jason Sebring 's çok yararlı ipucu ve şeyler üzerinde örtülü burada ve orada , benim durum için mükemmel bir çözüm bulundu:

Javascript snippet'leri ile sözde kod:

  1. kullanıcı işleminde hemen boş bir açılır pencere oluşturun

    var importantStuff = window.open('', '_blank');

    İsteğe bağlı: "bekleyen" bilgi mesajı ekleyin. Örnekler:

    a) Harici bir HTML sayfası: yukarıdaki satırı

    var importantStuff = window.open('http://example.com/waiting.html', '_blank');

    b) Metin: yukarıdakinin altına aşağıdaki satırı ekleyin:

    importantStuff.document.write('Loading preview...');
  2. hazır olduğunda içerikle doldur (örneğin AJAX çağrısı döndüğünde)

    importantStuff.location.href = 'http://shrib.com';

Çağrıyı ihtiyacınız window.openolan diğer seçeneklerle zenginleştirin .

Aslında bu çözümü bir mailto yönlendirmesi için kullanıyorum ve tüm tarayıcılarımda çalışıyor (Windows 7, Android). _blankBiraz btw mobil çalışma için mailto yönlendirme için yardımcı olur.

Deneyiminiz? Bunu geliştirmenin bir yolu var mı?


1
? tarayıcıdaki kullanıcı işleminden değilse ne yaparsınız? Örneğim için, kullanıcı sunucuya karşı kimlik doğrulaması yaptıktan sonra yeni bir sekme
Don Cheadle

@mmcrae bunu yapma. Ne yaparsanız yapın, bir açılır pencereden daha iyi bir yol var. Aksi takdirde, sitenizi asla görmek istemeyeceğim. Bugünün tarayıcıları bunu yapmamanız gerektiğinden emin oluyor - @dthorpe'un cevabına bakın .
İsviçre

5
Whatever it is you intend to do, there is a better way than a popup windowlol? Garip genelleme. Müşteri, kimlik doğrulaması yaptıkları sayfanın açık kalmasını ve kimlik doğrulamasından sonra yeni site / açılış sayfasının yeni bir sekmede açılmasını istiyor. Evet, mükemmel kullanıcı deneyimi fikrimi değil ... ama makul görünüyor
Don Cheadle

@mmcrae. Otur ve düşün, cidden. Açıkladığınız senaryoda bir "kullanıcı eylemi" bulacaksınız. Cevabımın asıl amacı , kullanıcı eylemi yaptığınızda açılan pencereyi oluşturmanız ve daha sonra onu içerikle doldurmanızdır. Durumunuz için ipucu: kullanıcı "kimlik doğrulaması" yapar -> açılır pencereyi oluştur (boş); zamanlayıcı açık veya sunucu yanıtı geri döndü ya da her neyse -> içeriği açılır pencereye doldurun.
İsviçre

3
Kullanışlı ipucu, ajax isteği başarısız olursa, importantStuff.closeyeni sekmeyi kapatmak için arayın ve orijinal sayfada uyarı verin.
Goose

24

Buna ek olarak, Swiss Mister yazı, benim durumumda window.open , bir açılır pencere engelleyiciyi açan bir sözün içinde başlatıldı, benim çözümüm: açısal olarak:

$scope.gotClick = function(){

  var myNewTab = browserService.openNewTab();
  someService.getUrl().then(
    function(res){
        browserService.updateTabLocation(res.url, myNewTab);

    }
  );
};

browserService:

this.openNewTab = function(){
     var newTabWindow = $window.open();
     return newTabWindow;
}

this.updateTabLocation = function(tabLocation, tab) {
     if(!tabLocation){
       tab.close();
     }
     tab.location.href = tabLocation;
}

bu, söz verilen yanıtı kullanarak ve açılır pencere engelleyiciyi çağırmadan yeni bir sekme açabilirsiniz.


1
Bu benim çözümüme yol açtı! Burada, açılan sekmeyi içeren bir değişken oluşturdum ve sonra veri yüklendikten sonra URL'yi doldurdum. Teşekkürler. const tab = window.open(); observable.subscribe(dataUrl => tab.location.href = dataUrl);
jonas

1
Pop-up engelleyiciyi etkinleştirdiyseniz, bu, pop-up engelleyiciyle ilgili sorunu çözmez ...
Alejandro Vales

@Alejandro Vales jonas çözümü yalnızca kod bir onClick olayından veya herhangi bir kullanıcı etkileşiminden çalıştırılacaksa çalışır. Windows.open'de bir vaat, zaman aşımı, abone olun ... aracılığıyla yeni bir sekme açmaya çalıştığınızda tarayıcı bunun bir manipülasyon olduğunu düşünür, bu yüzden çözüm vaadi girmeden önce bir örnek oluşturmaktır jonas gibi href yaptı
David

@David Çok teşekkür ederim !!! .thenO zaman cevap göremedim ve bu yüzden kafam karıştı: / SRY ...
Alejandro Vales

@David Bu harika! Tıkır tıkır çalışıyor. Seni sadece bir soru ile daha rahatsız edebilirsem, bunun Edge'de nasıl çalışacağını biliyor musun? Doğru bir kaynağa doğru bir
dürtü

21

İyi bir uygulama olarak, bir pop-up'ın engellenip engellenmediğini test etmek ve harekete geçmek iyi bir fikirdir . Window.open öğesinin bir dönüş değeri olduğunu ve işlem başarısız olursa bu değerin boş olabileceğini bilmeniz gerekir. Örneğin, aşağıdaki kodda:

function pop(url,w,h) {
    n=window.open(url,'_blank','toolbar=0,location=0,directories=0,status=1,menubar=0,titlebar=0,scrollbars=1,resizable=1,width='+w+',height='+h);
    if(n==null) {
        return true;
    }
    return false;
}

açılır pencere engellenirse, window.open null değerini döndürür. Böylece işlev false değerini döndürür.

Örnek olarak, bu işlevi doğrudan herhangi bir bağlantıdan aradığınızı düşünün target="_blank": açılır pencere başarıyla açılırsa, döndürmek falsebağlantı eylemini engelleyecektir, aksi takdirde açılır pencere engellenirse, döndürmek truevarsayılan davranışa (yeni _blank penceresi aç) izin verir ve devam eder .

<a href="http://whatever.com" target="_blank" onclick='return pop("http://whatever.com",300,200);' >

Bu şekilde, eğer çalışırsa bir pop-up penceresi ve eğer değilse bir _blank penceresi olacaktır.

Açılır pencere açılmazsa şunları yapabilirsiniz:

  • örnekteki gibi boş bir pencere açın ve devam edin
  • sahte bir açılır pencere açın (sayfanın içinde bir iç çerçeve)
  • kullanıcıyı bilgilendirin ("lütfen bu site için açılır pencerelere izin verin")
  • boş bir pencere açın ve sonra kullanıcıyı bilgilendirin vb.

Teşekkür ederim. Yaradı!
Bcktr

8

Google'ın oauth JavaScript API'sından:

http://code.google.com/p/google-api-javascript-client/wiki/Authentication

Okuduğu bölgeye bakın:

Kimlik Doğrulamayı Ayarlama

İstemcinin OAuth 2.0 uygulaması, kullanıcıdan oturum açmasını ve uygulamayı onaylamasını istemek için bir açılır pencere kullanır. Gapi.auth.authorize'a ilk çağrı, açılır pencereyi dolaylı olarak açtığından açılır pencere engelleyicilerini tetikleyebilir. Açılır pencere engelleyicisinin kimlik doğrulama çağrılarını tetiklemesini önlemek için, istemci yüklendiğinde gapi.auth.init (geri arama) öğesini arayın. Kitaplık kimlik doğrulama çağrıları yapmaya hazır olduğunda, sağlanan geri arama yürütülür.

Ben acil bir tepki varsa nasıl açıklar yukarıdaki açıklar ile ilgili, sanırım açılır alarmı trip olmaz. "Gapi.auth.init", API'nin hemen gerçekleşmesini sağlıyor.

Pratik uygulama

Ben npm üzerinde düğüm pasaportu ve her sağlayıcı için çeşitli pasaport paketleri kullanarak bir açık kaynak kimlik doğrulama mikro hizmet yaptı. 3. tarafa standart bir yönlendirme yaklaşımı kullandım ve geri gelmek için bir yönlendirme URL'si verdim. Bu programlı oldu, bu yüzden giriş / kayıt ve belirli sayfalarda yeniden yönlendirmek için farklı yerler olabilir.

github.com/sebringj/athu

passportjs.org


3

Birden fazla çözüm denedim, ancak tüm tarayıcılarda benim için çalışan tek çözüm bu

let newTab = window.open(); newTab.location.href = url;


2
Bu, pop-up engelleyiciyi etkinleştiren kişiler için işe yaramaz
Alejandro Vales

nedir url? atanmamış.
shinriyo

@shinriyo url, erişmek istediğiniz herhangi bir sayfanın bağlantısıdır, örneğinhttp://example.com
pomobc

@AlejandroVales ben açılır pencere engelleyicisi etkin ve çalışır. Sorun şu ki window.open(), yeni pencereyi programsal olarak açamıyor ve eğer ihtiyacımız olursa, bu seçenek seçeneklerden biri. İle newTabdeğişken biz bazı göndermeler yapan window.open()ve daha sonra biz insert, diyebilirsiniz urlbazı blob'un benim vaka url, biz muhtaç ve yeni sekme girilen url üzerinde birlikte açılacak.
stanimirsp

0

Geri arama başarıyla geri dönmediği sürece yeni sayfayı yapmak istemedim, bu yüzden kullanıcı tıklamasını simüle etmek için bunu yaptım :

function submitAndRedirect {
  apiCall.then(({ redirect }) => {
      const a = document.createElement('a');
      a.href = redirect;
      a.target = '_blank';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
  });
}

3
Chrome 62'de benim için çalışmıyor. Açılır pencere (sayfa) engellenir.
s.ermakovich

1
Evet haklısın - bunun tutarsız olduğunu da buldum. Api aramamı senkronize hale
getirdim

-8

Bundan kurtulmanın en kolay yolu:

  1. Document.open () öğesini kullanmayın.
  2. Bunun yerine this.document.location.href = location; yüklenecek URL nerede

Örn:

<script>
function loadUrl(location)
{
this.document.location.href = location;
}</script>

<div onclick="loadUrl('company_page.jsp')">Abc</div>

Bu benim için çok işe yaradı. Şerefe


2
URL'yi yeni sekmede açmaya ne dersiniz?
3 kural
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.