Làm cách nào để phát hiện khi một tab được lấy tiêu điểm hoặc không được đặt tiêu điểm trong Chrome bằng Javascript?


75

Tôi cần biết người dùng hiện có đang xem một tab hay không trong Google Chrome. Tôi đã cố gắng sử dụng các sự kiện làm mờ và tiêu điểm liên kết với cửa sổ, nhưng chỉ làm mờ dường như hoạt động chính xác.

window.addEventListener('focus', function() {
  document.title = 'focused';
});

window.addEventListener('blur', function() {
  document.title = 'not focused';
});

Sự kiện tiêu điểm hoạt động kỳ lạ, chỉ đôi khi. Nếu tôi chuyển sang tab khác và quay lại, sự kiện tiêu điểm sẽ không kích hoạt. Nhưng nếu tôi nhấp vào thanh địa chỉ và sau đó quay lại trang, nó sẽ xảy ra. Hoặc nếu tôi chuyển sang một chương trình khác và sau đó quay lại Chrome, nó sẽ kích hoạt nếu tab hiện được lấy tiêu điểm.


Bạn đã cố gắng đính kèm các sự kiện đó với docmentthay vì window?
Crozin

Tôi không chắc liệu nó có ảnh hưởng đến việc phát hiện sự kiện hay không, nhưng window.focushành động đã bị vô hiệu hóa (hoặc ít nhất là có lỗi) trong Chrome. Xem ở đâyở đây để biết thêm.
brahn

Cũng không hoạt động với tài liệu và điều này dành cho sự kiện tiêu điểm, không phải hành động tiêu điểm. Tôi nghĩ rằng tôi sẽ thay đổi cách tiếp cận của mình đối với điều này và thay đổi sự kiện thành di chuột qua hoặc cuộn cửa sổ. Đối với kịch bản này, nó thích hợp.
Fent

Mã bạn trong câu hỏi hoạt động hoàn hảo trong Chrome kể từ năm 2011. Giải pháp không hoạt động.
ninjagecko

Câu trả lời:


131

Cập nhật năm 2015: Cách thức HTML5 mới với API khả năng hiển thị (lấy từ nhận xét của Blowsie):

document.addEventListener('visibilitychange', function(){
    document.title = document.hidden; // change tab text for demo
})

Mã mà người đăng ban đầu cung cấp (trong câu hỏi) hiện đã hoạt động, kể từ năm 2011:

window.addEventListener('focus', function() {
    document.title = 'focused';
});

window.addEventListener('blur', function() {
    document.title = 'not focused';
});

chỉnh sửa : Kể từ vài tháng sau trong Chrome 14, điều này sẽ vẫn hoạt động, nhưng người dùng phải tương tác với trang bằng cách nhấp vào bất kỳ đâu trong cửa sổ ít nhất một lần. Chỉ cuộn và như vậy là không đủ để làm cho việc này hoạt động. Việc làm window.focus()này cũng không làm cho việc này tự động hoạt động. Nếu có ai biết về cách giải quyết khác, vui lòng đề cập.


1
Cách để điều này hoạt động mà không cần người dùng phải nhấp vào đâu đó trước tiên là thêm "window.focus ()" vào sự kiện window.onload. Tác dụng phụ của việc này là nếu cửa sổ là mục tiêu của một liên kết và đã được mở phía sau cửa sổ hiện tại, nó sẽ được đưa lên phía trước. Lưu ý rằng giải pháp này chỉ phát hiện mất tiêu điểm chứ không phải do chuyển đổi tab. Ví dụ: nếu mất tiêu điểm là do người dùng nhấp vào bên trong iframe, bạn phải loại bỏ điều đó:
SPitBalls.com

<iframe ... onmouseover = "iframeMouse (true)" onmouseout = "iframeMouse (false)"> </iframe>
SPitBalls.com

function iframeMouse (over) {oif = over; } window.addEventListener ('dim', function () {document.title = oif? "iframe focus": "not focus";});
SPitBalls.com

5
Để có câu trả lời sâu sắc hơn, hãy xem phần này. Forum.greensock.com/topic/…
Blowsie

2
Sử dụng document.visibilityStateđể có trạng thái hiển thị hiện tại
Oleg


2

Rốt cuộc thì nó có thể hoạt động, tôi đã tò mò và viết mã này:

...
setInterval ( updateSize, 500 );
function updateSize(){
  if(window.outerHeight == window.innerHeight){
    document.title = 'not focused';             
  } else {
    document.title = 'focused';
  }

  document.getElementById("arthur").innerHTML = window.outerHeight + " - " + window.innerHeight;
}
...
<div id="arthur">
  dent
</div>

Mã này thực hiện chính xác những gì bạn muốn, nhưng theo một cách xấu xí. Có điều, Chrome dường như bỏ qua việc thay đổi tiêu đề theo thời gian (khi chuyển sang tab và giữ chuột trong 1 giây dường như luôn tạo ra hiệu ứng này).

Bạn sẽ nhận được các giá trị khác nhau trên màn hình của mình, nhưng tiêu đề của bạn sẽ không thay đổi.

kết luận: Dù bạn đang làm gì, đừng tin tưởng vào kết quả khi kiểm tra nó!


Tiêu đề thay đổi ngay lập tức cho tôi. Nếu tôi thay đổi các sự kiện thành di chuột qua và di chuột ra, tôi sẽ nhận được kết quả tức thì.
Fent

Dù sao, cảm ơn vì phần (window.outerHeight == window.innerHeight). Đối với dự án cụ thể này, tôi chỉ cần biết người dùng hiện đang tập trung hay không. Không cần phải liên tục kiểm tra và mã của bạn hoạt động.
Fent

2

Đối với bất kỳ ai muốn hoán đổi tiêu đề trang khi làm mờ và sau đó quay lại tiêu đề trang ban đầu trên tiêu điểm:

// Swapping page titles on blur
var originalPageTitle = document.title;

window.addEventListener('blur', function(){
    document.title = 'Don\'t forget to read this...';
});

window.addEventListener('focus', function(){
    document.title = originalPageTitle;
});

0

Tôi thấy rằng việc thêm các sự kiện onblur = và onfocus = vào nội tuyến đã bỏ qua vấn đề:


0

Điều này có thể hoạt động với JQuery

$(function() {
    $(window).focus(function() {
        console.log('Focus');
    });

    $(window).blur(function() {
        console.log('Blur');
    });
});

Tôi nghĩ rằng điều này sẽ không hữu ích vì như anh ấy đã báo cáo trình duyệt KHÔNG kích hoạt chức năng sự kiện mà bạn đã đính kèm trong 'mờ'. Vì vậy, như trong ví dụ của bạn và mã console.log('Blur');sẽ KHÔNG được gọi trong một số tình huống.
psulek

-2

Trong chrome, bạn có thể chạy tập lệnh nền với thời gian chờ dưới 1 giây và khi tab không có tiêu điểm, chrome sẽ chỉ chạy nó mỗi giây. Thí dụ;

Điều này không hoạt động trong Firefox hoặc Opera. Không biết về các trình duyệt khác, nhưng tôi nghi ngờ nó cũng hoạt động ở đó.

var currentDate = new Date();
var a = currentDate.getTime();

function test() {
    var currentDate = new Date();
    var b = currentDate.getTime();
var c = b - a;
    if (c > 900) {
        //Tab does not have focus.
    } else {
        //It does
    }
    a = b;
    setTimeout("test()",800);
}



setTimeout("test()",1);

2
Tôi không thích ý tưởng sử dụng các khoảng thời gian cho một thứ gì đó nên xảy ra. Và lưu ý, bạn nên sử dụng setTimeout(test, 800). Nếu bạn cung cấp cho nó một chuỗi, nó sẽ eval()nó, nó sẽ chậm hơn nhiều.
2012
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.