對於WebIM 對話或其它各種Comet應用場景,當收到新消息時,希望能夠及時提醒用戶。
但是用戶可能將窗口切換到計算機上其它窗口上了,比如看其它網頁、聊一下QQ、收發一下郵件等各種其它事情,此時web窗口就不在用戶焦點上了,收到的新消息時很可能看不到。而javascript控制的web窗口並不能很好融入到OS級別的窗口系統中。比較普遍的一種做法就是讓瀏覽器標題欄不斷閃爍,應用程序的標題閃爍是很容易被注意到的,不管是瀏覽器和其它各種程序之間,還是瀏覽器多tab或windows之間。這算是最接近OS級別窗口的提示方式了。
實現的目標:
- 當對話窗口失去焦點(切換到其它程序或其它瀏覽器窗口),並且收到新消息時,標題欄閃爍。
- 沒有失去焦點時不閃爍提示。焦點重新回到窗口時,標題欄恢復正常不再閃爍。
一、標題欄的閃爍
要實現標題欄閃爍的效果很簡單,只要
讓 title 的內容來回變化就可以。
比如每500ms,
document.title=“【您有新的消息】”
下次
document.title=“【 】”
這樣來回變化就實現了閃爍效果。
二、瀏覽器窗口焦點的判斷
根據目標的要求,首先要知道當前窗口激活狀態。
注冊window.onblur和window.onfocus函數來記錄焦點變化,但是IE上的行為有差異,不能直接用,而應該用document.onfocusin和document.onfocusout。
關於window或Dom元素的focus焦點這方面的行為,各瀏覽器行為有差異,尤其IE的行為有很多bug。
//當前瀏覽器窗口是否處於焦點
var isWindowFocus = true;
function focusin() { isWindowFocus=true;}
function focusout() { isWindowFocus=false;}
//注冊焦點變化監聽器
if ("onfocusin" in document){//for IE
document.onfocusin = focusin;
document.onfocusout = focusout;
} else {
window.onblur = focusout;
window.onfocus= focusin;
}
三、具體實現
使用方式:每當收到新消息時就調用 doFlashTitle 方法實現閃爍,調用者不做任何判斷。
要求:
1.如果當前窗口失去焦點一直執行title閃爍,如果當前處於窗口焦點則什么也不做。
2.當窗口重新獲得焦點時,停止閃爍(退出閃爍循環)。
3.多次調用,閃爍循環本身只應執行一次。也就是說閃爍函數只同時運行一個,否則多個同樣的調用一起執行的話會導致標題閃動異常(快),消耗資源。
//實現標題閃動效果
var flashStep=0; //交替變量
var flashTitleRun = false; //是否正在執行
var normalTitle = "正常顯示的標題";
function flashTitle()
{
//僅窗口不在焦點時閃爍title,回到焦點時停止閃爍並將title恢復正常
if(isWindowFocus){//當前處於焦點
document.title=normalTitle;
flashTitleRun = false;
return;//退出循環
}
flashTitleRun = true;
flashStep++;
if (flashStep==3) {flashStep=1;}
if (flashStep==1) {document.title="【您有新的消息】";}
if (flashStep==2) {document.title="【 】";}
setTimeout("flashTitle()",500); //循環
}
//調用這個執行標題閃爍,而不是直接調用flashTitle,保證多次調用只會執行一次。
function doFlashTitle(){
if(!flashTitleRun)//沒有執行時,才執行
flashTitle();
}
四、小結
title閃爍並不難,但跨瀏覽器的焦點判斷的問題比較多,IE非常詭異。參考資料都是焦點判斷方面的。
只能判斷出窗口焦點是否激活,沒有辦法判斷窗口對人是不是可見的。
在js中調用window.focus()方法,窗口到底會不會被激活是完全不可靠的。而在IE上執行此方法,不管窗口是否激活了,都會導致focus事件的觸發,使得上述的判斷方法認為已經獲得焦點了,但其實沒有。所以最好就不要再使用window或dom的focus方法,以免干擾判斷。而非IE瀏覽器正常,只有窗口確實被激活了才觸發focus事件。
