研究界别onbeforeunload事件是刷新还是关闭

研究区分onbeforeunload事件是刷新还是关闭

一、原因

最近公司的一个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

研究界别onbeforeunload事件是刷新还是关闭

由于我禁用了键盘的刷新,目前只能通过鼠标操作刷新,鼠标点击刷新或者连接其他关闭窗口时,这时候window.event.clientY < 0,此时就认为是离开本窗口页面,就认为是关闭了。(和上边说的一样,我的任务仅是规避掉miniUI表格增删改触发onbeforeunload事件的情况,此处的刷新我认为是关闭,因为已经重新刷新系统里,就相当于重新打开页面一个道理。

以上的情况对我是完美了,其实我的系统窗口是通过window.open弹窗出来的,弹窗出来不会有任何刷新按钮,在IE下可以做到没有地址栏和其他状态栏,谷歌下仅有地址栏,但是地址栏是不可编辑的,也没有刷新按钮,所以,问题就解决了。

研究界别onbeforeunload事件是刷新还是关闭

接下来是关闭时做的代码操作:

    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+RF5
3、使用代码即可判断if(window.event.clientY < 0 || window.event.altKey)是关闭的情况