Có 3 phương pháp điển hình được sử dụng để xác định xem người dùng có thể xem trang HTML hay không, tuy nhiên không có phương pháp nào hoạt động hoàn hảo:
Các W3C API hiển thị trang là nghĩa vụ phải làm điều này (được hỗ trợ từ: Firefox 10, MSIE 10, Chrome 13). Tuy nhiên, API này chỉ làm tăng các sự kiện khi tab trình duyệt bị quá tải hoàn toàn (ví dụ: khi người dùng thay đổi từ tab này sang tab khác). API không tăng sự kiện khi khả năng hiển thị không thể được xác định với độ chính xác 100% (ví dụ: Alt + Tab để chuyển sang ứng dụng khác).
Sử dụng các phương pháp lấy nét / làm mờ cho bạn rất nhiều kết quả dương tính giả. Ví dụ: nếu người dùng hiển thị một cửa sổ nhỏ hơn ở trên cùng của cửa sổ trình duyệt, cửa sổ trình duyệt sẽ mất tiêu điểm ( onblur
nâng lên) nhưng người dùng vẫn có thể nhìn thấy nó (vì vậy nó vẫn cần được làm mới). Xem thêm http://javascript.info/tutorial/f Focus
- Dựa vào hoạt động của người dùng (di chuyển chuột, nhấp chuột, gõ phím) cũng mang lại cho bạn rất nhiều kết quả dương tính giả. Hãy suy nghĩ về trường hợp tương tự như trên hoặc người dùng đang xem video.
Để cải thiện các hành vi không hoàn hảo được mô tả ở trên, tôi sử dụng kết hợp cả 3 phương pháp: API hiển thị W3C, sau đó lấy nét / làm mờ và phương pháp hoạt động của người dùng để giảm tỷ lệ dương tính giả. Điều này cho phép quản lý các sự kiện sau:
- Thay đổi tab trình duyệt sang một trình duyệt khác (độ chính xác 100%, nhờ API hiển thị trang W3C)
- Trang có khả năng bị ẩn bởi một cửa sổ khác, ví dụ do Alt + Tab (xác suất = không chính xác 100%)
- Sự chú ý của người dùng có khả năng không tập trung vào trang HTML (xác suất = không chính xác 100%)
Đây là cách nó hoạt động: khi tài liệu mất tiêu điểm, hoạt động của người dùng (chẳng hạn như di chuyển chuột) trên tài liệu được theo dõi để xác định xem cửa sổ có hiển thị hay không. Xác suất hiển thị trang tỷ lệ nghịch với thời gian của hoạt động người dùng cuối cùng trên trang: nếu người dùng không thực hiện hoạt động nào trên tài liệu trong một thời gian dài, thì trang này hầu như không hiển thị. Mã bên dưới bắt chước API hiển thị trang của W3C: nó hoạt động theo cùng một cách nhưng có tỷ lệ dương tính giả nhỏ. Nó có lợi thế là đa chức năng (được thử nghiệm trên Firefox 5, Firefox 10, MSIE 9, MSIE 7, Safari 5, Chrome 9).
<div id = "x"> </ div>
<tập lệnh>
/ **
Đăng ký xử lý sự kiện cho đối tượng đã cho.
@param obj đối tượng sẽ nâng cao sự kiện
@param evType loại sự kiện: nhấp, nhấn, di chuột, ...
@param fn chức năng xử lý sự kiện
@param isCapturing đặt chế độ sự kiện (true = chụp sự kiện, false = sự kiện sủi bọt)
@return đúng nếu trình xử lý sự kiện đã được đính kèm chính xác
* /
hàm addEvent (obj, evType, fn, isCapturing) {
if (isCapturing == null) isCapturing = false;
if (obj.addEventListener) {
// Firefox
obj.addEventListener (evType, fn, isCapturing);
trả lại đúng sự thật;
} if if (obj.attachEvent) {
// MSIE
var r = obj.attachEvent ('trên' + evType, fn);
trả lại r;
} khác {
trả lại sai;
}
}
// đăng ký thay đổi khả năng hiển thị trang tiềm năng
addEvent (tài liệu, "tiềm năng trao đổi", hàm (sự kiện) {
document.getEuityById ("x"). InternalHTML + = "entialVisilityChange: tiềm năng = "
});
// đăng ký API hiển thị trang W3C
var ẩn = null;
khả năng hiển thị varChange = null;
if (typeof document.mozHidden! == "không xác định") {
ẩn = "mozHidden";
visualChange = "mozvisibilitychange";
} if if (typeof document.msHidden! == "không xác định") {
ẩn = "msHidden";
mức độ hiển thị = "msvisibilitychange";
} if if (typeof document.webkitHidden! == "không xác định") {
hidden = "webkitHidden";
mức độ hiển thị = "webkitvisibilitychange";
} if if (typeof document.hidden! == "hidden") {
ẩn = "ẩn";
tầm nhìnChange = "khả năng hiển thị";
}
if (hidden! = null && visualChange! = null) {
addEvent (tài liệu, mức độ hiển thị, chức năng (sự kiện) {
document.getEuityById ("x"). InternalHTML + = visualChange + ":" + hidden + "=" + document [hidden] + "<br>";
});
}
varentialPageVisibility = {
pageVisibilityChangeThrưỡng: 3 * 3600, // tính bằng giây
init: function () {
hàm setAsNotHidden () {
var ClarkEventRequired = document.potentialHidden;
tài liệu.potentialHidden = false;
tài liệu.potivelyHiddenSince = 0;
if (ftimeEventRequired) ftimePageVisibilityChangeEvent ();
}
hàm initPotivelyHiddenDetection () {
if (! hasF FocusLocal) {
// cửa sổ không có tiêu điểm => kiểm tra hoạt động của người dùng trong cửa sổ
lastActionDate = ngày mới ();
if (timeoutHandler! = null) {
ClearTimeout (timeoutHandler);
}
timeoutHandler = setTimeout (checkPageVisibility ,entialPageVisibility.pageVisibilityChangeThrưỡng * 1000 + 100); // +100 ms để tránh các vấn đề làm tròn trong Firefox
}
}
hàm ClarkPageVisibilityChangeEvent () {
unifiedVisilityChangeEventDispatch ALLowed = false;
var evt = document.createEvent ("Sự kiện");
evt.initEvent ("tiềm năng trao đổi", đúng, đúng);
document.dispatchEvent (evt);
}
chức năng checkPageVisibility () {
varentialHiddenDuration = (hasF FocusLocal || lastActionDate == null? 0: Math.floor ((ngày mới (). getTime () - lastActionDate.getTime ()) / 1000));
document.potivelyHiddenSince = tiềm năngHiddenDuration;
if (entialHiddenDuration> =entialPageVisibility.pageVisibilityChangeThr Ngưỡng &&! document.potentialHidden) {
// ngưỡng thay đổi mức độ hiển thị trang raiched => tăng mức chẵn
tài liệu.potentialHidden = true;
ClarkPageVisibilityChangeEvent ();
}
}
var lastActionDate = null;
var hasF FocusLocal = true;
var hasMouseOver = true;
tài liệu.potentialHidden = false;
tài liệu.potivelyHiddenSince = 0;
var timeoutHandler = null;
addEvent (tài liệu, "pagehow", hàm (sự kiện) {
document.getEuityById ("x"). InternalHTML + = "Pageshow / doc: <br>";
});
addEvent (tài liệu, "trang da", hàm (sự kiện) {
document.getEuityById ("x"). InternalHTML + = "page leather / doc: <br>";
});
addEvent (cửa sổ, "pagehow", hàm (sự kiện) {
document.getEuityById ("x"). InternalHTML + = "Pageshow / win: <br>"; // được nâng lên khi trang đầu tiên hiển thị
});
addEvent (cửa sổ, "trang da", hàm (sự kiện) {
document.getEuityById ("x"). InternalHTML + = "page leather / win: <br>"; // không được nâng lên
});
addEvent (tài liệu, "mousemove", hàm (sự kiện) {
lastActionDate = ngày mới ();
});
addEvent (tài liệu, "mouseover", hàm (sự kiện) {
hasMouseOver = true;
setAsNotHidden ();
});
addEvent (tài liệu, "mouseout", hàm (sự kiện) {
hasMouseOver = false;
initPotivelyHiddenDetection ();
});
addEvent (cửa sổ, "làm mờ", hàm (sự kiện) {
hasF FocusLocal = false;
initPotivelyHiddenDetection ();
});
addEvent (cửa sổ, "tiêu điểm", hàm (sự kiện) {
hasF FocusLocal = true;
setAsNotHidden ();
});
setAsNotHidden ();
}
}
tiềm năngPageVisibility.pageVisibilityChangeThr Ngưỡng = 4; // 4 giây để thử nghiệm
tiềm năngPageVisibility.init ();
</ script>
Vì hiện tại không có giải pháp trình duyệt chéo nào hoạt động mà không có dương tính giả, tốt hơn bạn nên suy nghĩ kỹ về việc vô hiệu hóa hoạt động định kỳ trên trang web của bạn.
requestAnimationFrame
API hoặc sử dụng tính năng hiện đại mà tần sốsetTimeout
/setInterval
bị giảm khi cửa sổ không hiển thị (ví dụ: 1 giây trong Chrome).