2011年10月16日星期日

浏览器窗口标题栏闪烁通知

对于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事件。


参考资料:

4 条评论:

匿名 说...

[url=http://buyaccutaneorderpillsonline.com/#3170]buy accutane[/url] - buy accutane , http://buyaccutaneorderpillsonline.com/#12883 generic accutane

匿名 说...

[url=http://buyaccutaneorderpillsonline.com/#794]generic accutane[/url] - accutane no prescription , http://buyaccutaneorderpillsonline.com/#6571 cheap accutane

匿名 说...

[url=http://buyaccutaneorderpillsonline.com/#18242]buy cheap accutane[/url] - buy cheap accutane , http://buyaccutaneorderpillsonline.com/#14487 accutane without prescription

匿名 说...

[url=http://buyonlinelasixone.com/#1713]buy lasix online[/url] - generic lasix , http://buyonlinelasixone.com/#10416 cheap lasix