Làm cách nào để phát hiện nếu trình duyệt chặn cửa sổ bật lên?


130

Thỉnh thoảng, tôi bắt gặp một trang web cố gắng mở một cửa sổ mới (đối với đầu vào của người dùng hoặc một cái gì đó quan trọng), nhưng trình chặn cửa sổ bật lên ngăn chặn điều này xảy ra.

Cửa sổ gọi nào có thể sử dụng phương pháp nào để đảm bảo cửa sổ mới được khởi chạy đúng cách?

Câu trả lời:


160

Nếu bạn sử dụng JavaScript để mở cửa sổ bật lên, bạn có thể sử dụng một cái gì đó như thế này:

var newWin = window.open(url);             

if(!newWin || newWin.closed || typeof newWin.closed=='undefined') 
{ 
    //POPUP BLOCKED
}

Đây là câu trả lời cho chrome: phát hiện-chặn-bật-bật-chrome
ajwaka

@ajwaka bạn có thể vui lòng làm rõ nếu câu trả lời này không thành công cho chrome, hoặc có lý do nào cho câu trả lời khác tốt hơn cho chrome không? cảm ơn!
Crashalot

@ajwaka ít nhất hôm nay mã này dường như hoạt động trên chrome, do đó câu hỏi.
Crashalot

@Crashalot - Bạn đang hỏi tôi về điều gì đó tôi đã trả lời 6 năm trước - tôi buồn thay không còn nhớ lại tình huống và trình duyệt đã đi một chặng đường dài trong 6 năm.
ajwaka

40

Tôi đã thử một số ví dụ ở trên, nhưng tôi không thể làm cho chúng hoạt động với Chrome. Cách tiếp cận đơn giản này dường như hoạt động với Chrome 39, Firefox 34, Safari 5.1.7 và IE 11. Đây là đoạn mã từ thư viện JS của chúng tôi.

openPopUp: function(urlToOpen) {
    var popup_window=window.open(urlToOpen,"myWindow","toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, copyhistory=yes, width=400, height=400");            
    try {
        popup_window.focus();   
    } catch (e) {
        alert("Pop-up Blocker is enabled! Please add this site to your exception list.");
    }
}

1
@Surendra xin vui lòng, bạn có thể chỉ định những gì bạn có nghĩa là "không hoạt động"? Một lỗi tại thời điểm phân tích? Một lỗi trong thời gian chạy? Cửa sổ bật lên mở nhưng nó được đánh dấu là bị chặn? Cửa sổ bật lên bị chặn nhưng nó được đánh dấu là mở? Tôi không thấy bất kỳ lý do nào khiến explorer thất bại điều này, trừ khi việc gọi tiêu điểm () trên NULL được cho phép trong trường hợp đó, một thử nghiệm cho NULL trước khi thử sẽ chỉ hoạt động.
FrancescoMM

IE luôn trả về null, ngay cả khi cửa sổ bật lên thành công.
Devin Garner

34

Cập nhật: Popups tồn tại từ thời cổ đại. Ý tưởng ban đầu là hiển thị một nội dung khác mà không đóng cửa sổ chính. Đến bây giờ, có nhiều cách khác để làm điều đó: JavaScript có thể gửi yêu cầu cho máy chủ, vì vậy cửa sổ bật lên hiếm khi được sử dụng. Nhưng đôi khi chúng vẫn tiện dụng.

Trong quá khứ các trang web ác lạm dụng quảng cáo rất nhiều. Một trang xấu có thể mở hàng tấn cửa sổ bật lên với quảng cáo. Vì vậy, bây giờ hầu hết các trình duyệt cố gắng chặn cửa sổ bật lên và bảo vệ người dùng.

Hầu hết các trình duyệt chặn cửa sổ bật lên nếu chúng được gọi bên ngoài trình xử lý sự kiện do người dùng kích hoạt như onclick.

Nếu bạn nghĩ về nó, đó là một chút khó khăn. Nếu mã trực tiếp trong một trình xử lý onclick, thì điều đó thật dễ dàng. Nhưng cửa sổ bật lên mở trong setTimeout là gì?

Hãy thử mã này:

 // open after 3 seconds
setTimeout(() => window.open('http://google.com'), 3000);

Cửa sổ bật lên mở trong Chrome, nhưng bị chặn trong Firefox.

Và điều này cũng hoạt động trong Firefox:

 // open after 1 seconds
setTimeout(() => window.open('http://google.com'), 1000);

Sự khác biệt là Firefox xử lý thời gian chờ từ 2000ms trở xuống là có thể chấp nhận được, nhưng sau đó - loại bỏ sự tin tưởng của Cameron, giả sử rằng bây giờ, nó nằm ngoài hành động của người dùng. Vì vậy, cái đầu tiên bị chặn, và cái thứ hai thì không.


Câu trả lời ban đầu là năm 2012:

Giải pháp này để kiểm tra trình chặn cửa sổ bật lên đã được thử nghiệm trong FF (v11), Safari (v6), Chrome (v23.0.127.95) & IE (v7 & v9). Cập nhật chức năng displayError để xử lý thông báo lỗi khi bạn thấy phù hợp.

var popupBlockerChecker = {
    check: function(popup_window){
        var scope = this;
        if (popup_window) {
            if(/chrome/.test(navigator.userAgent.toLowerCase())){
                setTimeout(function () {
                    scope.is_popup_blocked(scope, popup_window);
                },200);
            }else{
                popup_window.onload = function () {
                    scope.is_popup_blocked(scope, popup_window);
                };
            }
        } else {
            scope.displayError();
        }
    },
    is_popup_blocked: function(scope, popup_window){
        if ((popup_window.innerHeight > 0)==false){ 
            scope.displayError();
        }
    },
    displayError: function(){
       alert("Popup Blocker is enabled! Please add this site to your exception list.");
    }
};

Sử dụng:

var popup = window.open("http://www.google.ca", '_blank');
popupBlockerChecker.check(popup);

Hi vọng điêu nay co ich! :)


20
Tôi nghĩ rằng bạn cần nhiều dấu gạch dưới hơn
Jacob Stamm

Trong firefox, điều này sẽ hiển thị trang trống và bạn thậm chí không thể nhìn thấy thông báo chặn cửa sổ bật lên trên trang mở. Làm thế nào để đóng trang trống?
dùng460114

Lưu ý rằng nếu url cửa sổ bật lên là một tệp có thể tải xuống (có Content-Disposition: attachment;trong tiêu đề phản hồi), cửa sổ bật lên sẽ đóng ngay lập tức, do đó setTimeoutmã sẽ thất bại và trình duyệt sẽ phàn nàn rằng "Trình chặn Popup được bật!". Đối với Chrome, tôi khuyên dùng giải pháp của @ DanielB và nó hoạt động rất tốt.
wonsuc

1
@wonsuc khi mở một liên kết có Content-Disposition: attachment;tiêu đề bạn không cần mở trong cửa sổ bật lên. Chỉ cần tạo một liên kết trực tiếp đến tài sản mà bạn muốn tải xuống và hành vi gốc của trình duyệt sẽ cho phép bạn tải xuống mà không chuyển hướng bạn ra khỏi trang hiện tại.
Kevin B

@KevinB Tôi phải nói rằng tôi đang ở trong một tình huống cụ thể. Tôi phải tải xuống nhiều tệp đang tạo tệp PDF từ HTML. Và nếu nội dung HTML lớn, đôi khi phải mất vài giây và nếu tôi sử dụng window.locationnó, nếu tệp đầu tiên mất quá nhiều thời gian để tạo, nó sẽ bị bỏ qua khi yêu cầu thứ hai bắt đầu. Đó là lý do tại sao tôi phải sử dụng window.open, vì window.locationkhông bao giờ cho tôi biết khi phản hồi kết thúc.
wonsuc

12

Một "giải pháp" sẽ luôn hoạt động bất kể công ty hay phiên bản trình duyệt là chỉ cần đặt một thông báo cảnh báo trên màn hình, ở đâu đó gần với điều khiển sẽ tạo ra một cửa sổ bật lên, cảnh báo cho người dùng rằng hành động đó yêu cầu một cửa sổ bật lên và để vui lòng kích hoạt chúng cho trang web.

Tôi biết nó không lạ mắt hay gì cả, nhưng nó không thể đơn giản hơn và chỉ cần khoảng 5 phút thử nghiệm, sau đó bạn có thể chuyển sang những cơn ác mộng khác.

Khi người dùng đã cho phép cửa sổ bật lên cho trang web của bạn, nó cũng sẽ được cân nhắc nếu bạn không lạm dụng các cửa sổ bật lên. Điều cuối cùng bạn muốn làm là làm phiền khách truy cập của bạn.


1
Thật không may, đôi khi tất cả các giải pháp khác trong câu hỏi này không được chấp nhận - chỉ có giải pháp này. Tại sao? Bởi vì tất cả đều cố gắng hiển thị cửa sổ bật lên - không chỉ phát hiện nếu cửa sổ bật lên được bật. Nếu tôi muốn làm điều đó một cách im lặng thì sao?
Sagi Mann

Một điều cần nhớ ở đây là người dùng không thể luôn bật quảng cáo cho trang web của bạn. Ví dụ, trong các phiên bản cũ hơn của safari, người dùng chỉ có thể bật hoặc tắt hoàn toàn trình chặn cửa sổ bật lên, không có danh sách trắng.
Jeremy

1

Tôi đã kết hợp các giải pháp của @Kevin B và @ DanielB.
Điều này đơn giản hơn nhiều.

var isPopupBlockerActivated = function(popupWindow) {
    if (popupWindow) {
        if (/chrome/.test(navigator.userAgent.toLowerCase())) {
            try {
                popupWindow.focus();
            } catch (e) {
                return true;
            }
        } else {
            popupWindow.onload = function() {
                return (popupWindow.innerHeight > 0) === false;
            };
        }
    } else {
        return true;
    }
    return false;
};

Sử dụng:

var popup = window.open('https://www.google.com', '_blank');
if (isPopupBlockerActivated(popup)) {
    // Do what you want.
}

1
isPopupBlockerActivated chức năng không bao giờ trở lại return (popupWindow.innerHeight > 0) === false;. Chức năng của bạn trả về false khi trình duyệt của bạn không phải là Chrome. Bởi vì onload là quá trình không đồng bộ. Hàm của bạn trả về false và sau đó onload được thực thi nhưng kết quả của nó không bao giờ trả về.
Onur Gazioğlu

0

Tôi đã thử rất nhiều giải pháp, nhưng giải pháp duy nhất tôi có thể làm được với uBlock Origin, là bằng cách sử dụng thời gian chờ để kiểm tra trạng thái đóng của cửa sổ bật lên.

function popup (url, width, height) {
    const left = (window.screen.width / 2) - (width / 2)
    const top = (window.screen.height / 2) - (height / 2)
    let opener = window.open(url, '', `menubar=no, toolbar=no, status=no, resizable=yes, scrollbars=yes, width=${width},height=${height},top=${top},left=${left}`)

    window.setTimeout(() => {
        if (!opener || opener.closed || typeof opener.closed === 'undefined') {
            console.log('Not allowed...') // Do something here.
        }
    }, 1000)
}

Rõ ràng đây là một hack; giống như tất cả các giải pháp cho vấn đề này.

Bạn cần cung cấp đủ thời gian trong setTimeout của mình để tính đến lần mở và đóng ban đầu, vì vậy nó sẽ không bao giờ chính xác hoàn toàn. Nó sẽ là một vị trí của thử nghiệm và lỗi.

Thêm điều này vào danh sách các nỗ lực của bạn.


0

Một cách tiếp cận đơn giản nếu bạn cũng sở hữu mã con , sẽ tạo một biến đơn giản trong html của nó như sau:

    <script>
        var magicNumber = 49;
    </script>

Và sau đó kiểm tra sự tồn tại của nó từ cha mẹ một cái gì đó tương tự như sau:

    // Create the window with login URL.
    let openedWindow = window.open(URL_HERE);

    // Check this magic number after some time, if it exists then your window exists
    setTimeout(() => {
        if (openedWindow["magicNumber"] !== 32) {
            console.error("Window open was blocked");
        }
    }, 1500);

Chúng tôi chờ một thời gian để đảm bảo rằng trang web đã được tải và kiểm tra sự tồn tại của nó. Rõ ràng, nếu cửa sổ không tải sau 1500ms thì biến vẫn là undefined.


-1

Bằng cách sử dụng sự kiện onb Beforeunload, chúng tôi có thể kiểm tra như sau

    function popup()
    {
        var chk=false;
        var win1=window.open();
        win1.onbeforeunload=()=>{
            var win2=window.open();
            win2.onbeforeunload=()=>{
                chk=true;
            };
        win2.close();
        };
        win1.close();
        return chk;
    }

Nó sẽ mở 2 cửa sổ màu đen trong nền

hàm trả về giá trị boolean.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.