一、原因
最近公司的一个web项目需要在关闭网页窗口的时候对一些资源做处理,必须判断是刷新还是关闭,这很苦逼,造成必须做判断的问题是由miniUI的一个实时编辑grid控件引起的,因为表格控件在编辑,新增记录的时候,触发了reload的事件,UI底层可能做得不好,这些操作都会触发onbeforeunload
事件里的刷新
,但是由于控件上的耦合性问题,不能不使用miniUI控件,问题只能去解决和规避掉。
二、分析
我的系统里能触发onbeforeunload
事件的有以下:
1、F5刷新
2、Ctrl+R刷新
3、miniUI表格的增删改
4、关闭窗口(这个才是真正想要的)
这四个行为都会触发onbeforeunload
事件,现在我必须获取到第四个动作,也就是关闭窗口。
查询相关的onbeforeunload
浏览器触发:
关闭浏览器窗口
通过地址栏或收藏夹前往其他页面的时候
点击返回,前进,刷新,主页其中一个的时候
点击 一个前往其他页面的url连接的时候
调用以下任意一个事件的时候:
click,document write,document open,document close,window close,window navigate,window NavigateAndFind,location,replace,location reload,form submit
当用window open打开一个页面,并把本页的window的名字传给要打开的页面的时候。
重新赋予location.href的值的时候
通过input type=”submit”按钮提交一个具有指定action的表单的时候
可以用在以下元素:BODY, FRAMESET, window
平台支持:IE4+/Win, Mozilla 1.7a+, Netscape 7.2+, Firefox0.9+
其实真正做到判断触发onbeforeunload事件
的话是不可能的,因为没有放出相关的接口,做不了判断,网上可能出现过类似下边判断刷新还是关闭的判断方式:
window.onbeforeunload=function(e){
//获取事件鼠标的位置
var n = window.event.screenX - window.screenLeft;
//获取浏览器界面可活动的窗口宽度(50是右上角关闭按钮的宽度)
var b = n > document.documentElement.scrollWidth-50;
//window.event.clientY表示事件的y值(鼠标)
//window.event.altKey表示是否按下列alt键(alt+F4)
if(b && window.event.clientY < 0 || window.event.altKey)
{
alert("是关闭而非刷新");
window.event.returnValue ="是否要离开此页面?";
}else{
alert("是刷新而非关闭");
}
}
从以上代码看,远远不能满足我系统里边出现的情况,miniUI增删改都会触发,Ctrl+R也会触发刷新,还有一个特别大的漏洞是,当你鼠标放在关闭按钮上的时候,同时按下F5刷新页面,代码会误认为是关闭。
最后本人解决的方法是,系统里边禁止掉刷新,用户不能通过键盘刷新页面
$(document).keydown(function () {
if ((event.keyCode == 116) || //屏蔽 F5 刷新键
(event.ctrlKey && event.keyCode == 82)) { //Ctrl + R
event.keyCode = 0;
event.returnValue = false;
}
});
然后使用此段代码:
window.onbeforeunload=function(e){
//window.event.clientY < 0表示鼠标已经离开了document的区域
if(window.event.clientY < 0 || window.event.altKey)
{
alert("是关闭而非刷新");
window.event.returnValue ="您是否要离开此页面?";
}else{
alert("是刷新而非关闭");
}
}
window.event.clientY < 0
表示鼠标已经离开了document的区域,如图:
红色区域,就是window.event.clientY < 0的情况,蓝色的是>=0
由于我禁用了键盘的刷新,目前只能通过鼠标操作刷新,鼠标点击刷新或者连接其他关闭窗口时,这时候window.event.clientY < 0
,此时就认为是离开本窗口页面,就认为是关闭了。(和上边说的一样,我的任务仅是规避掉miniUI表格增删改触发onbeforeunload
事件的情况,此处的刷新我认为是关闭,因为已经重新刷新系统里,就相当于重新打开页面一个道理。
以上的情况对我是完美了,其实我的系统窗口是通过window.open弹窗出来的,弹窗出来不会有任何刷新按钮,在IE下可以做到没有地址栏和其他状态栏,谷歌下仅有地址栏,但是地址栏是不可编辑的,也没有刷新按钮,所以,问题就解决了。
接下来是关闭时做的代码操作:
var bCloseFlag=false;//关闭窗口标志位
window.onbeforeunload=function(e){
//一下是判断onbeforeunload是关闭还是刷新的情况
var n = window.event.screenX - window.screenLeft;
if(window.event.clientY < 0 || window.event.altKey)
{
// alert("是关闭而非刷新");
window.event.returnValue ="是否离开页面?";
bCloseFlag=true;
}else{
// alert("是刷新而非关闭");
}
}
//关闭浏览器的时候释放资源
window.onunload = function() {
if (bCloseFlag) {
try{
if(window.alarmConfirmChildWin){
window.alarmConfirmChildWin.close();
}
if(window.showPicChildWin){
window.showPicChildWin.close();
}
//释放所有的资源
//**此处做相关的关闭窗口后的代码**
}catch(e){}finally{}
}
}
三、结论
区分onbeforeunload事件是刷新还是关闭实际上是不可能的,要做到如上我的情况,如要满足三个:
1、系统窗口使用window.open弹窗出来,禁止了所有的按钮和状态栏和地址栏等(刷新按钮,主页按钮等都不会显示),这种情况估计很多系统不会用;
2、代码禁止一切用户刷新操作,比如Ctrl+R
和F5
3、使用代码即可判断if(window.event.clientY < 0 || window.event.altKey)
是关闭的情况